SpringMVC中的常用注解源碼及解析
用于配置控制器的注解
@Controller
該注解用用于修飾表現(xiàn)層控制器的注解
源碼
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Controller { // 用于指定存入IOC容器是Bean的唯一標識 @AliasFor(annotation = Component.class) String value() default ""; }
@RestController
該注解具備@Controller注解的全部功能,同時多了一個@ResponseBody注解的功能
源碼
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Controller @ResponseBody public @interface RestController { // 用于指定存入ioc容器時bean的唯一標識。 @since 4.0.1 @AliasFor(annotation = Controller.class) String value() default ""; }
用于提供方法映射的注解
@RequestMapping
該注解用于建立請求URL和處理請求方法之間的對應(yīng)關(guān)系
注解在類上: 請求URL的第一級訪問目錄. 如果沒有的話, 就相當(dāng)于從應(yīng)用根目錄開始. 放在類上的目的就是為了將URL可以按照模塊化管理.
源碼以及解析
package org.springframework.web.bind.annotation; @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping public @interface RequestMapping { // 給當(dāng)前url 提供一個名稱 String name() default ""; // value: 用于指定請求的URL . 和path屬性作用一樣 // 注意: 該屬性的值 前邊加不加 "/" 都是一樣的. @AliasFor("path") String[] value() default {}; // 4.2 版本中加入的注解 和value屬性一樣 // @since 4.2 @AliasFor("value") String[] path() default {}; // method:用于指定請求的方式。它支持以下這些類型: // GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE. // 是通過RequestMethod枚舉指定的 RequestMethod[] method() default {}; // params:用于指定限制請求參數(shù)的條件。它支持簡單的表達式。 // 要求請求參數(shù)的key和value必須和配置的一模一樣。 // 示例: params = {"accountName"},表示請求參數(shù)必須有accountName // params = {"moeny!100"},表示請求參數(shù)中money不能是100。 String[] params() default {}; // headers:用于指定限制請求消息頭的條件。 // 示例: RequestMapping(value = "/something", headers = "content-type=text/*") String[] headers() default {}; // consumes:用于指定可以接收的請求正文類型(MIME類型) // 示例: consumes = "text/plain" , consumes = {"text/plain", "application/*"} String[] consumes() default {}; // produces:用于指定可以生成的響應(yīng)正文類型。(MIME類型) // produces = "text/plain" // produces = {"text/plain", "application/*"} // produces = MediaType.APPLICATION_JSON_UTF8_VALUE String[] produces() default {}; }
@GetMapping 、@PostMapping、 @PutMapping 、@DeleteMapping 、是@RequestMapping 注解的衍生注解
除了method指定以外 , 其他和@RequestMapping 相同
可以看下源碼@PostMapping示例
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @RequestMapping( method = {RequestMethod.POST} ) public @interface PostMapping {
增強控制器方法的注解
@ModelAttribute
它可以用于修飾方法,或者是參數(shù)。
- 當(dāng)修飾方法時,表示執(zhí)行控制器方法之前,被此注解修飾的方法都會執(zhí)行。
- 當(dāng)修飾參數(shù)時,用于獲取指定的數(shù)據(jù)給參數(shù)賦值。
@Controller public class ModelAttributeController { @ModelAttribute("username") public String showModel(String username){ System.out.println("showModel method name is "+username); username = username + "aaa"; return username; } @RequestMapping("/useModelAttribute") public String useModelAttribute(@ModelAttribute("username") String username){ System.out.println("controller method name is "+username); return "success"; } }
測試結(jié)果
showModel method name is test
controller method name is testaaa
success.jsp執(zhí)行了
@ExceptionHandler
用于注釋方法,表明當(dāng)前方法是控制器執(zhí)行產(chǎn)生異常后的處理方法.
示例:
自定義異常
package com.exception; /** * 自定義異常(處理業(yè)務(wù)異常) */ public class CustomerException extends Exception{ private String message; public CustomerException(String message){ this.message = message; } @Override public String getMessage() { return message; } }
異常后處理類
@ControllerAdvice public class ExceptionHandlerAdvice { @ExceptionHandler(Exception.class) public String handleException(Model model, Exception e){ String errorMsg = ""; //判斷Exception的類型是不是CustomerException if(e instanceof CustomerException){ errorMsg = e.getMessage(); }else { //系統(tǒng)異常 errorMsg = "服務(wù)器內(nèi)部錯誤,請聯(lián)系管理員!"; } model.addAttribute("errorMsg",errorMsg); return "error"; } }
接口控制器類
package com.web.controller; @ControllerAdvice public class ExceptionHandlerAdvice { @ExceptionHandler(Exception.class) public String handleException(Model model, Exception e){ String errorMsg = ""; //判斷Exception的類型是不是CustomerException if(e instanceof CustomerException){ errorMsg = e.getMessage(); }else { //系統(tǒng)異常 errorMsg = "服務(wù)器內(nèi)部錯誤,請聯(lián)系管理員!"; } model.addAttribute("errorMsg",errorMsg); return "error"; } }
測試
<%-- ExceptionHandler注解的使用--%> <a href="useExceptionHandler?age=111" rel="external nofollow" >ExcpetionHandler注解的使用</a> <hr/>
@InitBinder
用于初始化表單請求參數(shù)的數(shù)據(jù)綁定器。
給控制器方法提供通知的注解
@ControllerAdive
用于給控制器提供一個增強的通知。
@RestControllerAdive
它和@ControllerAdvice注解的作用一樣,并且支持@ResponseBody的功能
用于綁定控制器方法參數(shù)的注解
@RequestParam
此注解是從請求正文中獲取請求參數(shù),給控制器方法形參賦值的 當(dāng)請求參數(shù)的名稱和控制器方法形參變量名稱一致時,無須使用此注解。 當(dāng)沒有獲取到請求參數(shù)時,此注解還可以給控制器方法形參提供默認值。 只能用在方法的參數(shù)上.
示例:
@RequestMapping("/useRequestParam") public String useRequestParam(@RequestParam(value = "page",defaultValue = "10") int page){ System.out.println("當(dāng)前頁是:"+page); return "success"; }
@RequestBody
該注解用于讀取 Request 請求的 body 部分數(shù)據(jù),使用系統(tǒng)默認配置的 HttpMessageConverter 進行解析,然后把相應(yīng)的數(shù)據(jù)綁定到要返回的對象上; 再把 HttpMessageConverter 返回的對象數(shù)據(jù)綁定到 controller 中方法的參數(shù)上。
也就是說,如果是 json 格式的數(shù)據(jù),我們要傳入的參數(shù)是一個對象,那就必須使用 @RequestBody
。
示例:
@RequestMapping("/useRequestBody") public String useRequestBody(@RequestBody(required = false) User user){ //System.out.println("不支持跨域 user is "+user); System.out.println(" user is "+user); return "success"; }
測試頁面
<a href="#" rel="external nofollow" id="useRequestBodyAjax">RequestBody注解的使用</a> <%-- RequestBody注解的使用--%> <script src="js/jquery-2.2.3.min.js"></script> <%-- <script src="${pageContext.request.contextPath}/js/jquery-2.2.3.min.js"></script>--%> <script type="text/javascript"> //頁面加載事件 $(function () { //給Id為useRequestBodyAjax超鏈接綁定一個點擊事件 $("#useRequestBodyAjax").click(function () { alert("點擊事件綁定成功"); $.ajax({ url: "useRequestBody", type: "post", // data:"username=test&age=18&gender=male", data: '{"username":"test","age":25,"gender":"male"}',//json contentType: "application/json", dataType: "text", success: function (data) { alert(data); } }); }); }) </script>
@RequestHeader
該注解是從請求消息頭中獲取消息頭的值,并把值賦給控制器方法形參。
注意: 它只能出現(xiàn)在方法的參數(shù)上
@RequestMapping("/useRequestHeader") public String useRequestHeader (@RequestHeader(value = "Accept-Language",required = false,defaultValue = "test") String header) { System.out.println("Accept-Language:"+header); return "success"; }
@CookieValue
從請求消息頭中獲取Cookie的值,并把值賦給控制器方法形參。
屬性:
- name = value cookie的key名稱
- required boolean 是否必須
- defaultValue 默認值
@CookieValue(value = "JSESSIONID" , required = true, defaultValue = "")
示例:
@RequestMapping("/useCookieValue") public String useCookieValue(@CookieValue("JSESSIONID") String jsessionid){ System.out.println(jsessionid); return "success"; }
@PathVariable
restful 該注解是springmvc框架支持rest風(fēng)格url的標識。用于獲取請求url映射中占位符對應(yīng)的值。
示例
@RequestMapping(method = RequestMethod.PUT,value = "/{id}") public String update(@PathVariable Integer id, User user){ //1.給user的id賦值 user.setId(id); //2.輸出 System.out.println("user is "+user); return "success"; }
改變響應(yīng)方式的注解
@SessionAttributes
- 通過此注解即可實現(xiàn)把數(shù)據(jù)存入會話域,而無需在使用HttpSession的setAttribute方法。
- 當(dāng)在控制器方法形參中加入Model或者ModelMap類型參數(shù)時,默認是存入請求域的。
- 但當(dāng)控制器上使用了此注解,就會往會話域中添加數(shù)據(jù)。
package com.web.controller; /** * SessionAttribute和SessionAttributes注解的使用 */ @Controller @SessionAttributes(value = {"message"}) public class SessionAttributesController { /** * 往session域中存入數(shù)據(jù) * 在沒有SessionAttributes注解時,當(dāng)控制器方法的參數(shù)有Model,ModelMap時是默認往請求域中存入數(shù)據(jù) * @return */ @RequestMapping("/useSessionAttributes") public String useSessionAttributes(Model model){ model.addAttribute("message","存入請求域的數(shù)據(jù)"); return "success"; } @RequestMapping("/useSessionAttribute") public String useSessionAttribute(HttpServletRequest request,@SessionAttribute(value = "message",required = false) String message){ System.out.println(message); System.out.println("request attribute "+request.getAttribute("message")); return "success"; } }
@SessionAttributes 往會話域中存數(shù)據(jù)
@SessionAttribute 從會話域中取數(shù)據(jù)
@ResponeBody
用于用流輸出響應(yīng)正文
將方法的返回值,以特定的格式寫入到response的body區(qū)域,進而將數(shù)據(jù)返回給客戶端。
- 當(dāng)方法上面沒有寫ResponseBody,底層會將方法的返回值封裝為ModelAndView對象。
- 如果返回值是字符串,那么直接將字符串寫到客戶端;
- 如果是一個對象,會將對象轉(zhuǎn)化為json串,然后寫到客戶端。
@RequestMapping("/useResponseBody") public String useResponseBody(){ return "use response body"; }
提供跨域訪問
@CrossOrigin
跨域訪問
當(dāng)一個域名請求另一個域名的資源時, 就是跨域 (協(xié)議,主機名, 端口任何一個不相同就是跨域)
域名模擬 C:/Windows/System32/drivers/ect/hosts(文件)
修改該文件,建立Ip和域名的對應(yīng)關(guān)系
如何刷新域名不重啟計算機
cmd命令行輸入:
ipconfig /displaydns
ipconfig /flushdns
跨域請求中,請求時可以正常發(fā)出去,并且服務(wù)端也可以收到. 問題出在了響應(yīng)身上,通過修改服務(wù)端的響應(yīng)頭就可以解決跨域問題.
解決跨域問題,不使用@CrossOrigin注解的解決辦法-添加跨域過濾器
package com.filters; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class CrossOriginFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { try{ HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse)res; System.out.println("解決跨域問題的過濾器執(zhí)行了"); //設(shè)置response的響應(yīng)消息頭實現(xiàn)跨域問題的解決 /* 允許跨域的主機地址 */ response.setHeader("Access-Control-Allow-Origin", "*"); /* 允許跨域的請求方法GET, POST, HEAD 等 */ response.setHeader("Access-Control-Allow-Methods", "*"); /* 重新預(yù)檢驗跨域的緩存時間 (s) */ response.setHeader("Access-Control-Max-Age", "3600"); /* 允許跨域的請求頭 */ response.setHeader("Access-Control-Allow-Headers", "*"); /* 是否攜帶cookie */ response.setHeader("Access-Control-Allow-Credentials", "true"); //放行 chain.doFilter(request,response); }catch (Exception e){ e.printStackTrace(); } } @Override public void destroy() { } }
在spring中提供了@CrossOrigin注解來解決跨域問題,
該注解可以放在類上和方法上, 以解決跨域問題.
/** * 跨域訪問的方法 * @param user * @return */ @RequestMapping("/useCrossOrigin") @ResponseBody @CrossOrigin public String useCrossOrigin(@RequestBody(required = false) User user){ System.out.println("user is "+user); return "success"; }
寫在類上表示該類中的所有資源都允許跨域訪問, 寫在方法上表示僅該方法允許跨域訪問.
注意: 一些靜態(tài)資源 例如 img 中的 src , link 中的 href 中的是可以進行跨域訪問的
比如在 一個jsp頁面中 , 如果使用 response.sendRedirect(); 會有跨域問題, 改為 window.location.href = ‘//xxx.xxx.xxx’ 則不會有跨域問題 . (踏平的坑!)
到此這篇關(guān)于SpringMVC中的常用注解源碼及解析的文章就介紹到這了,更多相關(guān)SpringMVC中的常用注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java使用ScriptEngine動態(tài)執(zhí)行代碼(附Java幾種動態(tài)執(zhí)行代碼比較)
這篇文章主要介紹了Java使用ScriptEngine動態(tài)執(zhí)行代碼,并且分享Java幾種動態(tài)執(zhí)行代碼比較,需要的朋友可以參考下2021-04-04SpringBoot自定義HttpMessageConverter操作
這篇文章主要介紹了SpringBoot自定義HttpMessageConverter的操作,具有很好的參考價值,如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08java 中用split分割字符串,最后的空格等不被拆分的方法
下面小編就為大家?guī)硪黄猨ava 中用split分割字符串,最后的空格等不被拆分的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02解決mybatis plus報錯com.microsoft.sqlserver.jdbc.SQLServerE
這篇文章主要介紹了解決mybatis plus報錯com.microsoft.sqlserver.jdbc.SQLServerException:必須執(zhí)行該語句才能獲得結(jié)果,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05Tomcat?8.5?+mysql?5.7+jdk1.8開發(fā)JavaSE的金牌榜小項目
這篇文章主要介紹了Tomcat?8.5?+mysql?5.7+jdk1.8開發(fā)JavaSE的金牌榜小項目,本文通過圖文實例相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-05-05Springboot教程之如何設(shè)置springboot熱重啟
這篇文章主要介紹了Springboot教程之如何設(shè)置springboot熱重啟,本文通過實例圖文相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07