日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

SpringMVC【校验器、统一处理异常、RESTful、拦截器】

發布時間:2023/12/10 javascript 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringMVC【校验器、统一处理异常、RESTful、拦截器】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

本博文主要講解的知識點如下:

  • 校驗器
  • 統一處理異常
  • RESTful
  • 攔截器

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: ozcDate: 2017/8/11Time: 9:56To 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就是接收到異常信息@Overridepublic 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 blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return new ModelAndView();}}

配置統一異常處理器

<!-- 定義統一異常處理器 --><bean class="cn.itcast.ssm.exception.CustomExceptionResolver"></bean>

RESTful支持

我們在學習webservice的時候可能就聽過RESTful這么一個名詞,當時候與SOAP進行對比的…那么RESTful究竟是什么東東呢???

RESTful(Representational State Transfer)軟件開發理念,RESTful對http進行非常好的詮釋

如果一個架構支持RESTful,那么就稱它為RESTful架構…

以下的文章供我們了解:

http://www.ruanyifeng.com/blog/2011/09/restful

綜合上面的解釋,我們總結一下什么是RESTful架構:

  •   (1)每一個URI代表一種資源;
  •   (2)客戶端和服務器之間,傳遞這種資源的某種表現層;
  •   (3)客戶端通過四個HTTP動詞,對服務器端資源進行操作,實現”表現層狀態轉化”

關于RESTful冪等性的理解:http://www.oschina.net/translate/put-or-post

簡單來說,如果對象在請求的過程中會發生變化(以Java為例子,屬性被修改了),那么此是非冪等的。多次重復請求,結果還是不變的話,那么就是冪等的。

PUT用于冪等請求,因此在更新的時候把所有的屬性都寫完整,那么多次請求后,我們其他屬性是不會變的

在上邊的文章中,冪等被翻譯成“狀態統一性”。這就更好地理解了。

其實一般的架構并不能完全支持RESTful的,因此,只要我們的系統支持RESTful的某些功能,我們一般就稱作為支持RESTful架構

url的RESTful實現

非RESTful的http的url:http://localhost:8080/items/editItems.action?id=1&….

RESTful的url是簡潔的:http:// localhost:8080/items/editItems/1

更改DispatcherServlet的配置

從上面我們可以發現,url并沒有.action后綴的,因此我們要修改核心分配器的配置

<!-- restful的配置 --><servlet><servlet-name>springmvc_rest</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 加載springmvc配置 --><init-param><param-name>contextConfigLocation</param-name><!-- 配置文件的地址 如果不配置contextConfigLocation, 默認查找的配置文件名稱classpath下的:servlet名稱+"-serlvet.xml"即:springmvc-serlvet.xml --><param-value>classpath:spring/springmvc.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>springmvc_rest</servlet-name><!-- rest方式配置為/ --><url-pattern>/</url-pattern></servlet-mapping>

在Controller上使用PathVariable注解來綁定對應的參數

//根據商品id查看商品信息rest接口//@RequestMapping中指定restful方式的url中的參數,參數需要用{}包起來//@PathVariable將url中的{}包起參數和形參進行綁定@RequestMapping("/viewItems/{id}")public @ResponseBody ItemsCustom viewItems(@PathVariable("id") Integer id) throws Exception{//調用 service查詢商品信息ItemsCustom itemsCustom = itemsService.findItemsById(id);return itemsCustom;}

當DispatcherServlet攔截/開頭的所有請求,對靜態資源的訪問就報錯:我們需要配置對靜態資源的解析

<!-- 靜態資源 解析 --><mvc:resources location="/js/" mapping="/js/**" /><mvc:resources location="/img/" mapping="/img/**" />

/**就表示不管有多少層,都對其進行解析,/*代表的是當前層的所有資源..


SpringMVC攔截器

在Struts2中攔截器就是我們當時的核心,原來在SpringMVC中也是有攔截器的

用戶請求到DispatherServlet中,DispatherServlet調用HandlerMapping查找Handler,HandlerMapping返回一個攔截的鏈兒(多個攔截),springmvc中的攔截器是通過HandlerMapping發起的。

實現攔截器的接口:

public class HandlerInterceptor1 implements HandlerInterceptor {//在執行handler之前來執行的//用于用戶認證校驗、用戶權限校驗@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {System.out.println("HandlerInterceptor1...preHandle");//如果返回false表示攔截不繼續執行handler,如果返回true表示放行return false;}//在執行handler返回modelAndView之前來執行//如果需要向頁面提供一些公用 的數據或配置一些視圖信息,使用此方法實現 從modelAndView入手@Overridepublic void postHandle(HttpServletRequest request,HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {System.out.println("HandlerInterceptor1...postHandle");}//執行handler之后執行此方法//作系統 統一異常處理,進行方法執行性能監控,在preHandle中設置一個時間點,在afterCompletion設置一個時間,兩個時間點的差就是執行時長//實現 系統 統一日志記錄@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex)throws Exception {System.out.println("HandlerInterceptor1...afterCompletion");}}

配置攔截器

<!--攔截器 --><mvc:interceptors><!--多個攔截器,順序執行 --><!-- <mvc:interceptor><mvc:mapping path="/**" /><bean class="cn.itcast.ssm.controller.interceptor.HandlerInterceptor1"></bean></mvc:interceptor><mvc:interceptor><mvc:mapping path="/**" /><bean class="cn.itcast.ssm.controller.interceptor.HandlerInterceptor2"></bean></mvc:interceptor> --><mvc:interceptor><!-- /**可以攔截路徑不管多少層 --><mvc:mapping path="/**" /><bean class="cn.itcast.ssm.controller.interceptor.LoginInterceptor"></bean></mvc:interceptor></mvc:interceptors>

測試執行順序

如果兩個攔截器都放行

測試結果: HandlerInterceptor1...preHandle HandlerInterceptor2...preHandleHandlerInterceptor2...postHandle HandlerInterceptor1...postHandleHandlerInterceptor2...afterCompletion HandlerInterceptor1...afterCompletion總結: 執行preHandle是順序執行。 執行postHandle、afterCompletion是倒序執行

1 號放行和2號不放行

測試結果: HandlerInterceptor1...preHandle HandlerInterceptor2...preHandle HandlerInterceptor1...afterCompletion總結: 如果preHandle不放行,postHandle、afterCompletion都不執行。 只要有一個攔截器不放行,controller不能執行完成

1 號不放行和2號不放行

測試結果: HandlerInterceptor1...preHandle 總結: 只有前邊的攔截器preHandle方法放行,下邊的攔截器的preHandle才執行。

日志攔截器或異常攔截器要求

  • 將日志攔截器或異常攔截器放在攔截器鏈兒中第一個位置,且preHandle方法放行

攔截器應用-身份認證

攔截器攔截

public class LoginInterceptor implements HandlerInterceptor {//在執行handler之前來執行的//用于用戶認證校驗、用戶權限校驗@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {//得到請求的urlString url = request.getRequestURI();//判斷是否是公開 地址//實際開發中需要公開 地址配置在配置文件中//...if(url.indexOf("login.action")>=0){//如果是公開 地址則放行return true;}//判斷用戶身份在session中是否存在HttpSession session = request.getSession();String usercode = (String) session.getAttribute("usercode");//如果用戶身份在session中存在放行if(usercode!=null){return true;}//執行到這里攔截,跳轉到登陸頁面,用戶進行身份認證request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);//如果返回false表示攔截不繼續執行handler,如果返回true表示放行return false;}//在執行handler返回modelAndView之前來執行//如果需要向頁面提供一些公用 的數據或配置一些視圖信息,使用此方法實現 從modelAndView入手@Overridepublic void postHandle(HttpServletRequest request,HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {System.out.println("HandlerInterceptor1...postHandle");}//執行handler之后執行此方法//作系統 統一異常處理,進行方法執行性能監控,在preHandle中設置一個時間點,在afterCompletion設置一個時間,兩個時間點的差就是執行時長//實現 系統 統一日志記錄@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex)throws Exception {System.out.println("HandlerInterceptor1...afterCompletion");}}

Controller

@Controller public class LoginController {//用戶登陸提交方法@RequestMapping("/login")public String login(HttpSession session, String usercode,String password)throws Exception{//調用service校驗用戶賬號和密碼的正確性//..//如果service校驗通過,將用戶身份記錄到sessionsession.setAttribute("usercode", usercode);//重定向到商品查詢頁面return "redirect:/items/queryItems.action";}//用戶退出@RequestMapping("/logout")public String logout(HttpSession session)throws Exception{//session失效session.invalidate();//重定向到商品查詢頁面return "redirect:/items/queryItems.action";}}

總結

  • 使用Spring的校驗方式就是將要校驗的屬性前邊加上注解聲明。
  • 在Controller中的方法參數上加上@Validation注解。那么SpringMVC內部就會幫我們對其進行處理(創建對應的bean,加載配置文件)
  • BindingResult可以拿到我們校驗錯誤的提示
  • 分組校驗就是將讓我們的校驗更加靈活:某方法需要校驗這個屬性,而某方法不用校驗該屬性。我們就可以使用分組校驗了。
  • 對于處理異常,SpringMVC是用一個統一的異常處理器類的。實現了HandlerExceptionResolver接口。
  • 對模塊細分多個異常類,都交由我們的統一異常處理器類進行處理。
  • 對于RESTful規范,我們可以使用SpringMVC簡單地支持的。將SpringMVC的攔截.action改成是任意的。同時,如果是靜態的資源文件,我們應該設置不攔截。
  • 對于url上的參數,我們可以使用@PathVariable將url中的{}包起參數和形參進行綁定
  • SpringMVC的攔截器和Struts2的攔截器差不多。不過SpringMVC的攔截器配置起來比Struts2的要簡單。
    • 至于他們的攔截器鏈的調用順序,和Filter的是沒有差別的。

如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y

總結

以上是生活随笔為你收集整理的SpringMVC【校验器、统一处理异常、RESTful、拦截器】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。