Java框架——SpringMVC(二)

SpringMVC的重定向与转发

1.使用String作为返回值的时候,直接在字符串前添加
redirect:表示当前字符串为重定向的请求路径
forward:表示为转发的请求路径
@Controller
@RequestMapping("/test")
public class MyController {

	@RequestMapping("/register.do")
	public String doSome(String name,int age,Model model) {
		System.out.println("------------");
		//将数据放入Model 中	
		model.addAttribute("name", name);
		model.addAttribute("age", age);
		//重定向到当前处理器的第二个方法中
		return "redirect:other.do";
	}
	@RequestMapping("/other.do")
	public String doOther(Model model) {
		
		return "/welcome.jsp";
	}
}
2.使用ModelAndView作为返回值时使用setViewName方法跳转
mView.setViewName("/welcome.jsp");默认是请求转发
	@RequestMapping("/register.do")
	public ModelAndView doAjax() {
		System.out.println("------------");
		ModelAndView mView = new ModelAndView();
		mView.addObject("name", "zd");
		mView.addObject("age", 23);
		// mView.setViewName("forward:/WEB-INF/jsp/welcome.jsp");
		mView.setViewName("redirect:/welcome.jsp");
		//设置跳转方式为重定向,它会将数据直接拼接在地址栏
		return mView;
	}

处理器方法的参数

处理器方法参数有5类,在系统调用时自动赋值
1.HttpServletRequest
2.HttpServletResponse
3.HttpSession
4.用于承载数据的Model
5.请求中携带的请求参数
@RequestMapping("/register.do")
	public String doSome(HttpServletRequest request,HttpServletResponse response,HttpSession session,Model model,String name,int age) {
		
		return "redirect:other.do";
	}

处理器将返回数据添加到响应中

1)处理器返回一个数值类型的数据到前端
直接在处理器中返回一个数据而不是视图名称
需要在方法上添加@ResponseBody注解将返回的数据放入响应体中
	<script type="text/javascript">
	$(function(){//页面加载后触发以下事件
		$("button").click(function(){//给按钮绑定一个单击事件
			//按钮点击后提交一个AJAX请求
			$.ajax({
				url : "test/register.do",//请求路径
				//请求成功后的回调函数
				success:function(data){
					alert(data);
				}
			})
			
		})
	}
	)
	
	</script>
</head>
<body>
	<button >提交AJAX请求</button>
</body>
接收请求后返回一个数值型对象
@ResponseBody注解将返回的数据放入响应体中,需要注册 MVC注解驱动
	<!-- springMVC.xml注解驱动 -->
	<mvc:annotation-driven />
不再是返回资源视图名称,直接返回数据到前端
@Controller
@RequestMapping("/test")
public class MyController {

	@RequestMapping("/register.do")
	@ResponseBody	//将返回的数据放入响应体中
	public Object doAjax() {
		System.out.println("------------");
		return 123.456;
	}
}
2)返回String类型对象
对于中文的字符串会出现乱码问题
需要在@RequestMapping标签中设置返回结果的类型
produces="text/html;charset=utf-8"
@Controller
@RequestMapping("/test")
public class MyController {
	@RequestMapping(value="/register.do",produces="text/html;charset=utf-8")//设置返回结果的类型
	@ResponseBody //将返回的数据放入响应体中
	public Object doAjax() {
		System.out.println("------------");
		return "abc北京"; //会出现响应的中文乱码,需要在@RequestMapping标签中设置
	}
}
3)返回自定义类型对象
@Controller
@RequestMapping("/test")
public class MyController {
	@RequestMapping("/register.do")
	@ResponseBody //将返回的数据放入响应体中
	public Object doAjax() {
		System.out.println("------------");
		return new Student("张三"23); 
	}
}
前端的回调函数
success:function(data){
	alert(data.name+ "  " + data.age);//将之当做Student对象来使用即可
}
4)返回List对象
	@RequestMapping("/register.do")
	@ResponseBody //将返回的数据放入响应体中
	public Object doAjax() {
		//...
		//...
		return List<Student> student; 
	}
前端接收返回结果的回调函数
success:function(data){
	//这里需要遍历List
	$(data).each(function(index){
	alert(  data[index].name + "  " + data[index].age);
	});
}
5)返回map对象
@RequestMapping("/register.do")
	@ResponseBody
	public Object doAjax() {
		System.out.println("------------");
		Map<String, Student> map = new HashMap<String, Student>();
		Student student = new Student();
		student.setAge(23);
		student.setName("张三");
		map.put("stu", student);
		return map;
	}
回调函数解析结果
success:function(data){
	alert(data.stu.name  + "  " + data.stu.age);
}

JSON与SpringMVC的交互

1.接收json格式的数据
2.返回json格式的数据
<script type="text/javascript">
$(function(){
	var params = '{"id": 1,"name": "商品","price": 99.9,}';
	$.ajax({
		url : "${pageContext.request.contextPath }/json.do",
		data : params,
		contentType : "application/json;charset=UTF-8",//发送数据的格式
		type : "post",//提交方式
		dataType : "json",//回调函数的数据格式
		success : function(data){
			alert(data.name);
		}
		
	});
});
</script>
处理接收json数据并返回json数据
	//json数据交互
	@RequestMapping(value = "/json.do")
	@ResponseBody //将返回数据放入响应体中
	public Article jsonDate(@RequestBody Article article){// 将json数据封装到JavaBean对象中,自动完成json字符串与Java对象间的转换
	//从请求体中获取对象数据		
		System.out.println(article);		
		return article;
	}

SpringMVC的异常处理

SpringMVC对异常处理的方式有3种,处理器方法执行过程中出现的异常
1.使用系统自带的异常处理器
2.使用自定义的异常处理器
3.使用异常注解处理

一,使用系统自带的异常处理器
1)使用系统自带的异常处理器
在springmvc的配置文件中注册这个异常处理器SimpleMappingExceptionResolver
<!-- 组件扫描器 -->
<context:component-scan base-package="com.handlers" />
<!-- MVC注解驱动 -->
<mvc:annotation-driven />
<!-- 异常处理器 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
	<property name="defaultErrorView" value="/errors/error.jsp"></property> 
	<!--定义发生错误时默认跳转的页面-->
	<property name="exceptionAttribute" value="ex"></property> 
	<!--定义发生错误的形参,名称任意,方便获取错误的具体信息-->
</bean>
当发生异常时,异常信息会返回给中央调度器,中央调度器会调用注册的这个异常处理器处理异常
	@RequestMapping("/register.do")
	public void do(String name,int age) throws StudentException {
		System.out.println("------------");
		int i = 3 / 0;//发生异常调用异常处理器
2)发生指定异常时跳转指定的错误页面
public class StudentException extends Exception {
	//自定义异常	
}
public class NameException extends StudentException
public class AgeException extends StudentException
在SpringMVC的配置文件中注册异常处理器
<!-- 组件扫描器 -->
<context:component-scan base-package="com.handlers" />
<!-- MVC注解驱动 -->
<mvc:annotation-driven />
<!-- 异常处理器 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
	<property name="defaultErrorView" value="/errors/error.jsp"></property>
	<property name="exceptionAttribute" value="ex"></property>
	<property name="exceptionMappings">
		<props>
		<!-- 发生指定异常时跳转的异常页面-->
			<prop key="com.exceptions.NameException">/errors/nameErroe.jsp </prop>
			<prop key="com.exceptions.AgeException">/errors/ageError.jsp</prop>
		</props>
	</property>
</bean>
指定异常的抛出
	@RequestMapping("/register.do")
	public ModelAndView doAjax(String name,int age) throws StudentException {
		System.out.println("------------");
		//int a = 3/0;
		if (!"beijing".equals(name)) {
			throw new NameException("名字不正确");
		}
		if (age > 20) {
			throw new AgeException("年龄不正确");
		}
二,自定义异常处理器
需要实现HandlerExceptionResolver接口
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {
	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
			Exception ex) {
		ModelAndView mv = new ModelAndView();
		System.out.println("-----------------");
		mv.addObject("ex", ex);
		mv.setViewName("/errors/error.jsp");
		if( ex instanceof NameException) {
			mv.setViewName("/errors/nameErroe.jsp");
		}
		if( ex instanceof AgeException) {
			mv.setViewName("/errors/ageError.jsp");
		}
		return mv;
	}

}
在SpringMVC中注册异常处理器
<!-- 组件扫描器 -->
<context:component-scan base-package="com.handlers" />
<!-- MVC注解驱动 -->
<mvc:annotation-driven />
<bean class="com.resolver.MyHandlerExceptionResolver"></bean>
三,使用注解式异常处理器
需要@ExceptionHandler注解
@ExceptionHandler(NameException.class)//处理自定义异常
@Controller
@RequestMapping("/test")
public class MyController {
	@RequestMapping("/register.do")
	public ModelAndView doAjax(String name,int age) throws StudentException {
		System.out.println("------------");
		if (!"beijing".equals(name)) {
			throw new NameException("名字不正确");
		}
		if (age > 20) {
			throw new AgeException("年龄不正确");
		}
		ModelAndView mView = new ModelAndView();
		return mView;
	}	
	
	@ExceptionHandler//处理其他异常
	public ModelAndView handlerException(Exception ex) {
		ModelAndView mv = new ModelAndView();
		System.out.println("-----------------");
		mv.addObject("ex", ex);
		mv.setViewName("/errors/error.jsp");
		
		return mv;
	}
	@ExceptionHandler(NameException.class)//处理指定异常
	public ModelAndView handlerNameException(Exception ex) {
		ModelAndView mv = new ModelAndView();
		System.out.println("-----------------");
		mv.addObject("ex", ex);
		mv.setViewName("/errors/nameErroe.jsp");
		return mv;
	}
	@ExceptionHandler(AgeException.class)//处理指定异常
	public ModelAndView handlerAgeException1(Exception ex) {
		ModelAndView mv = new ModelAndView();
		System.out.println("-----------------");
		mv.addObject("ex", ex);
		mv.setViewName("/errors/ageError.jsp");
		
		return mv;
	}
}

需要注册mvc的注解扫描
<!-- 组件扫描器 -->
<context:component-scan base-package="com.handlers" />
<!-- MVC注解驱动 -->
<mvc:annotation-driven />

SpringMVC的文件上传

1.在前端编写一个文件上传的表单
上传文件时form表单需要属性enctype="multipart/form-data"
<form action="${pageContext.request.contextPath}/test/upload.do" method="POST" enctype="multipart/form-data">
文件:<input type="file" name="img"/> <br/>
	<input type="submit" value="上传"/>
</form>
2.用处理器接收请求中的文件数据
获取上传文件相关信息需要jar包
commons-fileupload.jar
commons-io.jar
注意:处理器方法参数类型为MultipartFile,参数名为前端页面的name属性的值
	@RequestMapping("/upload.do")
	public String doFileUpload(MultipartFile img,HttpSession session) throws Exception {
		if(img.getSize() > 0){ //如果没有提交上传文件直接点击提交
		//MultipartFile img不是空,不能用!= null来判断
			String path = session.getServletContext().getRealpath("/images");//获取images文件路径来存放上传文件
			String fileName = img.getOriginalFilename();// 获取上传文件的完整文件名称
			String extension = FilenameUtils.getExtension(fileName);// 通过文件名称获取文件后缀
			String newName = UUID.randomUUID().toString() + "." + extension;// 自定义新文件名
			File file = new File(path, newName);
			img.transferTo(file);//将上传的文件保存,需要File对象作为参数
			System.out.println("------------");
			return "/welcome.jsp";
		}
		return "/error.jsp";// 跳转失败页面,根据业务具体操作
	}
3.在mvc的配置文件中注册文件上传的处理器
<!-- 组件扫描器 -->
<context:component-scan base-package="com.bjpowernode.handlers" />
<!-- 文件上传实现类 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<property name="defaultEncoding" value="utf-8"/>
	<!-- 上传数据的编码,可以防止文件名出现中文乱码 -->
	<property name="maxUploadSize" value="1048576"/>
	<!--最大上传文件的大小,单位为B,上传文件过大会出现异常,-1表示没有限制  -->
	<property name="maxInMemorySize" value="10240"/> <!-- 文件在内存中占有的总大小-->
</bean>
<!-- 如果文件大小超过容量时默认跳转的错误页面 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
	<property name="defaultErrorView" value="/error.jsp"></property>
</bean>

上传多个文件

上传多个文件时
<form action="${pageContext.request.contextPath}/test/upload.do" method="POST" enctype="multipart/form-data">
	文件1:<input type="file" name="imgs"/> <br/>
	文件2:<input type="file" name="imgs"/> <br/>
	文件3:<input type="file" name="imgs"/> <br/>
	<input type="submit" value="上传"/>
</form>
处理器的参数就不是MultipartFile img而是一个数组MultipartFile[ ] imgs
但是mvc不会自动封装为数据,需要注解@RequestParam将获取的文件封装为一个数组
	@RequestMapping("/upload.do")
	public String doFileUpload(@RequestParam MultipartFile[ ] imgs) throws Exception {
		String path="E:\\Java";
		String fileName=img.getOriginalFilename();//获取上传文件的原始文件名
		//获取File对象
		File file = new File(path,fileName);
		//保存上传文件
		img.transferTo(file);
		System.out.println("------------");
		return "/welcome.jsp";
	}

Multipart请求的源码分析

文件上传时注册的类的id值是DispatcherServlet类的属性值之一
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
DispatcherServlet类的属性
public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";
部分代码
	try {
			//为MultipartResolver对象赋值
			this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);

			if (logger.isDebugEnabled()) {
				logger.debug("Using MultipartResolver [" + this.multipartResolver + "]");
			}
		}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		boolean multipartRequestParsed = false;

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		try {
			ModelAndView mv = null;
			Exception dispatchException = null;

			try {
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);
				//如果是multipart请求,为true
		//.....................
		if (multipartRequestParsed) {//true走这里
					cleanupMultipart(processedRequest);
					//对multipart请求进行处理
				}
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
		if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
		//判断multipart不为空,上面已经赋值,并且请求是multipart请求
		//判断是multipart请求的依据是form表单的设置  enctype="multipart/form-data"
			if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) {
				logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " +
						"this typically results from an additional MultipartFilter in web.xml");
			}
			else if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) instanceof MultipartException) {
				logger.debug("Multipart resolution failed for current request before - " +
						"skipping re-resolution for undisturbed error rendering");
			}
			else {
				return this.multipartResolver.resolveMultipart(request);
				//如果是multipart请求就返回真正的multipart请求
			//CommonsMultipartResolver类的resolveMultipart(final HttpServletRequest request)方法
			//返回MultipartHttpServletRequest
			}
		}
		// If not returned before: return original request.
		return request;//如果不是multipart请求就返回普通的request请求
	}

SpringMVC的类型转换器

在页面表单提交的无论是int还是double类型数据,都能在处理接收之前转换为相应类型的数据
这是因为SpringMVC中有默认的类型转换器
SpringMVC中没有日期类型的转换器,因为日期格式太多,有一种默认的日期格式,2018/9/9——年/月/日 ,不支持前端发送的年-月-日的格式

自定义类型转换器

1.需要实现Converter接口,重写convert方法
Converter<S, T >有2个泛型
S:源的类型,表示在页面接收的数据类型
T:宿的类型,想要转换的类型
public class MyConverter implements Converter<String, Date> {

	@Override
	public Date convert(String source) {
		//根据请求中日期字符串的格式定义mvc中日期类型格式
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		//sdf.format(date);将Date数据转换为String
		//sdf.parse(source);将String转换为Date
		try {
			return sdf.parse(source);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

}
2.注册自定义的类型转换器
<!-- 组件扫描器 -->
<context:component-scan base-package="com.handlers" />
<!-- 注册自定义类型转换器 -->
<bean id="myConverter" class="com.handlers.MyConverter"/>
<!-- 注册转换服务对象,springmvc中对类型转换器有集中管理的对象,需要将自定义的转换器添加进去 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
	<property name="converters">
		<set>
			<ref bean="myConverter"/>
		</set>
	</property>
</bean>
<!-- MVC注解驱动 : 属性值为转换服务对象的id值-->
<mvc:annotation-driven conversion-service="conversionService"/>
3.定义一个form表单提交日期格式数据
会自动调用类型转换器将提交的数据转为自定义日期格式的数据
<form action="${pageContext.request.contextPath}/test/register.do" method="POST">
姓名:<input type="text" name="name"/>
生日:<input type="text" name="birther"/>
	<input type="submit" value="注册"/>
</form>
4.接收日期格式数据
将请求中字符串格式的日期自动转为Date类型的数据赋值给birther变量
	@RequestMapping("/register.do")
	public ModelAndView doSome(String name,Date birther) {
		ModelAndView mView = new ModelAndView();
		mView.addObject("name" ,name);
		mView.addObject("birther" ,birther);
		mView.setViewName("/welcome.jsp");
		return mView;
	}

利用正则表达式匹配多种日期格式

自定义的类型转换器可以将String数据可以转换为指定格式的Date数据,
但是原先默认的yyyy/MM/dd格式无法使用
可以使用正则表达式,在一个类型转换器中所有不同格式的String 
正则表达式以^开头,以$结尾,\d表示数字 ,\d{4} 表示4位数字
import java.util.regex.Pattern; 导入正则模块
	@Override
	public Date convert(String source) {
		SimpleDateFormat sdf = getDateFormat(source);
		try {
			return sdf.parse(source);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	private SimpleDateFormat getDateFormat(String source) {
		SimpleDateFormat sdf = null;
		if(Pattern.matches("^\\d{4}-\\d{2}-\\d{2}$", source)) {
			sdf = new SimpleDateFormat("yyyy-MM-dd");
		
		}else if (Pattern.matches("^\\d{4}/\\d{2}/\\d{2}$", source)) {
			sdf = new SimpleDateFormat("yyyy/MM/dd");
			
		}else if (Pattern.matches("^\\d{4}\\d{2}\\d{2}$", source)) {
			sdf = new SimpleDateFormat("yyyyMMdd");
			
		}
		return sdf ;
	}

SpringMVC的类型转换异常

当获取的参数的类型无法转换时会出现TypeMismatchException
这个异常出现在处理器获取参数之前,无法使用自动的异常解析器处理
可以使用注解式的异常解析器
	@ExceptionHandler(TypeMismatchException.class)
	public ModelAndView handlerException(Exception ex) {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("/index.jsp");
		return mv;
	}
自定义日期格式转换时可能出现的一种异常是ParseException,
这个异常已经被try..catch捕获了,外部无法得知
所有可以在发生ParseException之前主动抛出一个TypeMismatchException
private SimpleDateFormat getDateFormat(String source) {
		SimpleDateFormat sdf = new SimpleDateFormat();
		if(Pattern.matches("^\\d{4}-\\d{2}-\\d{2}$", source)) {
			sdf = new SimpleDateFormat("yyyy-MM-dd");
			return sdf ;
		}else if (Pattern.matches("^\\d{4}/\\d{2}/\\d{2}$", source)) {
			sdf = new SimpleDateFormat("yyyy/MM/dd");
			return sdf ;
		}else if (Pattern.matches("^\\d{4}\\d{2}\\d{2}$", source)) {
			sdf = new SimpleDateFormat("yyyyMMdd");
			return sdf ;
		}else{
			throw  new 	TypeMismatchException("",Date.class);
	//第一个参数是页面传递过来的数据类型,
	//第二个参数是要转换的数据类型的class,如果不能转换就会抛出这个异常
	}

数据的回显和异常信息的提示

用户提交数据出现异常时,
将请求中的参数和详细的异常信息放入ModelAndView对象中返回数据填写页面
@ExceptionHandler(TypeMismatchException.class)
	public ModelAndView handlerException(HttpServletRequest request,Exception ex) {
		String age = request.getParameter("age");
		String birthday	= request.getParameter("birthday	");
		String errors = ex.message();//获取异常信息
		ModelAndView mv = new ModelAndView();
		mView.addObject("age " ,age );
		mView.addObject("birthday" ,birthday	);
		if(errors.contains(age)){
			mView.addObject("ageError" ,"年龄输入有误");
		}
		if(errors.contains(birthday)){
			mView.addObject("birthdayError" ,"日期格式输入有误");
		}
		mv.setViewName("/index.jsp");
		return mv;
	}
回显用户提交的数据
<form action="${pageContext.request.contextPath}/test/register.do" method="POST">
	姓名:<input type="text" name="name"  value=${age} />${ageError} <br/>
	生日:<input type="text" name="birther"  value=${birthday} /> ${birthdayError}<br/>
	<input type="submit" value="注册"/>
</form>

初始化参数绑定实现类型转换

将字符串格式的日期参数转换为自定义格式的日期类型
利用@InitBinder注解实现类型的转换
利用@InitBinder只能绑定一种类型的日期格式,想要多种就需要自定义属性编辑器
@Controller
@RequestMapping("/test")
public class MyController {
	@RequestMapping("/register.do")
	public ModelAndView doSome(String name,Date birther) {
		ModelAndView mView = new ModelAndView();
		mView.addObject("name" ,name);
		mView.addObject("birther" ,birther);
		mView.setViewName("/welcome.jsp");
		return mView;
	}
	
	@InitBinder
	public void doDate(WebDataBinder binder) {
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		binder.registerCustomEditor(Date.class, new CustomDateEditor(df, true));
/*第一个参数是我们想要的参数类型,第二个是属性编辑器,
springmvc给我们提供的CustomDateEditor编辑器,需要DateFormat作为第一个参数,
第二个参数是是否允许我们想要的类型为空;
流程:数据作为参数传递到处理器的doSome(String name,Date birther) 这个方法前,先经过这个doDate方法
*/
	}
}
自定义属性编辑器要继承PropertiesEditor类,需要重写setAsText方法
public class MyDateEditor extends  PropertiesEditor{
	@Override
	public void  setAsText(String source) {
		SimpleDateFormat sdf = getDateFormat(source);
		try {
			Date date = sdf.parse(source); 
			//将传过来的值转换为Date并传过去
			setValue(date);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	private SimpleDateFormat getDateFormat(String source) {
		SimpleDateFormat sdf = new SimpleDateFormat();
		if(Pattern.matches("^\\d{4}-\\d{2}-\\d{2}$", source)) {
			sdf = new SimpleDateFormat("yyyy-MM-dd");
		
		}else if (Pattern.matches("^\\d{4}/\\d{2}/\\d{2}$", source)) {
			sdf = new SimpleDateFormat("yyyy/MM/dd");
			
		}else {
			throw new TypeMismatchException("", Date.class);
		}
		return sdf ;
	}
}

SpringMVC的数据验证

对前台数据进校验(除非安全性较高的应用,否则一般只在前台做验证即可)
SpringMVC支持JSP 303-Bean Validation数据验证规范
验证的是对象,不是基本数据类型,该规范的实现很多,常用的是Hibernate Validator 
classmate.jar
hibernate-validator.Final.jar
validation-api.Final.jar
1.在springmvc,xml中注册验证器
<!-- 生成验证器 -->
<bean id="myValidator"
	class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
	<!-- 验证器工厂 -->
	<property name="providerClass" value="org.hibernate.validator.HibernateValidator" />
	<!-- 真正的验证器类 -->
</bean>
<mvc:annotation-driven validator="myValidator"/>
2.在传递参数对应的实体类中编写校验规则
public class Student {
	@NotNull(message="姓名不能为空")
	@Size(min=3,max=6,message="姓名长度应在{min} —— {max} 间")
	private String name;
	
	@Min(value=18,message="年龄不能小于{value}")
	@Max(value=120,message="年龄不能大于{value}")
	private int age;
	
	@NotNull(message="手机号不能为空")
	@Pattern(regexp="^1[34578]\\d{9}$",message="手机号格式不正确")
	private String mobile;
	//...
}
3.在处理器中接收数据校验结果
数据到处理器之前会自动封装为Student类型时,使用@Valid注解进行校验,将异常信息封装到BindingResult bResult中
在处理器中获取参数校验结果即可
	@RequestMapping("/register.do")
	public ModelAndView doSome(@Valid Student student, BindingResult bResult) {
		ModelAndView mView = new ModelAndView();
		int errorCount = bResult.getErrorCount();//是否有错误
		if (errorCount > 0) {//有错误
			FieldError nameError = bResult.getFieldError("name");//根据Student属性名获取异常对象
			FieldError ageError = bResult.getFieldError("age");
			FieldError mobileError = bResult.getFieldError("mobile");
			if (nameError != null) {
				String name = nameError.getDefaultMessage();//获取异常信息
				mView.addObject("names", name);//添加异常信息返回前端
			}
			
			if (ageError != null) {
				String age = ageError.getDefaultMessage();
				mView.addObject("ages", age);
			}
			
			if (mobileError != null) {
				String mobile = mobileError.getDefaultMessage();
				System.out.println(mobile);
				mView.addObject("mobiles", mobile);
			}

		}
		mView.addObject("student", student);
		mView.setViewName("/index.jsp");
		return mView;
	}
4.在前台显示异常信息
<form action="${pageContext.request.contextPath}/test/register.do" method="POST">
	姓名:<input type="text" name="name"/>${ names}<br><!--页面接收错误信息-->
	成绩:<input type="text" name="age"/>${ ages}<br>
	手机号:<input type="text" name="mobile"/>${mobiles }<br>
	<input type="submit" value="注册"/>
</form>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值