Spring MVC 数据绑定流程分析
1. 数据绑定流程原理★
① Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创建 DataBinder 实例对象
② DataBinder 调用装配在 Spring MVC 上下文中的 ConversionService 组件进行数据类型转换、数据格式化工作。将 Servlet 中的请求信息填充到入参对象中
③ 调用 Validator 组件对已经绑定了请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果 BindingData 对象
④ Spring MVC 抽取 BindingResult 中的入参对象和校验错误对象,将它们赋给处理方法的响应入参
Spring MVC 通过反射机制对目标处理方法进行解析,将请求消息绑定到处理方法的入参中。数据绑定的核心部件是 DataBinder,运行机制如下:
binderFactory
//绑定器工厂根据当前请求,其他信息;创建出数据绑定器;
//数据绑定器负责将请求中的数据绑定到pojo中
WebDataBinder binder = binderFactory.createBinder(request, attribute, name);
if (binder.getTarget() != null) {
//数据绑定期间进行类型转换以及格式化工作
bindRequestParameters(binder, request);
//数据校验:email;birth;BindingResult组件中会封装错误信息;
validateIfApplicable(binder, parameter);
//数据校验错误信息处理
if (binder.getBindingResult().hasErrors()) {
//如果出错有处理
if (isBindExceptionRequired(binder, parameter)) {
\\parameter指目标方法正在处理的当前参数 saveEmp(Employee emp)
protected boolean isBindExceptionRequired(WebDataBinder binder, MethodParameter parameter) {
int i = parameter.getParameterIndex();//获取参数索引
Class<?>[] paramTypes = parameter.getMethod().getParameterTypes();//获取当前方法所有参数的参数类型 //如果下一个参数是Errors旗下的,就返回成功;否则就是没人处理;
boolean hasBindingResult =
(paramTypes.length > (i + 1) && Errors.class.isAssignableFrom(paramTypes[i + 1])); return !hasBindingResult;
} //如果没人处理就抛异常
throw new BindException(binder.getBindingResult());
}
}
}
SpringMVC默认使用的是DefaultFormattingCOnversionService
ConversionService converters = 负责数据类型转换及格式化;都是里面的每一个转换器负责工作;
@org.springframework.format.annotation.DateTimeFormat java.lang.Long -> java.lang.String: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@7c515e0,@org.springframework.format.annotation.NumberFormat java.lang.Long -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@592e7da0
@org.springframework.format.annotation.DateTimeFormat java.time.LocalDate -> java.lang.String: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@7bfa429f,java.time.LocalDate -> java.lang.String : org.springframework.format.datetime.standard.TemporalAccessorPrinter@34d07c25
@org.springframework.format.annotation.DateTimeFormat java.time.LocalDateTime -> java.lang.String: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@7bfa429f,java.time.LocalDateTime -> java.lang.String : org.springframework.format.datetime.standard.TemporalAccessorPrinter@2fbd9c99
@org.springframework.format.annotation.DateTimeFormat java.time.LocalTime -> java.lang.String: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@7bfa429f,java.time.LocalTime -> java.lang.String : org.springframework.format.datetime.standard.TemporalAccessorPrinter@317cb8e5
@org.springframework.format.annotation.DateTimeFormat java.time.OffsetDateTime -> java.lang.String: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@7bfa429f,java.time.OffsetDateTime -> java.lang.String : org.springframework.format.datetime.standard.TemporalAccessorPrinter@4c6fb0c7
@org.springframework.format.annotation.DateTimeFormat java.time.OffsetTime -> java.lang.String: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@7bfa429f,java.time.OffsetTime -> java.lang.String : org.springframework.format.datetime.standard.TemporalAccessorPrinter@616a3ae3
@org.springframework.format.annotation.DateTimeFormat java.time.ZonedDateTime -> java.lang.String: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@7bfa429f,java.time.ZonedDateTime -> java.lang.String : org.springframework.format.datetime.standard.TemporalAccessorPrinter@48de4b92
@org.springframework.format.annotation.DateTimeFormat java.util.Calendar -> java.lang.String: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@7c515e0
@org.springframework.format.annotation.DateTimeFormat java.util.Date -> java.lang.String: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@7c515e0
@org.springframework.format.annotation.NumberFormat java.lang.Double -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@592e7da0
@org.springframework.format.annotation.NumberFormat java.lang.Float -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@592e7da0
@org.springframework.format.annotation.NumberFormat java.lang.Integer -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@592e7da0
@org.springframework.format.annotation.NumberFormat java.lang.Short -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@592e7da0
@org.springframework.format.annotation.NumberFormat java.math.BigDecimal -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@592e7da0
@org.springframework.format.annotation.NumberFormat java.math.BigInteger -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@592e7da0
java.lang.Boolean -> java.lang.String : org.springframework.core.convert.support.ObjectToStringConverter@1ae88e8d
java.lang.Character -> java.lang.Number : org.springframework.core.convert.support.CharacterToNumberFactory@15499bcc
java.lang.Character -> java.lang.String : org.springframework.core.convert.support.ObjectToStringConverter@314796e3
java.lang.Enum -> java.lang.String : org.springframework.core.convert.support.EnumToStringConverter@67a9e5f5
java.lang.Long -> java.util.Calendar : org.springframework.format.datetime.DateFormatterRegistrar$LongToCalendarConverter@2425e96f
java.lang.Long -> java.util.Date : org.springframework.format.datetime.DateFormatterRegistrar$LongToDateConverter@37be4c53
java.lang.Number -> java.lang.Character : org.springframework.core.convert.support.NumberToCharacterConverter@64e80876
java.lang.Number -> java.lang.Number : org.springframework.core.convert.support.NumberToNumberConverterFactory@24d24a7d
java.lang.Number -> java.lang.String : org.springframework.core.convert.support.ObjectToStringConverter@2d2b9f78
java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.lang.Long: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@7c515e0,java.lang.String -> @org.springframework.format.annotation.NumberFormat java.lang.Long: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@592e7da0
java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.time.LocalDate: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@7bfa429f,java.lang.String -> java.time.LocalDate: org.springframework.format.datetime.standard.TemporalAccessorParser@1b95054a
java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.time.LocalDateTime: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@7bfa429f,java.lang.String -> java.time.LocalDateTime: org.springframework.format.datetime.standard.TemporalAccessorParser@1cb17371
java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.time.LocalTime: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@7bfa429f,java.lang.String -> java.time.LocalTime: org.springframework.format.datetime.standard.TemporalAccessorParser@183beaef
java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.time.OffsetDateTime: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@7bfa429f,java.lang.String -> java.time.OffsetDateTime: org.springframework.format.datetime.standard.TemporalAccessorParser@5b5278c0
java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.time.OffsetTime: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@7bfa429f,java.lang.String -> java.time.OffsetTime: org.springframework.format.datetime.standard.TemporalAccessorParser@43da3826
java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.time.ZonedDateTime: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@7bfa429f,java.lang.String -> java.time.ZonedDateTime: org.springframework.format.datetime.standard.TemporalAccessorParser@ff5bcf4
java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.util.Calendar: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@7c515e0
java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.util.Date: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@7c515e0
java.lang.String -> @org.springframework.format.annotation.NumberFormat java.lang.Double: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@592e7da0
java.lang.String -> @org.springframework.format.annotation.NumberFormat java.lang.Float: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@592e7da0
java.lang.String -> @org.springframework.format.annotation.NumberFormat java.lang.Integer: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@592e7da0
java.lang.String -> @org.springframework.format.annotation.NumberFormat java.lang.Short: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@592e7da0
java.lang.String -> @org.springframework.format.annotation.NumberFormat java.math.BigDecimal: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@592e7da0
java.lang.String -> @org.springframework.format.annotation.NumberFormat java.math.BigInteger: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@592e7da0
java.lang.String -> java.lang.Boolean : org.springframework.core.convert.support.StringToBooleanConverter@1795e212
java.lang.String -> java.lang.Character : org.springframework.core.convert.support.StringToCharacterConverter@7f0a5c2
java.lang.String -> java.lang.Enum : org.springframework.core.convert.support.StringToEnumConverterFactory@3ee79e1e
java.lang.String -> java.lang.Number : org.springframework.core.convert.support.StringToNumberConverterFactory@35ac0acf
java.lang.String -> java.time.Instant: org.springframework.format.datetime.standard.InstantFormatter@72824112
java.lang.String -> java.util.Locale : org.springframework.core.convert.support.StringToLocaleConverter@5f141e60
java.lang.String -> java.util.Properties : org.springframework.core.convert.support.StringToPropertiesConverter@34316a3
java.lang.String -> java.util.UUID : org.springframework.core.convert.support.StringToUUIDConverter@54f52170
java.time.Instant -> java.lang.String : org.springframework.format.datetime.standard.InstantFormatter@72824112
java.time.ZoneId -> java.util.TimeZone : org.springframework.core.convert.support.ZoneIdToTimeZoneConverter@309ed382
java.util.Calendar -> java.lang.Long : org.springframework.format.datetime.DateFormatterRegistrar$CalendarToLongConverter@783071dc
java.util.Calendar -> java.util.Date : org.springframework.format.datetime.DateFormatterRegistrar$CalendarToDateConverter@18da2904
java.util.Date -> java.lang.Long : org.springframework.format.datetime.DateFormatterRegistrar$DateToLongConverter@3a5ea3fa
java.uti...
ConversionService 是 Spring 类型转换体系的核心接口。
可以利用 ConversionServiceFactoryBean 在 Spring 的 IOC 容器中定义一个 ConversionService.
Spring 将自动识别出 IOC 容器中的 ConversionService,并在 Bean 属性配置及
Spring MVC 处理方法入参绑定等场合使用它进行数据的转换
可通过 ConversionServiceFactoryBean 的 converters 属性注册自定义的类型转换器
</bean>
<bean id="conversionServiceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
<!-- 我们的类型转换器要赋值给他 -->
<property name="converters">
<!-- 给set赋值 -->
<set>
<ref bean="myStringToEmployeeConvertor"/>
</set>
</property>
</bean>
<!-- 静态资源被SpringMVC拦截到了,所以jquery 404 -->
<!-- SpringMVC处理不了的资源,现在交给tomcat的DefaultServlet;
default-servlet-name:
default-servlet-name="default";如果只有它,动态资源就完蛋了;
-->
<!--静态资源访问ok -->
<mvc:default-servlet-handler/>
<!--动态资源就能访问;开挂版的mvc模式 -->
<!-- 转换器采用自定义的 -->
<mvc:annotation-driven conversion-service="conversionServiceFactoryBean"></mvc:annotation-driven>
1) Spring 支持的转换器类型
Spring 定义了 3 种类型的转换器接口,实现任意一个转换器接口都可以作为自定义转换器注册到 ConversionServiceFactoryBean 中:
Converter<S,T>:将 S 类型对象转为 T 类型对象
ConverterFactory:将相同系列多个 “同质” Converter 封装在一起。如果希望将一种类型的对象转换为另一种类型及其子类的对象(例如将 String 转换为 Number 及 Number 子类(Integer、Long、Double 等)对象)可使用该转换器工厂类
GenericConverter:会根据源类对象及目标类对象所在的宿主类中的上下文信息进行类型转换
public class MyStringToEmployeeConvertor implements Converter<String, Employee>{
@Autowired
DepartmentDao dao;
@Override
public Employee convert(String source) {
// TODO Auto-generated method stub
Employee employee = new Employee(null, "haha", "hahah", 0,null);
System.out.println("MyStringToEmployeeConvertor开始工作啦......."+source);
//admin-aaa@qq.com-0-101
if(!"".equals(source)&&source!=null){
//把字符串按照"-"进行分割,得到的数据保存在数组中
String[] split = source.split("-");
employee.setLastName(split[0]);
employee.setEmail(split[1]);
employee.setGender(Integer.parseInt(split[2]));
Department department = dao.getDepartment(Integer.parseInt(split[3]));
employee.setDepartment(department);
}
return employee;
}
hibernate-validator-5.0.0.CR2.jar
hibernate-validator-annotation-processor-5.0.0.CR2.jar
classmate-0.8.0.jar
jboss-logging-3.1.1.GA.jar
validation-api-1.1.0.CR1.jar
2、加注解
给需要校验的javaBean属性上加注解;给javaBean加校验注解
private Integer id;
@NotEmpty
@Length(min=5,max=15)
private String lastName;
private String email;
//1 male, 0 female
private Integer gender=1;
/**
* pattern:指定日期格式
*/
@DateTimeFormat(pattern="yyyy-MM-dd")
@Past
private Date birthDay;
3、告诉SpringMVC这个javaBean需要校验;@Valid
一定注意:所有的ModelAttribute要全部统一;
* 在员工更新操作之前;在点击提交之前,提前运行查出数据
* 校验成功失败的信息,以及校验失败后怎么做?
* 给参数后面紧跟一个Errors、或者BindingResult
public String empUpdate(@Valid @ModelAttribute("employee") Employee employee,Errors errors){
//后端把错误显示出来
if(errors.getFieldErrorCount()>0){
System.out.println("类型转换出错误了");
//1、获取产生的所有的错误
List<FieldError> fieldErrors = errors.getFieldErrors();
for(FieldError fieldError:fieldErrors){
System.out.println(fieldError.getField()+"-"+fieldError.getDefaultMessage());
}
return "/edit";
}
System.out.println(employee);
employeeDao.save(employee);
return "redirect:/emps";
}
4 在页面上显示错误
Spring MVC 除了会将表单/命令对象的校验结果保存到对应的 BindingResult 或 Errors 对象中外,还会将所有校验结果保存到“隐含模型”
即使处理方法的签名中没有对应于表单/命令对象的结果入参,校验结果也会保存在 “隐含对象” 中。
隐含模型中的所有数据最终将通过 HttpServletRequest 的属性列表暴露给 JSP 视图对象,因此在 JSP 中可以获取错误信息
在 JSP 页面上可通过 <form:errors path=“userName”> 显示错误消息
<form:form action="${ ctp}/emp/${employee.id }" method="post" modelAttribute="employee" >
birthDay:<form:input path="birthDay"/><form:errors path="birthDay"/><br/>
email:<form:input path="email"/><form:errors path="email"/><br>
男:<form:radiobutton path="gender" value="1"/>
女:<form:radiobutton path="gender" value="0"/><br/>
<!-- SpringMvc习惯于直接用参数,而不是通过类。参数获取 -->
department:<form:select path="department.id"
items="${depts}"
itemLabel="departmentName"
itemValue="id"
></form:select><br/>
<!-- 浏览器 form 表单只支持 GET 与 POST 请求,而DELETE、PUT 等 method 并不支持,
Spring3.0 添加了一个过滤器,可以将这些请求转换为标准的 http 方法,使得支持 GET、POST、PUT 与 DELETE 请求。
所以要添加name="_method" value="PUT",过滤器根据这个进行区分
-->
<input type="hidden" name="_method" value="PUT" >
<input type="hidden" name="id" value="${employee.id}">
<input type="submit" value="更新">
</form:form>
5. 提示消息的国际化
每个属性在数据绑定和数据校验发生错误时,都会生成一个对应的 FieldError 对象。
当一个属性校验失败后,校验框架会为该属性生成 4 个消息代码,这些代码以校验注解类名为前缀,结合 modleAttribute、属性名及属性类型名生成多个对应的消息代码:例如 User 类中的 password 属性标注了一个 @Pattern 注解,当该属性值不满足 @Pattern 所定义的规则时, 就会产生以下 4 个错误代码:
Pattern.user.password
Pattern.password
Pattern.java.lang.String
Pattern
当使用 Spring MVC 标签显示错误消息时, Spring MVC 会查看 WEB 上下文是否装配了对应的国际化消息,如果没有,则显示默认的错误消息,否则使用国际化消息。
若数据类型转换或数据格式转换时发生错误,或该有的参数不存在,或调用处理方法时发生错误,都会在隐含模型中创建错误消息。其错误代码前缀说明如下:
required:必要的参数不存在。如 @RequiredParam(“param1”) 标注了一个入参,但是该参数不存在
typeMismatch:在数据绑定时,发生数据类型不匹配的问题
methodInvocation:Spring MVC 在调用处理方法时发生了错误
1)、创建所有错误消息提示的国际化文件
Field error in object 'employee' on field 'lastName': rejected value [E-AA];
codes
[
Length.employee.lastName,//校验注解类名.modleAttribute(保存隐含模型)的key.属性
Length.lastName,//校验注解类名.属性
Length.java.lang.String,//校验注解类名.属性类型
Length//校验注解类名
];//4种错误代码;任何字段错误都会有他的错误代码;国际化文件中的key就是要写这个错误代码;
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [employee.lastName,lastName]; arguments []; default message [lastName],15,5]; default message [length must be between 5 and 15]
<!-- SpringMVC管理国际化资源文件 -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="error"></property>
</bean>
3)、SpringMVC:<form:errors path="fieldName">自动的按照国际化要求取出错误信息;
https://www.cnblogs.com/limingxian537423/p/7277538.html
https://www.jianshu.com/p/a707acd7eb3a
http://www.imooc.com/article/263093
Spring MVC 数据绑定流程分析的更多相关文章
- Spring MVC启动流程分析
本文是Spring MVC系列博客的第一篇,后续会汇总成贴子. Spring MVC是Spring系列框架中使用频率最高的部分.不管是Spring Boot还是传统的Spring项目,只要是Web项目 ...
- Spring MVC 数据绑定流程
DataBinder 数据绑定 入参,校验,格式化, ConversionService: 进行数据类型转换和数据格式化 Validators 进行数据合法性的校验, 把结果放入BindingResu ...
- spring mvc处理流程概述
大部分Java应用都是Web应用,展现层是Web应用不可忽略的重要环节.Spring为展现层提供了一个优秀的Web框架-Spring MVC.和众多其他Web框架一样,它基于MVC设计理念,此外,它采 ...
- 从一个简单案例上手Spring MVC,同时分析Spring MVC面试问题
很多公司都会用Spring MVC,而且初级程序员在面试时,一定会被问到这方面的问题,所以这里我们来通过一个简单的案例来分析Spring MVC,事实上,我们在培训中就用这个举例,很多零基础的程序员能 ...
- 精尽Spring MVC源码分析 - 寻找遗失的 web.xml
该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...
- 精尽Spring MVC源码分析 - 一个请求的旅行过程
该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...
- 精尽Spring MVC源码分析 - HandlerAdapter 组件(四)之 HandlerMethodReturnValueHandler
该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...
- Spring mvc源码分析系列--前言
Spring mvc源码分析系列--前言 前言 距离上次写文章已经过去接近两个月了,Spring mvc系列其实一直都想写,但是却不知道如何下笔,原因有如下几点: 现在项目开发前后端分离的趋势不可阻挡 ...
- Spring mvc源码分析系列--Servlet的前世今生
Spring mvc源码分析系列--Servlet的前世今生 概述 上一篇文章Spring mvc源码分析系列--前言挖了坑,但是由于最近需求繁忙,一直没有时间填坑.今天暂且来填一个小坑,这篇文章我们 ...
随机推荐
- C#中字段、属性、只读、构造函数赋值、反射赋值的相关
C#中字段.属性和构造函数赋值的问题 提出问题 首先提出几个问题: 1.如何实现自己的注入框架? 2.字段和自动属性的区别是什么? 3.字段和自动属性声明时的直接赋值和构造函数赋值有什么区别? 4.为 ...
- WP8.1StoreApp(WP8.1RT)---SystemTray的变化
原Microsoft.Phone.Shell中的SystemTray,已经改到Windows.UI.ViewManagement中StatusBar了. 只能在代码中设置相关属性. 如: 1 2 3 ...
- win32拖拽编程
本文由作者邹启文授权网易云社区发布. 在邮箱大师PC版中,我们需要实现一个功能:账号和邮件夹拖拽排序. 准备 封装win32 API.我们使用到的API有, ImageList_Create.Imag ...
- 知物由学 | AI网络安全实战:生成对抗网络
本文由 网易云发布. “知物由学”是网易云易盾打造的一个品牌栏目,词语出自汉·王充<论衡·实知>.人,能力有高下之分,学习才知道事物的道理,而后才有智慧,不去求问就不会知道.“知物由学” ...
- C# 收银机顾显(客显)及打印小票(58热敏打印机)
最近做winform收银机,设计顾显及打印小票总结. 1.顾显(串口COM1) 只涉及到总计,所以只是简单的功能. public static ClientDisplayResult Display( ...
- ISE14.7生成.bit文件和mcs文件
1.FPGA bit文件加载步骤(加载到FPGA的RAM中,用于在线调试,掉电丢失) 第一步:选择Tools->IMPCAT->选择OK: 第二步:双击Boundary Scan-> ...
- Python 用队列实现多线程并发
# Python queue队列,实现并发,在网站多线程推荐最后也一个例子,比这货简单,但是不够规范 # encoding: utf-8 __author__ = 'yeayee.com' # 由本站 ...
- 脚本:定时释放 Linux/CentOS 缓存【转载自:杭州山不高】
定时释放Linux/CentOS缓存的脚本(yl_dropcaches)如下: #!/bin/bash used=`free -m | awk 'NR==2' | awk '{print $3}'` ...
- [JS] 气球放气效果
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name ...
- VMware Workstation 14 pro License Keys
AC5XK-0ZD4H-088HP-9NQZV-ZG2R4 CG54H-D8D0H-H8DHY-C6X7X-N2KG6 ZC3WK-AFXEK-488JP-A7MQX-XL8YF ZC5XK-A6E0 ...