注解开发-高级

 

 

2.1 上传图片

2.1.1 配置虚拟目录

 

2.1.2 配置解析器

[html] view plain copy print?

  1.   

  2.   

  3. <bean id="multipartResolver"  

  4.   

  5. class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  

  6.   

  7.   

  8.   

  9. <property name="maxUploadSize">  

  10.   

  11. <value>5242880value>  

  12.   

  13. property>  

  14.   

  15. bean>  



 

2.1.3 jar

CommonsMultipartResolver解析器依赖commons-fileuploadcommons-io,加入如下jar包:

 

 

2.1.4 单个图片上传

1、controller

 

[java] view plain copy print?

  1. //商品修改提交  

  2.   

  3. @RequestMapping("/editItemSubmit")  

  4.   

  5. public String editItemSubmit(Items items, MultipartFile pictureFile)throws Exception{  

  6.   

  7. //原始文件名称  

  8.   

  9. String pictureFile_name =  pictureFile.getOriginalFilename();  

  10.   

  11. //新文件名称  

  12.   

  13. String newFileName = UUID.randomUUID().toString()+pictureFile_name.substring(pictureFile_name.lastIndexOf("."));  

  14.   

  15. //上传图片  

  16.   

  17. File uploadPic = new java.io.File("F:/develop/upload/temp/"+newFileName);  

  18.   

  19. if(!uploadPic.exists()){  

  20.   

  21. uploadPic.mkdirs();  

  22.   

  23. }  

  24.   

  25. //向磁盘写文件  

  26.   

  27. pictureFile.transferTo(uploadPic);  

  28.   

  29.    

  30.   

  31. .....  

  32.   

  33.    



 

2、 页面:

 

form添加enctype="multipart/form-data"

[html] view plain copy print?

  1. <form id="itemForm"  

  2.   

  3. action="${pageContext.request.contextPath }/item/editItemSubmit.action"  

  4.   

  5. method="post" enctype="multipart/form-data">  

  6.   

  7. <input type="hidden" name="pic" value="${item.pic }" />  

  8.   

  9.    



 

filenamecontroller形参一致:

[html] view plain copy print?

  1. <tr>  

  2.   

  3. <td>商品图片td>  

  4.   

  5. <td><c:if test="${item.pic !=null}">  

  6.   

  7. <img src="/pic/${item.pic}" width=100 height=100 />  

  8.   

  9. <br />  

  10.   

  11. c:if> <input type="file" name="pictureFile" />td>  

  12.   

  13. tr>  



 

 

2.2 Validation(了解)

 

b/s系统中对http请求数据的校验多数在客户端进行,这也是出于简单及用户体验性上考虑,但是在一些安全性要求高的系统中服务端校验是不可缺少的,本节主要学习springmvc实现控制层添加校验。

Spring3支持JSR-303验证框架,JSR-303Java EE 6中的一项子规范,叫做Bean Validation,官方参考实现是hibernate Validator(与Hibernate ORM没有关系),JSR 303用于对Java Bean中的字段的值进行验证。

2.2.1 需求

对商品信息进行校验,是否必须,输入数据合法性。

 

2.2.2 加入jar

 

 

2.2.3 配置validator

 

[html] view plain copy print?

  1.   

  2.   

  3. <bean id="messageSource"  

  4.   

  5. class="org.springframework.context.support.ReloadableResourceBundleMessageSource">  

  6.   

  7. <property name="basenames">     

  8.   

  9.         <list>      

  10.   

  11.             <value>classpath:CustomValidationMessagesvalue>     

  12.   

  13.         list>     

  14.   

  15.     property>  

  16.   

  17. <property name="fileEncodings" value="utf-8" />  

  18.   

  19. <property name="cacheSeconds" value="120" />  

  20.   

  21. bean>  

  22.   

  23. <bean id="validator"  

  24.   

  25. class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">  

  26.   

  27. <property name="providerClass" value="org.hibernate.validator.HibernateValidator" />  

  28.   

  29.   

  30.   

  31. <property name="validationMessageSource" ref="messageSource" />  

  32.   

  33. bean>  



 

 

2.2.4 validator加到处理器适配器

配置方式1

[html] view plain copy print?

  1.   

  2.   

  3. <bean id="customBinder"  

  4.   

  5. class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">  

  6.   

  7. <property name="validator" ref="validator" />  

  8.   

  9. bean>  


 

[html] view plain copy print?

  1.   

  2.   

  3. <bean  

  4.   

  5. class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">  

  6.   

  7. <property name="webBindingInitializer" ref="customBinder">property>  

  8.   

  9. bean>  



 

配置方式2

[html] view plain copy print?

  1. <mvc:annotation-driven validator="validator"> mvc:annotation-driven>  



 

 

2.2.5 添加验证规则

 

[html] view plain copy print?

  1. public class Items {  

  2.   

  3.     private Integer id;  

  4.   

  5.     @Size(min=1,max=30,message="{item.name.length.illigel}")  

  6.   

  7.     private String name;  

  8.   

  9.       

  10.   

  11.     @NotEmpty(message="{pic.is.null}")  

  12.   

  13.     private String pic;  

  14.   

  15.    



2.2.6 错误消息文件CustomValidationMessages

 

如果在eclipse中编辑properties文件无法看到中文则参考“Eclipse开发环境配置-indigo.docx”添加propedit插件。

 

2.2.7 捕获错误

 

修改Controller方法:

[html] view plain copy print?

  1. // 商品修改提交  

  2.   

  3. @RequestMapping("/editItemSubmit")  

  4.   

  5. public String editItemSubmit(@Validated @ModelAttribute("item") Items items,BindingResult result,  

  6.   

  7. @RequestParam("pictureFile") MultipartFile[] pictureFile,Model model)  

  8.   

  9. throws Exception {  

  10.   

  11. //如果存在校验错误则转到商品修改页面  

  12.   

  13. if (result.hasErrors()) {  

  14.   

  15. List<ObjectError> errors = result.getAllErrors();  

  16.   

  17. for(ObjectError objectError:errors){  

  18.   

  19. System.out.println(objectError.getCode());  

  20.   

  21. System.out.println(objectError.getDefaultMessage());  

  22.   

  23. }  

  24.   

  25. return "item/editItem";  

  26.   

  27. }  

  28.   

  29.    

  30.   

  31.    



注意:添加@Validated表示在对items参数绑定时进行校验,校验信息写入BindingResult中,在要校验的pojo后边添加BingdingResult, 一个BindingResult对应一个pojo,且BingdingResult放在pojo的后边。

 

商品修改页面:

页头:

[html] view plain copy print?

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"  

  2.   

  3.     pageEncoding="UTF-8"%>  

  4.   

  5. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  

  6.   

  7. <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"    

  8.   

  9. <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>  



 

在需要显示错误信息地方:

[html] view plain copy print?

  1. <spring:hasBindErrors name="item">  

  2.   

  3. <c:forEach items="${errors.allErrors}" var="error">  

  4.   

  5. ${error.defaultMessage }<br/>  

  6.   

  7. c:forEach>  

  8.   

  9. spring:hasBindErrors>  

  10.   

  11.    



说明:

表示如果item参数绑定校验错误下边显示错误信息。

 

2.2.8 分组校验

如果两处校验使用同一个Items类则可以设定校验分组。

 

定义分组:

分组就是一个标识,这里定义一个接口:

[html] view plain copy print?

  1. public interface ValidGroup1 {  

  2.   

  3.    

  4.   

  5. }  

  6.   

  7. public interface ValidGroup2 {  

  8.   

  9.    

  10.   

  11. }  



 

指定分组校验:

[html] view plain copy print?

  1. public class Items {  

  2.   

  3.     private Integer id;  

  4.   

  5. //这里指定分组ValidGroup1,此@Size校验只适用ValidGroup1校验  

  6.   

  7.     @Size(min=1,max=30,message="{item.name.length.illigel}",groups={ValidGroup1.class})  

  8.   

  9.     private String name;  

  10.   

  11.    

  12.   

  13. // 商品修改提交  

  14.   

  15. @RequestMapping("/editItemSubmit")  

  16.   

  17. public String editItemSubmit(@Validated(value={ValidGroup1.class}) @ModelAttribute("item") Items items,BindingResult result,  

  18.   

  19. @RequestParam("pictureFile") MultipartFile[] pictureFile,Model model)  

  20.   

  21. throws Exception {  



@Validated中添加value={ValidGroup1.class}表示商品修改使用了ValidGroup1分组校验规则,也可以指定多个分组中间用逗号分隔,

@Validated(value={ValidGroup1.classValidGroup2.class })

 

2.3 异常处理器

 

springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。

2.3.1 异常处理思路

系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。

系统的daoservicecontroller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:

 

 

2.3.2 自定义异常类

为了区别不同的异常通常根据异常类型自定义异常类,这里我们创建一个自定义系统异常,如果controllerservicedao抛出此类异常说明是系统预期处理的异常信息。

 

[html] view plain copy print?

  1.     public class CustomException extends Exception {  

  2.   

  3.    

  4.   

  5. /** serialVersionUID*/  

  6.   

  7. private static final long serialVersionUID = -5212079010855161498L;  

  8.   

  9. public CustomException(String message){  

  10.   

  11. super(message);  

  12.   

  13. this.message = message;  

  14.   

  15. }  

  16.   

  17.    

  18.   

  19. //异常信息  

  20.   

  21. private String message;  

  22.   

  23.    

  24.   

  25. public String getMessage() {  

  26.   

  27. return message;  

  28.   

  29. }  

  30.   

  31.    

  32.   

  33. public void setMessage(String message) {  

  34.   

  35. this.message = message;  

  36.   

  37. }  

  38.   

  39. }  

  40.   

  41.    

  42.   

  43.    



2.3.3 自定义异常处理器

 

[html] view plain copy print?

  1. public class CustomExceptionResolver implements HandlerExceptionResolver {  

  2.   

  3.    

  4.   

  5. @Override  

  6.   

  7. public ModelAndView resolveException(HttpServletRequest request,  

  8.   

  9. HttpServletResponse response, Object handler, Exception ex) {  

  10.   

  11.    

  12.   

  13. ex.printStackTrace();  

  14.   

  15.    

  16.   

  17. CustomException customException = null;  

  18.   

  19. //如果抛出的是系统自定义异常则直接转换  

  20.   

  21. if(ex instanceof CustomException){  

  22.   

  23. customException = (CustomException)ex;  

  24.   

  25. }else{  

  26.   

  27. //如果抛出的不是系统自定义异常则重新构造一个未知错误异常。  

  28.   

  29. customException = new CustomException("未知错误,请与系统管理 员联系!");  

  30.   

  31. }  

  32.   

  33. ModelAndView modelAndView = new ModelAndView();  

  34.   

  35. modelAndView.addObject("message", customException.getMessage());  

  36.   

  37. modelAndView.setViewName("error");  

  38.   

  39.    

  40.   

  41. return modelAndView;  

  42.   

  43. }  

  44.   

  45.    

  46.   

  47. }  

  48.   

  49.    



2.3.4 错误页面

[html] view plain copy print?

  1.    

  2.   

  3. <%@ page language="java" contentType="text/html; charset=UTF-8"  

  4.   

  5.     pageEncoding="UTF-8"%>  

  6.   

  7. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  

  8.   

  9. <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"  prefix="fmt"%>   

  10.   

  11. >  

  12.   

  13. <html>  

  14.   

  15. <head>  

  16.   

  17. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  

  18.   

  19. <title>错误页面title>  

  20.   

  21.    

  22.   

  23. head>  

  24.   

  25. <body>  

  26.   

  27. 您的操作出现错误如下:<br/>  

  28.   

  29. ${message }  

  30.   

  31. body>  

  32.   

  33.    

  34.   

  35. html>  

  36.   

  37.    

  38.   

  39.    

  40.   

  41.    



2.3.5 异常处理器配置

springmvc.xml中添加:

 

[html] view plain copy print?

  1.   

  2.   

  3. <bean id="handlerExceptionResolver" class="cn.itcast.ssm.controller.exceptionResolver.CustomExceptionResolver"/>  



 

2.3.6 异常测试

修改商品信息,id输入错误提示商品信息不存在。

 

修改controller方法“editItem”,调用service查询商品信息,如果商品信息为空则抛出异常:

[html] view plain copy print?

  1. // 调用service查询商品信息  

  2.   

  3. Items item = itemService.findItemById(id);  

  4.   

  5. if(item == null){  

  6.   

  7. throw new CustomException("商品信息不存在!");  

  8.   

  9. }  

  10.   

  11.    

  12.   

  13.    



 

请自行实现在servicedao中跑出异常。

 

 

2.4 json数据交互

2.4.1 @RequestBody

作用:

@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为jsonxml等格式的数据并绑定到controller方法的参数上。

 

本例子应用:

@RequestBody注解实现接收http请求的json数据,将json数据转换为java对象

 

2.4.2 @ResponseBody

作用:

该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端

 

本例子应用:

@ResponseBody注解实现将controller方法返回对象转换为json响应给客户端

 

2.4.3 请求json,响应json实现:

2.4.3.1 环境准备

Springmvc默认用MappingJacksonHttpMessageConverterjson数据进行转换,需要加入jackson的包,如下:

 

2.4.3.2 配置json转换器

在注解适配器中加入messageConverters

 

[html] view plain copy print?

  1.   

  2.   

  3. <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">  

  4.   

  5. <property name="messageConverters">  

  6.   

  7. <list>  

  8.   

  9. <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">bean>  

  10.   

  11. list>  

  12.   

  13. property>  

  14.   

  15. bean>  



 

注意:如果使用 则不用定义上边的内容。

 

 

2.4.3.3 controller编写

[html] view plain copy print?

  1. // 商品修改提交json信息,响应json信息  

  2.   

  3. @RequestMapping("/editItemSubmit_RequestJson")  

  4.   

  5. public @ResponseBody Items editItemSubmit_RequestJson(@RequestBody Items items) throws Exception {  

  6.   

  7. System.out.println(items);  

  8.   

  9. //itemService.saveItem(items);  

  10.   

  11. return items;  

  12.   

  13.    

  14.   

  15. }  



 

2.4.3.4 页面js方法编写:

引入 js

 

 

[html] view plain copy print?

  1. //请求json响应json  

  2.   

  3. function request_json(){  

  4.   

  5. $.ajax({  

  6.   

  7. type:"post",  

  8.   

  9. url:"${pageContext.request.contextPath }/item/editItemSubmit_RequestJson.action",  

  10.   

  11. contentType:"application/json;charset=utf-8",  

  12.   

  13. data:'{"name":"测试商品","price":99.9}',  

  14.   

  15. success:function(data){  

  16.   

  17. alert(data);  

  18.   

  19. }  

  20.   

  21. });  

  22.   

  23. }  

  24.   

  25.    



2.4.3.5 测试结果:

 

 

从上图可以看出请求的数据是json格式

2.4.4 Form提交,响应json实现:

采用form提交是最常用的作法,通常有postget两种方法,响应json数据是为了方便客户端处理,实现如下:

 

2.4.4.1 环境准备

同第一个例子

 

2.4.4.2 controller编写

 

[html] view plain copy print?

  1. // 商品修改提交,提交普通form表单数据,响应json  

  2.   

  3. @RequestMapping("/editItemSubmit_ResponseJson")  

  4.   

  5. public @ResponseBody Items editItemSubmit_ResponseJson(Items items) throws Exception {  

  6.   

  7.    

  8.   

  9. System.out.println(items);  

  10.   

  11.    

  12.   

  13. //itemService.saveItem(items);  

  14.   

  15. return items;  

  16.   

  17. }  



 

2.4.4.3 页面js方法编写:

 

[html] view plain copy print?

  1. function formsubmit(){  

  2.   

  3. var user = " name=测试商品&price=99.9";  

  4.   

  5. alert(user);  

  6.   

  7.   $.ajax(  

  8.   

  9. {  

  10.   

  11. type:'post',//这里改为get也可以正常执行  

  12.   

  13. url:'${pageContext.request.contextPath}/item/ editItemSubmit_RequestJson.action',  

  14.   

  15. //ContentType没指定将默认为:application/x-www-form-urlencoded  

  16.   

  17. data:user,  

  18.   

  19. success:function(data){  

  20.   

  21. alert(data.name);  

  22.   

  23. }  

  24.   

  25. }  

  26.   

  27. )  

  28.   

  29. }  



 

从上边的js代码看出,已去掉ContentType的定义,ContentType默认为:application/x-www-form-urlencoded格式。

 

 

2.4.4.4 测试结果:

 

从上图可以看出请求的数据是标准的key/value格式。

 

2.4.4.5 jqueryform插件插件

 

针对上边第二种方法,可以使用jqueryform插件提交form表单,实现ajax提交form表单,如下:

 

引用js

 

js方法如下:

 

[html] view plain copy print?

  1. function response_json() {  

  2.   

  3. //form对象  

  4.   

  5. var formObj = $("#itemForm");  

  6.   

  7. //执行ajax提交  

  8.   

  9. formObj.ajaxSubmit({  

  10.   

  11. dataType : "json",//设置预期服务端返回json  

  12.   

  13. success : function(responseText) {  

  14.   

  15. alert(responseText);  

  16.   

  17. }  

  18.   

  19. });  

  20.   

  21. }  

  22.   

  23.    



 

 

2.4.5 小结

实际开发中常用第二种方法,请求key/value数据,响应json结果,方便客户端对结果进行解析。

 

 

 

2.5 RESTful支持

2.5.1 需求

RESTful方式商品修改、商品查询。

 

2.5.2 添加DispatcherServletrest配置

 

[html] view plain copy print?

  1. <servlet>  

  2.   

  3. <servlet-name>springmvc-servlet-restservlet-name>  

  4.   

  5. <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>  

  6.   

  7. <init-param>  

  8.   

  9. <param-name>contextConfigLocationparam-name>  

  10.   

  11. <param-value>classpath:spring/springmvc.xmlparam-value>  

  12.   

  13. init-param>  

  14.   

  15. servlet>  

  16.   

  17. <servlet-mapping>  

  18.   

  19. <servlet-name>springmvc-servlet-restservlet-name>  

  20.   

  21. <url-pattern>/url-pattern>  

  22.   

  23. servlet-mapping>  



2.5.3 URL 模板模式映射

@RequestMapping(value="/ editItem/{item_id}"){×××}占位符,请求的URL可以是/editItem/1”或“/editItem/2”,通过在方法中使用@PathVariable获取{×××}中的×××变量。

 

[html] view plain copy print?

  1. @RequestMapping("/ editItem/{item_id}")   

  2.   

  3. public String useredit(@PathVariable("item_id ") String id,Model model) throws Exception{  

  4.   

  5. //方法中使用@PathVariable获取useried的值,使用model传回页面  

  6.   

  7. model.addAttribute("userid", userid);  

  8.   

  9. return"/user/useredit";  

  10.   

  11. }  



 

如果RequestMapping中表示为"/ editItem/{id}"id和形参名称一致,@PathVariable不用指定名称。

 

商品查询的controller方法也改为rest实现:

 

[html] view plain copy print?

  1. // 查询商品列表  

  2.   

  3. @RequestMapping("/queryItem")  

  4.   

  5. public ModelAndView queryItem() throws Exception {  

  6.   

  7. // 商品列表  

  8.   

  9. List<Items> itemsList = itemService.findItemsList(null);  

  10.   

  11.    

  12.   

  13. // 创建modelAndView准备填充数据、设置视图  

  14.   

  15. ModelAndView modelAndView = new ModelAndView();  

  16.   

  17.    

  18.   

  19. // 填充数据  

  20.   

  21. modelAndView.addObject("itemsList", itemsList);  

  22.   

  23. // 视图  

  24.   

  25. modelAndView.setViewName("item/itemsList");  

  26.   

  27.    

  28.   

  29. return modelAndView;  

  30.   

  31. }  



 

2.5.4 静态资源访问

spring mvc 实现对静态资源进行映射访问。

如下是对js文件访问配置: