SpringMVC第六篇【校验、统一处理异常】

Validation

在咱们的Struts2中,咱们是继承ActionSupport来实现校验的…它有两种方式来实现校验的功能css

  • 手写代码
  • XML配置
    • 这两种方式也是能够特定处理方法或者整个Action的

而SpringMVC使用JSR-303(javaEE6规范的一部分)校验规范,springmvc使用的是Hibernate Validator(和Hibernate的ORM无关)html

快速入门

导入jar包前端

这里写图片描述

配置校验器java

 <!-- 校验器 --> <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> <!-- 校验器 --> <property name="providerClass" value="org.hibernate.validator.HibernateValidator" /> <!-- 指定校验使用的资源文件,若是不指定则默认使用classpath下的ValidationMessages.properties --> <property name="validationMessageSource" ref="messageSource" /> </bean> 

错误信息的校验文件配置web

<!-- 校验错误信息配置文件 -->
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <!-- 资源文件名 -->
        <property name="basenames">
            <list>
                <value>classpath:CustomValidationMessages</value>
            </list>
        </property>
        <!-- 资源文件编码格式 -->
        <property name="fileEncodings" value="utf-8" />
        <!-- 对资源文件内容缓存时间,单位秒 -->
        <property name="cacheSeconds" value="120" />
    </bean>

添加到自定义参数绑定的WebBindingInitializer中spring

<!-- 自定义webBinder -->
    <bean id="customBinder" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
        <!-- 配置validator -->
        <property name="validator" ref="validator" />
    </bean>

最终添加到适配器中缓存

<!-- 注解适配器 -->
    <bean  class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <!-- 在webBindingInitializer中注入自定义属性编辑器、自定义转换器 -->
        <property name="webBindingInitializer" ref="customBinder"></property>
    </bean>

建立CustomValidationMessages配置文件markdown

这里写图片描述

定义规则mvc

package entity;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Date;

public class Items {
    private Integer id;

    //商品名称的长度请限制在1到30个字符
    @Size(min=1,max=30,message="{items.name.length.error}")
    private String name;

    private Float price;

    private String pic;

    //请输入商品生产日期
    @NotNull(message="{items.createtime.is.notnull}")
    private Date createtime;

    private String detail;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name == null ? null : name.trim();
    }

    public Float getPrice() {
        return price;
    }

    public void setPrice(Float price) {
        this.price = price;
    }

    public String getPic() {
        return pic;
    }

    public void setPic(String pic) {
        this.pic = pic == null ? null : pic.trim();
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public String getDetail() {
        return detail;
    }

    public void setDetail(String detail) {
        this.detail = detail == null ? null : detail.trim();
    }
}

测试:app

 <%-- Created by IntelliJ IDEA. User: ozc Date: 2017/8/11 Time: 9:56 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>测试文件上传</title> </head> <body> <form action="${pageContext.request.contextPath}/validation.action" method="post" > 名称:<input type="text" name="name"> 日期:<input type="text" name="createtime"> <input type="submit" value="submit"> </form> </body> </html> 

Controller须要在校验的参数上添加@Validation注解…拿到BindingResult对象…

@RequestMapping("/validation")
    public void validation(@Validated Items items, BindingResult bindingResult) {

        List<ObjectError> allErrors = bindingResult.getAllErrors();
        for (ObjectError allError : allErrors) {
            System.out.println(allError.getDefaultMessage());
        }

    }

因为我在测试的时候,已经把日期转换器关掉了,所以提示了字符串不能转换成日期,可是名称的校验已是出来了…

这里写图片描述


分组校验

分组校验其实就是为了咱们的校验更加灵活,有的时候,咱们并不须要把咱们当前配置的属性都进行校验,而须要的是当前的方法仅仅校验某些的属性。那么此时,咱们就能够用到分组校验了…

步骤:

  • 定义分组的接口【主要是标识】
  • 定于校验规则属于哪一各组
  • 在Controller方法中定义使用校验分组

这里写图片描述

这里写图片描述

这里写图片描述


统一异常处理

在咱们以前SSH,使用Struts2的时候也配置过统一处理异常…

当时候是这么干的:

  • 在service层中自定义异常
  • 在action层也自定义异常
  • 对于Dao层的异常咱们先无论【由于咱们管不着,dao层的异常太致命了】
  • service层抛出异常,Action把service层的异常接住,经过service抛出的异常来判断是否让请求经过
  • 若是不经过,那么接着抛出Action异常
  • 在Struts的配置文件中定义全局视图,页面显示错误信息

详情可看:http://blog.csdn.net/hon_3y/article/details/72772559

那么咱们此次的统一处理异常的方案是什么呢????

咱们知道Java中的异常能够分为两类

  • 编译时期异常
  • 运行期异常

对于运行期异常咱们是没法掌控的,只能经过代码质量、在系统测试时详细测试等排除运行时异常

而对于编译时期的异常,咱们能够在代码手动处理异常能够try/catch捕获,能够向上抛出。

咱们能够换个思路,自定义一个模块化的异常信息,好比:商品类别的异常

public class CustomException extends Exception {

    //异常信息
    private String message;

    public CustomException(String message){
        super(message);
        this.message = message;

    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }



}

咱们在查看Spring源码的时候发现:前端控制器DispatcherServlet在进行HandlerMapping、调用HandlerAdapter执行Handler过程当中,若是遇到异常,在系统中自定义统一的异常处理器,写系统本身的异常处理代码。。

这里写图片描述

这里写图片描述

咱们也能够学着点,定义一个统一的处理器类来处理异常…

定义统一异常处理器类

public class CustomExceptionResolver implements HandlerExceptionResolver {

    //前端控制器DispatcherServlet在进行HandlerMapping、调用HandlerAdapter执行Handler过程当中,若是遇到异常就会执行此方法
    //handler最终要执行的Handler,它的真实身份是HandlerMethod
    //Exception ex就是接收到异常信息
    @Override
    public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex) {
        //输出异常
        ex.printStackTrace();

        //统一异常处理代码
        //针对系统自定义的CustomException异常,就能够直接从异常类中获取异常信息,将异常处理在错误页面展现
        //异常信息
        String message = null;
        CustomException customException = null;
        //若是ex是系统 自定义的异常,直接取出异常信息
        if(ex instanceof CustomException){
            customException = (CustomException)ex;
        }else{
            //针对非CustomException异常,对这类从新构形成一个CustomException,异常信息为“未知错误”
            customException = new CustomException("未知错误");
        }

        //错误 信息
        message = customException.getMessage();

        request.setAttribute("message", message);


        try {
            //转向到错误 页面
            request.getRequestDispatcher("/WEB-INF/jsp/error.jsp").forward(request, response);
        } catch (ServletException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return new ModelAndView();
    }

}

配置统一异常处理器

<!-- 定义统一异常处理器 -->
    <bean class="cn.itcast.ssm.exception.CustomExceptionResolver"></bean>

这里写图片描述

相关文章
相关标签/搜索