勿谓今日不学而有来日,勿谓今年不学而有来年。
日月逝矣,岁不我延。

SSM框架的CURD案例三 JSR303校验与Rest风格的URI

JSR303简介

单纯的前端校验可以通过伪造请求的方式绕过,而造成不可预知的危害,所有后端校验是保证系统安全不可缺少的一环。

JSR 303 – Bean Validation是一个数据验证的规范,2009年11月确定最终方案。Hibernate Validator是Bean Validation的最佳实践。

注解介绍

Bean Validation中的约束

Hibernate Validator附加的约束

依赖

hibernate-validator.jar(与hibernate无关)

<!--hibernate-validator-->
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-validator</artifactId>
  <version>5.4.1.Final</version>
</dependency>

使用

在bean中对属性添加注解

@Pattern是自定义规则,regexp填写正则表达式,注意\转义

//@Email
@Pattern(regexp = "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$",message = "邮箱地址不正确")

在Controller中方法初入参使用@Valid进行校验

/**
 * 保存员工信息
 * @param employee
 * @return
 */
@RequestMapping(value = "/emps",method = RequestMethod.POST)
@ResponseBody
public Message saveEmp(@Valid Employee employee, BindingResult bindingResult){
    Map<String,Object> errorMap=new HashMap<String ,Object>();
     if(bindingResult.hasErrors()){
        List<FieldError> errors= bindingResult.getFieldErrors();
         for (FieldError error : errors) {
             //获取错误字段和信息
             errorMap.put(error.getField(), error.getDefaultMessage());
         }
        return Message.fail().add("errorFields",errorMap);
    }else {
        employeeService.saveEmp(employee);
        return Message.succrss();
    }
}

 

Rest风格的URI

优势

  1. 资源通过URL来指定和操作。
  2. 对资源的操作包括获取、创建、修改和删除,正好对应HTTP协议的GET,POST,PUT和DELETE方法。
  3. 连接是无状态性的。
  4. 能够利用Cache机制来提高性能。”
//查询
@RequestMapping(value = "/emp",method = RequestMethod.GET)
//删除
@RequestMapping(value = "/emp/{ids}",method = RequestMethod.DELETE)
//修改
@RequestMapping(value = "/emp/{empId}",method = RequestMethod.PUT)
//保存
@RequestMapping(value = "/emp",method = RequestMethod.POST)

问题

如果用ajax直接发送PUT请求,在Controller会获取不到表单封装的对象。

分析

Springmvc封装对象的步骤如下:

  • TomCat会把请求体中的数据封装成一个map
  • request.getparameter(“”)时会直接从map中取值
  • Springmvc封装POJO时就是使用request.getparameter(“”)

然而,当TomCat发现请求时PUT时就不会封装Map,自然Springmvc也就获取不到请求值了。

TomCat源码3111行

org.apache.catalina.connector.Request–parseParameters() (3111);

protected String parseBodyMethods = “POST”; //默认位POST请求时才封装

if( !getConnector().isParseBodyMethod(getMethod()) ) {
    success = true;
    return;
}

解决

配置HttpPutFormContentFilter过滤器

<filter>
  <filter-name>HttpPutFormContentFilter</filter-name>
  <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>HttpPutFormContentFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

HttpPutFormContentFilter拦截到put请求后会封装HttpInputMessage对象,然后转换成一个MultiValueMap<String, String>而MultiValueMap<K, V>继承了java的Map;接下来把原来的request和MultValueMap传入HttpPutFormContentRequestWrapper(它重写了getParament方法),返回一个包装过的HttpServletRequest

源码如下:

protected void doFilterInternal(final HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    if (("PUT".equals(request.getMethod()) || "PATCH".equals(request.getMethod())) && this.isFormContentType(request)) {
        HttpInputMessage inputMessage = new ServletServerHttpRequest(request) {
            public InputStream getBody() throws IOException {
                return request.getInputStream();
            }
        };
        MultiValueMap<String, String> formParameters = this.formConverter.read((Class)null, inputMessage);
        HttpServletRequest wrapper = new HttpPutFormContentFilter.HttpPutFormContentRequestWrapper(request, formParameters);
        filterChain.doFilter(wrapper, response);
    } else {
        filterChain.doFilter(request, response);
    }

}

public HttpPutFormContentRequestWrapper(HttpServletRequest request, MultiValueMap<String, String> parameters) {
    super(request);
    this.formParameters = (MultiValueMap)(parameters != null ? parameters : new LinkedMultiValueMap());
}

public String getParameter(String name) {
    String queryStringValue = super.getParameter(name);
    String formValue = (String)this.formParameters.getFirst(name);
    return queryStringValue != null ? queryStringValue : formValue;
}

 

源码:https://github.com/llanc/SSM_CURD

 

赞(1)
未经允许不得转载:喋喋不休 » SSM框架的CURD案例三

评论 抢沙发

评论前必须登录!

 

精品网站

有券无忧电脑壁纸精选