springmvc教程(4)
springmvc教程系列
springmvc史上最好教程(2)
springmvc史上最好教程(1)springmvc史上最好教程(3)
2注解開發-高級
2.1上傳圖片
2.1.1配置虛擬目錄
2.1.2配置解析器
<!-- 文件上傳 --><bean id="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!-- 設置上傳文件的最大尺寸為5MB --><property name="maxUploadSize"><value>5242880</value></property></bean>2.1.3jar包
CommonsMultipartResolver解析器依賴commons-fileupload和commons-io,加入如下jar包:
2.1.4單個圖片上傳
1、controller:
//商品修改提交@RequestMapping("/editItemSubmit")public String editItemSubmit(Items items, MultipartFile pictureFile)throws Exception{//原始文件名稱String pictureFile_name = pictureFile.getOriginalFilename();//新文件名稱String newFileName = UUID.randomUUID().toString()+pictureFile_name.substring(pictureFile_name.lastIndexOf("."));//上傳圖片File uploadPic = new java.io.File("F:/develop/upload/temp/"+newFileName);if(!uploadPic.exists()){uploadPic.mkdirs();}//向磁盤寫文件pictureFile.transferTo(uploadPic);.....2、 頁面:
form添加enctype="multipart/form-data":
<form id="itemForm"action="${pageContext.request.contextPath }/item/editItemSubmit.action"method="post" enctype="multipart/form-data"><input type="hidden" name="pic" value="${item.pic }" />file的name與controller形參一致:
<tr><td>商品圖片</td><td><c:if test="${item.pic !=null}"><img src="/pic/${item.pic}" width=100 height=100 /><br /></c:if> <input type="file" name="pictureFile" /></td></tr>2.2Validation(了解)
b/s系統中對http請求數據的校驗多數在客戶端進行,這也是出于簡單及用戶體驗性上考慮,但是在一些安全性要求高的系統中服務端校驗是不可缺少的,本節主要學習springmvc實現控制層添加校驗。
Spring3支持JSR-303驗證框架,JSR-303是JAVA EE 6中的一項子規范,叫做Bean Validation,官方參考實現是Hibernate Validator(與Hibernate ORM沒有關系),JSR 303用于對Java Bean中的字段的值進行驗證。
2.2.1需求
對商品信息進行校驗,是否必須,輸入數據合法性。
2.2.2加入jar包
2.2.3配置validator
<!-- 校驗錯誤信息配置文件 --><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><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>2.2.4將validator加到處理器適配器
配置方式1:
<!-- 自定義webBinder --><bean id="customBinder"class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"><property name="validator" ref="validator" /></bean><!-- 注解適配器 --><beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="webBindingInitializer" ref="customBinder"></property></bean>
配置方式2:
<mvc:annotation-driven validator="validator"> </mvc:annotation-driven>2.2.5添加驗證規則
public class Items {private Integer id;@Size(min=1,max=30,message="{item.name.length.illigel}")private String name;@NotEmpty(message="{pic.is.null}")private String pic;2.2.6錯誤消息文件CustomValidationMessages
item.name.length.illigel=商品在名稱在1到3個字符之間
pic.is.null=請上傳圖片
如果在eclipse中編輯properties文件無法看到中文則參考“Eclipse開發環境配置-indigo.docx”添加propedit插件。
2.2.7捕獲錯誤
修改Controller方法:
// 商品修改提交@RequestMapping("/editItemSubmit")public String editItemSubmit(@Validated @ModelAttribute("item") Items items,BindingResult result,@RequestParam("pictureFile") MultipartFile[] pictureFile,Model model)throws Exception {//如果存在校驗錯誤則轉到商品修改頁面if (result.hasErrors()) {List<ObjectError> errors = result.getAllErrors();for(ObjectError objectError:errors){System.out.println(objectError.getCode());System.out.println(objectError.getDefaultMessage());}return "item/editItem";}注意:添加@Validated表示在對items參數綁定時進行校驗,校驗信息寫入BindingResult中,在要校驗的pojo后邊添加BingdingResult, 一個BindingResult對應一個pojo,且BingdingResult放在pojo的后邊。
商品修改頁面:
頁頭:
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>在需要顯示錯誤信息地方:
<spring:hasBindErrors name="item"><c:forEach items="${errors.allErrors}" var="error">${error.defaultMessage }<br/></c:forEach></spring:hasBindErrors>說明:
<spring:hasBindErrors name="item">表示如果item參數綁定校驗錯誤下邊顯示錯誤信息。
2.2.8分組校驗
如果兩處校驗使用同一個Items類則可以設定校驗分組。
定義分組:
分組就是一個標識,這里定義一個接口:
public interface ValidGroup1 {}public interface ValidGroup2 {}指定分組校驗:
public class Items {private Integer id;//這里指定分組ValidGroup1,此@Size校驗只適用ValidGroup1校驗@Size(min=1,max=30,message="{item.name.length.illigel}",groups={ValidGroup1.class})private String name;// 商品修改提交@RequestMapping("/editItemSubmit")public String editItemSubmit(@Validated(value={ValidGroup1.class}) @ModelAttribute("item") Items items,BindingResult result,@RequestParam("pictureFile") MultipartFile[] pictureFile,Model model)throws Exception {在@Validated中添加value={ValidGroup1.class}表示商品修改使用了ValidGroup1分組校驗規則,也可以指定多個分組中間用逗號分隔,
@Validated(value={ValidGroup1.class,ValidGroup2.class})
2.3異常處理器
springmvc在處理請求過程中出現異常信息交由異常處理器進行處理,自定義異常處理器可以實現一個系統的異常處理邏輯。
2.3.1異常處理思路
系統中異常包括兩類:預期異常和運行時異常RuntimeException,前者通過捕獲異常從而獲取異常信息,后者主要通過規范代碼開發、測試通過手段減少運行時異常的發生。
系統的dao、service、controller出現都通過throws Exception向上拋出,最后由springmvc前端控制器交由異常處理器進行異常處理,如下圖:
2.3.2自定義異常類
為了區別不同的異常通常根據異常類型自定義異常類,這里我們創建一個自定義系統異常,如果controller、service、dao拋出此類異常說明是系統預期處理的異常信息。
public class CustomException extends Exception {/** serialVersionUID*/private static final long serialVersionUID = -5212079010855161498L;public CustomException(String message){super(message);this.message = message;}//異常信息private String message;public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}}2.3.3自定義異常處理器
public class CustomExceptionResolver implements HandlerExceptionResolver {@Overridepublic ModelAndView resolveException(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex) {ex.printStackTrace();CustomException customException = null;//如果拋出的是系統自定義異常則直接轉換if(ex instanceof CustomException){customException = (CustomException)ex;}else{//如果拋出的不是系統自定義異常則重新構造一個未知錯誤異常。customException = new CustomException("未知錯誤,請與系統管理 員聯系!");}ModelAndView modelAndView = new ModelAndView();modelAndView.addObject("message", customException.getMessage());modelAndView.setViewName("error");return modelAndView;}}2.3.4錯誤頁面
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>錯誤頁面</title></head><body>您的操作出現錯誤如下:<br/>${message }</body></html>2.3.5異常處理器配置
在springmvc.xml中添加:
<!-- 異常處理器 --><bean id="handlerExceptionResolver" class="cn.itcast.ssm.controller.exceptionResolver.CustomExceptionResolver"/>2.3.6異常測試
修改商品信息,id輸入錯誤提示商品信息不存在。
修改controller方法“editItem”,調用service查詢商品信息,如果商品信息為空則拋出異常:
// 調用service查詢商品信息Items item = itemService.findItemById(id);if(item == null){throw new CustomException("商品信息不存在!");}請自行實現在service、dao中跑出異常。
2.4json數據交互
2.4.1@RequestBody
作用:
@RequestBody注解用于讀取http請求的內容(字符串),通過springmvc提供的HttpMessageConverter接口將讀到的內容轉換為json、xml等格式的數據并綁定到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默認用MappingJacksonHttpMessageConverter對json數據進行轉換,需要加入jackson的包,如下:
2.4.3.2配置json轉換器
在注解適配器中加入messageConverters
<!--注解適配器 --><bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="messageConverters"><list><bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean></list></property></bean>注意:如果使用<mvc:annotation-driven />則不用定義上邊的內容。
2.4.3.3controller編寫
// 商品修改提交json信息,響應json信息@RequestMapping("/editItemSubmit_RequestJson")public @ResponseBody Items editItemSubmit_RequestJson(@RequestBody Items items) throws Exception {System.out.println(items);//itemService.saveItem(items);return items;}2.4.3.4頁面js方法編寫:
引入 js:
<script type="text/javascript"
src="${pageContext.request.contextPath }/js/jquery-1.4.4.min.js"></script>
//請求json響應jsonfunction request_json(){$.ajax({type:"post",url:"${pageContext.request.contextPath }/item/editItemSubmit_RequestJson.action",contentType:"application/json;charset=utf-8",data:'{"name":"測試商品","price":99.9}',success:function(data){alert(data);}});}2.4.3.5測試結果:
從上圖可以看出請求的數據是json格式
2.4.4Form提交,響應json實現:
采用form提交是最常用的作法,通常有post和get兩種方法,響應json數據是為了方便客戶端處理,實現如下:
2.4.4.1環境準備
同第一個例子
2.4.4.2controller編寫
// 商品修改提交,提交普通form表單數據,響應json@RequestMapping("/editItemSubmit_ResponseJson")public @ResponseBody Items editItemSubmit_ResponseJson(Items items) throws Exception {System.out.println(items);//itemService.saveItem(items);return items;}2.4.4.3頁面js方法編寫:
function formsubmit(){var user = " name=測試商品&price=99.9";alert(user);$.ajax({type:'post',//這里改為get也可以正常執行url:'${pageContext.request.contextPath}/item/ editItemSubmit_RequestJson.action',//ContentType沒指定將默認為:application/x-www-form-urlencodeddata:user,success:function(data){alert(data.name);}})}從上邊的js代碼看出,已去掉ContentType的定義,ContentType默認為:application/x-www-form-urlencoded格式。
2.4.4.4測試結果:
從上圖可以看出請求的數據是標準的key/value格式。
2.4.4.5jquery的form插件插件
針對上邊第二種方法,可以使用jquery的form插件提交form表單,實現ajax提交form表單,如下:
引用js:
<script type="text/javascript"
src="${pageContext.request.contextPath }/js/jquery-1.4.4.min.js"></script>
<script type="text/javascript"
src="${pageContext.request.contextPath }/js/jquery.form.min.js"></script>
js方法如下:
function response_json() {//form對象var formObj = $("#itemForm");//執行ajax提交formObj.ajaxSubmit({dataType : "json",//設置預期服務端返回jsonsuccess : function(responseText) {alert(responseText);}});}2.4.5小結
實際開發中常用第二種方法,請求key/value數據,響應json結果,方便客戶端對結果進行解析。
2.5RESTful支持
2.5.1需求
RESTful方式商品修改、商品查詢。
2.5.2添加DispatcherServlet的rest配置
<servlet><servlet-name>springmvc-servlet-rest</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/springmvc.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>springmvc-servlet-rest</servlet-name><url-pattern>/</url-pattern></servlet-mapping>2.5.3URL模板模式映射
@RequestMapping(value="/editItem/{item_id}"):{×××}占位符,請求的URL可以是“/editItem/1”或“/editItem/2”,通過在方法中使用@PathVariable獲取{×××}中的×××變量。
@RequestMapping("/ editItem/{item_id}") public String useredit(@PathVariable("item_id ") String id,Model model) throws Exception{//方法中使用@PathVariable獲取useried的值,使用model傳回頁面model.addAttribute("userid", userid);return"/user/useredit";}如果RequestMapping中表示為"/editItem/{id}",id和形參名稱一致,@PathVariable不用指定名稱。
商品查詢的controller方法也改為rest實現:
// 查詢商品列表@RequestMapping("/queryItem")public ModelAndView queryItem() throws Exception {// 商品列表List<Items> itemsList = itemService.findItemsList(null);// 創建modelAndView準備填充數據、設置視圖ModelAndView modelAndView = new ModelAndView();// 填充數據modelAndView.addObject("itemsList", itemsList);// 視圖modelAndView.setViewName("item/itemsList");return modelAndView;}2.5.4靜態資源訪問<mvc:resources>
spring mvc 的<mvc:resources mapping="" location="">實現對靜態資源進行映射訪問。
如下是對js文件訪問配置:
<mvc:resources location="/js/" mapping="/js/**"/>
3攔截器
3.1定義
Spring Web MVC 的處理器攔截器類似于Servlet 開發中的過濾器Filter,用于對處理器進行預處理和后處理。
3.2攔截器定義
實現HandlerInterceptor接口,如下:
Public class HandlerInterceptor1 implements HandlerInterceptor{/*** controller執行前調用此方法* 返回true表示繼續執行,返回false中止執行* 這里可以加入登錄校驗、權限攔截等*/@OverridePublic boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {// TODO Auto-generated method stubReturn false;}/*** controller執行后但未返回視圖前調用此方法* 這里可在返回用戶前對模型數據進行加工處理,比如這里加入公用信息以便頁面顯示*/@OverridePublic void postHandle(HttpServletRequest request,HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {// TODO Auto-generated method stub}/*** controller執行后且視圖返回后調用此方法* 這里可得到執行controller時的異常信息* 這里可記錄操作日志,資源清理等*/@OverridePublic void afterCompletion(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex)throws Exception {// TODO Auto-generated method stub}}
3.3攔截器配置
3.3.1針對某種mapping配置攔截器
<beanclass="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"><property name="interceptors"><list><ref bean="handlerInterceptor1"/><ref bean="handlerInterceptor2"/></list></property></bean><bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/><bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>
3.3.2針對所有mapping配置全局攔截器
<!--攔截器 --><mvc:interceptors><!--多個攔截器,順序執行 --><mvc:interceptor><mvc:mapping path="/**"/><bean class="cn.itcast.springmvc.filter.HandlerInterceptor1"></bean></mvc:interceptor><mvc:interceptor><mvc:mapping path="/**"/><bean class="cn.itcast.springmvc.filter.HandlerInterceptor2"></bean></mvc:interceptor></mvc:interceptors>
3.4正常流程測試
3.4.1代碼:
定義兩個攔截器分別為:HandlerInterceptor1和HandlerInteptor2,每個攔截器的preHandler方法都返回true。
3.4.2運行流程
HandlerInterceptor1..preHandle..
HandlerInterceptor2..preHandle..
HandlerInterceptor2..postHandle..
HandlerInterceptor1..postHandle..
HandlerInterceptor2..afterCompletion..
HandlerInterceptor1..afterCompletion..
3.5中斷流程測試
3.5.1代碼:
定義兩個攔截器分別為:HandlerInterceptor1和HandlerInteptor2。
3.5.2運行流程
HandlerInterceptor1的preHandler方法返回false,HandlerInterceptor2返回true,運行流程如下:
HandlerInterceptor1..preHandle..
從日志看出第一個攔截器的preHandler方法返回false后第一個攔截器只執行了preHandler方法,其它兩個方法沒有執行,第二個攔截器的所有方法不執行,且controller也不執行了。
HandlerInterceptor1的preHandler方法返回true,HandlerInterceptor2返回false,運行流程如下:
HandlerInterceptor1..preHandle..
HandlerInterceptor2..preHandle..
HandlerInterceptor1..afterCompletion..
從日志看出第二個攔截器的preHandler方法返回false后第一個攔截器的postHandler沒有執行,第二個攔截器的postHandler和afterCompletion沒有執行,且controller也不執行了。
總結:
preHandle按攔截器定義順序調用
postHandler按攔截器定義逆序調用
afterCompletion按攔截器定義逆序調用
postHandler在攔截器鏈內所有攔截器返成功調用
afterCompletion只有preHandle返回true才調用
3.6攔截器應用
3.6.1用戶身份認證
Public class LoginInterceptorimplements HandlerInterceptor{@OverridePublic boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler)throws Exception {//如果是登錄頁面則放行if(request.getRequestURI().indexOf("login.action")>=0){return true;}HttpSession session = request.getSession();//如果用戶已登錄也放行if(session.getAttribute("user")!=null){return true;}//用戶沒有登錄挑戰到登錄頁面request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);return false;}}3.6.2用戶登陸controller
//登陸頁面@RequestMapping("/login")public String login(Model model)throws Exception{return "login";}//登陸提交//userid:用戶賬號,pwd:密碼@RequestMapping("/loginsubmit")public String loginsubmit(HttpSession session,String userid,String pwd)throws Exception{//向session記錄用戶身份信息session.setAttribute("activeUser", userid);return "redirect:item/queryItem.action";}//退出@RequestMapping("/logout")public String logout(HttpSession session)throws Exception{//session過期session.invalidate();return "redirect:item/queryItem.action";}總結
以上是生活随笔為你收集整理的springmvc教程(4)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: shiro教程(1)-基于url权限管理
- 下一篇: springmvc教程--RESTful