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


tags: SpringMVC


Validation

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

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

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

快速入门

导入jar包

配置校验器



	
	<!-- 校验器 -->
	<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>


复制代码

错误信息的校验文件配置


	<!-- 校验错误信息配置文件 -->
	<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中


	<!-- 自定义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配置文件

定义规则

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();
    }
}

复制代码

测试:




<%--
  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的配置文件中定义全局视图,页面显示错误信息

详情可看:blog.csdn.net/hon_3y/arti…

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

我们知道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>
复制代码

总结#

  • 使用Spring的校验方式就是将要校验的属性前边加上注解声明。
  • 在Controller中的方法参数上加上@Validation注解。那么SpringMVC内部就会帮我们对其进行处理(创建对应的bean,加载配置文件)
  • BindingResult可以拿到我们校验错误的提示
  • 分组校验就是将让我们的校验更加灵活:某方法需要校验这个属性,而某方法不用校验该属性。我们就可以使用分组校验了。
  • 对于处理异常,SpringMVC是用一个统一的异常处理器类的。实现了HandlerExceptionResolver接口。
  • 对模块细分多个异常类,都交由我们的统一异常处理器类进行处理。

如果您觉得这篇文章帮助到了您,可以给作者一点鼓励

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值