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

