SpringMVC中的JSR303與攔截器的使用方法
一,JSR303的概念
JSR303是Java中的一個(gè)標(biāo)準(zhǔn),用于驗(yàn)證和校驗(yàn)JavaBean對(duì)象的屬性的合法性。它提供了一組用于定義驗(yàn)證規(guī)則的注解,如@NotNull、@Min、@Max等。在Spring MVC中,可以使用JSR303注解對(duì)請(qǐng)求參數(shù)進(jìn)行校驗(yàn)。
1.2 為什么要使用JSR303?(更加理解)
前端不是已經(jīng)校驗(yàn)過(guò)數(shù)據(jù)了嗎?為什么我們還要做校驗(yàn)?zāi)?,直接用不就好了?草率了,假如說(shuō)前端代碼校驗(yàn)沒(méi)寫(xiě)好又或者是對(duì)于會(huì)一點(diǎn)編程的人來(lái)說(shuō),直接繞過(guò)前端發(fā)請(qǐng)求(通過(guò)類(lèi)似Postman這樣的測(cè)試工具進(jìn)行非常數(shù)據(jù)請(qǐng)求),把一些錯(cuò)誤的參數(shù)傳過(guò)來(lái),你后端代碼不就危險(xiǎn)了嘛
所以我們一般都是前端一套校驗(yàn),后端在一套校驗(yàn),這樣安全性就能夠大大得到提升了。
1.3 常用的注解
在上面JSR303的概念中也指到了一些注解,以下是注解的詳細(xì)概述
注解 | 說(shuō)明 |
---|---|
@Null | 用于驗(yàn)證對(duì)象為null |
@NotNull | 用于對(duì)象不能為null,無(wú)法查檢長(zhǎng)度為0的字符串 |
@NotBlank | 只用于String類(lèi)型上,不能為null且trim()之后的size>0 |
@NotEmpty | 用于集合類(lèi)、String類(lèi)不能為null,且size>0。但是帶有空格的字符串校驗(yàn)不出來(lái) |
@Size | 用于對(duì)象(Array,Collection,Map,String)長(zhǎng)度是否在給定的范圍之內(nèi) |
@Length | 用于String對(duì)象的大小必須在指定的范圍內(nèi) |
@Pattern | 用于String對(duì)象是否符合正則表達(dá)式的規(guī)則 |
用于String對(duì)象是否符合郵箱格式 | |
@Min | 用于Number和String對(duì)象是否大等于指定的值 |
@Max | 用于Number和String對(duì)象是否小等于指定的值 |
@AssertTrue | 用于Boolean對(duì)象是否為true |
@AssertFalse | 用于Boolean對(duì)象是否為false |
1.4 @Validated與@Valid區(qū)別
@Validated:
Spring提供的
支持分組校驗(yàn)
可以用在類(lèi)型、方法和方法參數(shù)上。但是不能用在成員屬性(字段)上
由于無(wú)法加在成員屬性(字段)上,所以無(wú)法單獨(dú)完成級(jí)聯(lián)校驗(yàn),需要配合@Valid
@Valid:
JDK提供的(標(biāo)準(zhǔn)JSR-303規(guī)范)
不支持分組校驗(yàn)
可以用在方法、構(gòu)造函數(shù)、方法參數(shù)和成員屬性(字段)上
可以加在成員屬性(字段)上,能夠獨(dú)自完成級(jí)聯(lián)校驗(yàn)
二,JSR303使用
2.1 導(dǎo)入pom.xml依賴(lài)
<!-- JSR303 --> <hibernate.validator.version>6.0.7.Final</hibernate.validator.version> <!-- JSR303 --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>${hibernate.validator.version}</version> </dependency>
2.2 配置校驗(yàn)規(guī)則
package com.Bingzy.model; import lombok.ToString; import org.hibernate.validator.constraints.NotBlank; @ToString public class Tbook { @ToString public class Clazz { @NotNull(message = "書(shū)籍編號(hào)不能為空") protected Integer bid; @NotBlank(message = "書(shū)籍名不能為空") protected String bname; @NotBlank(message = "書(shū)籍價(jià)格不能為空") protected Float price; public Clazz(String bid, String bname, Float price) { this.bid = bid; this.bname = bname; this.price = price; } public String getBid() { return bid; } public void setBid(String bid) { this.bid = bid; } public String getBname() { return bname; } public void setBname(String bname) { this.bname = bname; } public Float getPrice() { return price; } public void setPrice(Float price) { this.price = price; } @Override public String toString() { return "Clazz{" + "bid='" + bid + '\'' + ", bname='" + bname + '\'' + ", price=" + price + '}'; } } }
2.3 入門(mén)案例
在請(qǐng)求處理方法中,使用@Validated或@Valid注解要驗(yàn)證的對(duì)象,并根據(jù)BindingResult判斷校驗(yàn)是否通過(guò)。
// 給數(shù)據(jù)添加服務(wù)端校驗(yàn) @RequestMapping("/valiAdd") public String valiAdd(@Validated Tbook tbook, BindingResult result, HttpServletRequest req){ // 如果服務(wù)端驗(yàn)證不通過(guò),有錯(cuò)誤 if(result.hasErrors()){ // 服務(wù)端驗(yàn)證了實(shí)體類(lèi)的多個(gè)屬性,多個(gè)屬性都沒(méi)有驗(yàn)證通過(guò) List<FieldError> fieldErrors = result.getFieldErrors(); Map<String,Object> map = new HashMap<>(); for (FieldError fieldError : fieldErrors) { // 將多個(gè)屬性的驗(yàn)證失敗信息輸送到控制臺(tái) System.out.println(fieldError.getField() + ":" + fieldError.getDefaultMessage()); map.put(fieldError.getField(),fieldError.getDefaultMessage()); } req.setAttribute("errorMap",map); }else { this.tbookBiz.insertSelective(tbook); return "redirect:list"; } return "book/edit"; }
edit.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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> <center> 編輯界面 <form action="${pageContext.request.contextPath }/${empty b ? 'book/valiAdd' : 'book/edit'}" method="post"><br> 書(shū)籍id:<input type="text" name="bid" value="${b.bid }"><span style="color: red">${errorMap.bid}</span><br> 書(shū)籍名稱(chēng):<input type="text" name="bname" value="${b.bname }"><span style="color: red">${errorMap.bname}</span><br> 書(shū)籍價(jià)格:<input type="text" name="price" value="${b.price }"><span style="color: red">${errorMap.price}</span><br> <input type="submit"> </form> </center> </body> </html>
運(yùn)行結(jié)果:
點(diǎn)擊新增或修改,進(jìn)入頁(yè)面后點(diǎn)擊提交顯示相對(duì)應(yīng)的提示語(yǔ)句
三,攔截器
3.1 什么是攔截器?
Spring MVC攔截器是Spring框架中的一個(gè)組件,用于攔截請(qǐng)求并在請(qǐng)求處理之前或之后執(zhí)行一些額外的操作。它可以用于實(shí)現(xiàn)一些通用的、與業(yè)務(wù)無(wú)關(guān)的功能,如日志記錄、權(quán)限驗(yàn)證、異常處理、跨域請(qǐng)求處理等。
攔截器在請(qǐng)求到達(dá)DispatcherServlet之后,但在具體的Controller方法執(zhí)行之前,提供了一個(gè)攔截點(diǎn),可以對(duì)請(qǐng)求進(jìn)行處理和干預(yù)。攔截器可以攔截請(qǐng)求、響應(yīng)或會(huì)話(huà)的各個(gè)階段,并在每個(gè)階段執(zhí)行預(yù)定義的操作。
3.2 什么是過(guò)濾器
依賴(lài)于servlet容器。在實(shí)現(xiàn)上基于函數(shù)回調(diào),可以對(duì)幾乎所有請(qǐng)求進(jìn)行過(guò)濾,但是缺點(diǎn)是一個(gè)過(guò)濾器實(shí)例只能在容器初始化時(shí)調(diào)用一次。使用過(guò)濾器的目的是用來(lái)做一些過(guò)濾操作,比如:在過(guò)濾器中修改字符編碼;在過(guò)濾器中修改HttpServletRequest的一些參數(shù),包括:過(guò)濾低俗文字、危險(xiǎn)字符等
3.3 攔截器與過(guò)濾器的區(qū)別?
過(guò)濾器(filter)
1.filter屬于Servlet技術(shù),只要是web工程都可以使用
2.filter主要由于對(duì)所有請(qǐng)求過(guò)濾
3.filter的執(zhí)行時(shí)機(jī)早于Interceptor
攔截器(interceptor)
1.interceptor屬于SpringMVC技術(shù),必須要有SpringMVC環(huán)境才可以使用
2.interceptor通常由于對(duì)處理器Controller進(jìn)行攔截
3.interceptor只能攔截dispatcherServlet處理的請(qǐng)求
3.4 應(yīng)用場(chǎng)景
日志記錄:記錄請(qǐng)求信息的日志,以便進(jìn)行信息監(jiān)控、信息統(tǒng)計(jì)、計(jì)算PV(Page View)等。
權(quán)限檢查:如登錄檢測(cè),進(jìn)入處理器檢測(cè)是否登錄,如果沒(méi)有直接返回到登錄頁(yè)面;
性能監(jiān)控:有時(shí)候系統(tǒng)在某段時(shí)間莫名其妙的慢,可以通過(guò)攔截器在進(jìn)入處理器之前記錄開(kāi)始時(shí)間,在處理完后記錄結(jié)束時(shí)間,從而得到該請(qǐng)求的處理時(shí)間(如果有反向代理,如apache可以自動(dòng)記錄);
通用行為:讀取cookie得到用戶(hù)信息并將用戶(hù)對(duì)象放入請(qǐng)求,從而方便后續(xù)流程使用,還有如提取Locale、Theme信息等,只要是多個(gè)Controller中的處理方法都需要的,我們就可以使用攔截器實(shí)現(xiàn)
四,攔截器快速入門(mén)
定義一個(gè)包并創(chuàng)建OneInterceptor類(lèi)
攔截器(interceptor):
package com.Bingzy.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class OneInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("【OneInterceptor】:preHandle..."); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("【OneInterceptor】:postHandle..."); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("【OneInterceptor】:afterCompletion..."); } }
spring-mvc.xml配置自定義攔截器
<mvc:interceptors> <bean class="com.Bingzy.interceptor.OneInterceptor"></bean> </mvc:interceptors>
在攔截器(interceptor)中的preHandle()方法中的返回值為true未攔截的情況:
在攔截器(interceptor)中的preHandle()方法中的返回值為false攔截的情況:
注意:攔截器會(huì)根據(jù)preHandle()方法返回值進(jìn)行攔截判斷,返回了一個(gè)true
值。這個(gè)返回值表示該攔截器已經(jīng)處理了當(dāng)前的請(qǐng)求,并且可以繼續(xù)向下傳遞請(qǐng)求。如果返回false
,則表示該攔截器不處理當(dāng)前請(qǐng)求,請(qǐng)求將被終止
4.1 攔截器原理圖
preHandle:用于對(duì)攔截到的請(qǐng)求進(jìn)行預(yù)處理,方法接收布爾(true,false)類(lèi)型的返回值,返回true:放行,false:不放行。
執(zhí)行時(shí)機(jī):在處理器方法執(zhí)行前執(zhí)行
方法參數(shù)
參數(shù) 說(shuō)明 request 請(qǐng)求對(duì)象 response 響應(yīng)對(duì)象 handler 攔截到的方法處理 postHandle:用于對(duì)攔截到的請(qǐng)求進(jìn)行后處理,可以在方法中對(duì)模型數(shù)據(jù)和視圖進(jìn)行修改
執(zhí)行時(shí)機(jī):在處理器的方法執(zhí)行后,視圖渲染之前
方法參數(shù)
參數(shù) 說(shuō)明 request 請(qǐng)求對(duì)象 response 響應(yīng)對(duì)象 handler 攔截到的處理器方法 ModelAndView 處理器方法返回的模型和視圖對(duì)象,可以在方法中修改模型和視圖 afterCompletion:用于在整個(gè)流程完成之后進(jìn)行最后的處理,如果請(qǐng)求流程中有異常,可以在方法中獲取對(duì)象
執(zhí)行時(shí)機(jī):視圖渲染完成后(整個(gè)流程結(jié)束之后)
方法參數(shù)
參數(shù) 說(shuō)明 request 請(qǐng)求參數(shù) response 響應(yīng)對(duì)象 handler 攔截到的處理器方法 ex 異常對(duì)象
4.2 攔截器鏈
如果多個(gè)攔截器能夠?qū)ο嗤恼?qǐng)求進(jìn)行攔截,則多個(gè)攔截器會(huì)形成一個(gè)攔截器鏈,主要理解攔截器鏈中各個(gè)攔截器的執(zhí)行順序。攔截器鏈中多個(gè)攔截器的執(zhí)行順序,根攔截器的配置順序有關(guān),先配置的先執(zhí)行
攔截器(interceptor)
package com.Bingzy.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TwoInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("【TwoInterceptor】:preHandle..."); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("【TwoInterceptor】:postHandle..."); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("【TwoInterceptor】:afterCompletion..."); } }
spring-mvc.xml配置自定義攔截器
<mvc:interceptors> <!--2) 多攔截器(攔截器鏈)--> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.Bingzy.interceptor.OneInterceptor"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/book/**"/> <bean class="com.Bingzy.interceptor.TwoInterceptor"/> </mvc:interceptor> </mvc:interceptors>
運(yùn)行展示:
五,用戶(hù)登錄權(quán)限案例
登入攔截器(interceptor):
package com.Bingzy.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("【implements】:preHandle..."); StringBuffer url = request.getRequestURL(); if (url.indexOf("/login") > 0 || url.indexOf("/logout") > 0){ // 如果是 登錄、退出 中的一種 return true; } // 代表不是登錄,也不是退出 // 除了登錄、退出,其他操作都需要判斷是否 session 登錄成功過(guò) String bname = (String) request.getSession().getAttribute("bname"); if (bname == null || "".equals(bname)){ response.sendRedirect("/page/book/login"); return false; } return true; } }
spring-mvc.xml配置自定義登入攔截器
<mvc:interceptors> <bean class="com.Bingzy.interceptor.LoginInterceptor"></bean> </mvc:interceptors>
Controller層(web):
package com.Bingzy.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; @Controller public class LoginController { @RequestMapping("/login") public String login(HttpServletRequest req){ String bname = req.getParameter("bname"); HttpSession session = req.getSession(); if ("zs".equals(bname)){ session.setAttribute("bname",bname); } return "redirect:/book/list"; } @RequestMapping("/logout") public String logout(HttpServletRequest req){ req.getSession().invalidate(); return "redirect:/book/list"; } }
login.jsp:
簡(jiǎn)單的測(cè)試布局,可自行布局
測(cè)試結(jié)果:
總結(jié):
如果用戶(hù)發(fā)送URL中的后綴包含"/login"或"/logout",則表示當(dāng)前請(qǐng)求是登錄或退出操作,直接返回true表示繼續(xù)處理請(qǐng)求,后端進(jìn)行判斷“uname”是否為“zs”,如果不是zs則域?qū)ο蟛粫?huì)保存,從而到攔截器判斷域?qū)ο鬄榭談t會(huì)重定向到登良頁(yè)面,如果不為空就執(zhí)行后端返回的字符串到視圖解析器解析跳轉(zhuǎn)指定頁(yè)面
到此這篇關(guān)于SpringMVC中的JSR303與攔截器的使用方法的文章就介紹到這了,更多相關(guān)SpringMVC JSR303與攔截器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Springboot集成JSR303參數(shù)校驗(yàn)的方法實(shí)現(xiàn)
- Spring Boot利用JSR303實(shí)現(xiàn)參數(shù)驗(yàn)證的方法實(shí)例
- SpringBoot結(jié)合JSR303對(duì)前端數(shù)據(jù)進(jìn)行校驗(yàn)的示例代碼
- SpringBoot使用jsr303校驗(yàn)的實(shí)現(xiàn)
- Spring中使用JSR303請(qǐng)求約束判空的實(shí)現(xiàn)
- SpringBoot后端進(jìn)行數(shù)據(jù)校驗(yàn)JSR303的使用詳解
- springboot接口參數(shù)校驗(yàn)JSR303的實(shí)現(xiàn)
- springboot整合JSR303參數(shù)校驗(yàn)與全局異常處理的方法
- springboot整合JSR303校驗(yàn)功能實(shí)現(xiàn)代碼
相關(guān)文章
深入理解Java class文件格式_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
對(duì)于理解JVM和深入理解Java語(yǔ)言, 學(xué)習(xí)并了解class文件的格式都是必須要掌握的功課2017-06-06Java中Process類(lèi)的使用與注意事項(xiàng)說(shuō)明
這篇文章主要介紹了Java中Process類(lèi)的使用與注意事項(xiàng)說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12java使用bitmap實(shí)現(xiàn)可回收自增id的示例
本文主要介紹了java使用bitmap實(shí)現(xiàn)可回收自增id的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-10-10Springboot攔截器如何獲取@RequestBody參數(shù)
這篇文章主要介紹了Springboot攔截器如何獲取@RequestBody參數(shù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06

SpringBoot+mybatis實(shí)現(xiàn)多數(shù)據(jù)源支持操作

java 反射getClass .class 的使用方法示例

Spring實(shí)戰(zhàn)之@Autowire注解用法詳解

Spring Boot集成Spring Cloud Security進(jìn)行安全增強(qiáng)的方法