摘要:同時另外一個目的是希望完全屏蔽掉源生,增加它的擴展性。本文我以為例進行講解,因為也是后推出的注解不管從使用和原理上都是一模一樣的。作用從中取對應(yīng)的屬性值。
每篇一句
改我們就改得:取其精華,去其糟粕。否則木有意義前言
如果說知道@SessionAttributes這個注解的人已經(jīng)很少了,那么不需要統(tǒng)計我就可以確定的說:知道@RequestAttribute注解的更是少之又少。我覺得主要有如下兩個原因:
@RequestAttribute這個注解很新,Spring4.3后才有
我們可以使用API調(diào)用的方式(ServletRequest.getAttribute())來達到目的,而不用注解。且成本也不太高
既然Spring推出了這個注解,那必然有它的優(yōu)點。本文就帶大家領(lǐng)略一下它的風(fēng)騷之處。
Spring提供的這些注解比如@ModelAttribute、@SessionAttributes、@RequestAttribute都是為了簡化開發(fā),提高復(fù)用性。同時另外一個目的是希望完全屏蔽掉源生Servlet API,增加它的擴展性。@RequestAttribute本文我以@RequestAttribute為例進行講解,因為@SessionAttribute(也是Spring4.3后推出的注解)不管從使用和原理上都是一模一樣的。你可以理解成唯一區(qū)別是ServletRequest.getAttribute()和HttpSession.getAttribute()的區(qū)別
此處再強調(diào)一次,這里指的是:org.springframework.web.bind.annotation.SessionAttribute,而非org.springframework.web.bind.annotation.SessionAttributes
它比前面介紹的那些@ModelAttribute、@SessionAttributes等注解要簡單很多,它只能使用在方法入?yún)⑸?/strong>。作用:從request中取對應(yīng)的屬性值。
很多小伙伴對getParameter()和getAttribute()相關(guān)方法傻傻分不清楚。建議你可以先弄清楚param和attribute的區(qū)別~
// @since 4.3 @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RequestAttribute { @AliasFor("name") String value() default ""; @AliasFor("value") String name() default ""; // 默認情況下 這個屬性是必須的(沒有就報錯了) boolean required() default true; }
接下來這句話很重要:@RequestAttribute只負責(zé)從request里面取屬性值,至于你什么時候往里放值,是有多種方式的可以達到的:
@ModelAttribute注解預(yù)存
HandlerInterceptor攔截器中預(yù)存
請求轉(zhuǎn)發(fā)帶過來
下面分別按照這三種使用場景,給出使用Demo:
@ModelAttribute注解預(yù)存比較簡單,在@ModelAttribute標(biāo)注的方法上使用源生的HttpServletRequest放值即可
@RestController @RequestMapping public class HelloController { // 放置attr屬性值 @ModelAttribute public Person personModelAttr(HttpServletRequest request) { request.setAttribute("myApplicationName", "fsx-application"); return new Person("非功能方法", 50); } @GetMapping("/testRequestAttr") public void testRequestAttr(@RequestAttribute("myApplicationName") String myApplicationName, HttpServletRequest request, ModelMap modelMap) { System.out.println(myApplicationName); //fsx-application // 從request里獲取 System.out.println(request.getAttribute("myApplicationName")); //fsx-application // 從model里獲取 System.out.println(modelMap.get("myApplicationName")); // null 獲取不到attr屬性的 System.out.println(modelMap.get("person")); // Person(name=非功能方法, age=50) } }
請求/testRequestAttr,結(jié)果打印如下:
fsx-application fsx-application null Person(name=非功能方法, age=50)
這里務(wù)必注意:@RequestAttribute("myApplicationName")注解如果省略,是綁定不到attr屬性的哦(必須要有注解)~
但是,這樣是可行的:@RequestAttribute String myApplicationName(若注解沒有指定,Spring MVC會再去看形參的名字來確認自動綁定)HandlerInterceptor攔截器中預(yù)存
但若你寫成了這樣@RequestAttribute String aaa,那請求就直接400錯誤了拋出異常:org.springframework.web.bind.ServletRequestBindingException
簡單,直接上代碼:
public class SimpleInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { request.setAttribute("myApplicationName", "fsx-application"); return true; } ... }
測試代碼:略。
forward請求轉(zhuǎn)發(fā)帶過來形如這樣:
request.setAttribute("myApplicationName", "fsx-application"); request.getRequestDispatcher("/index").forward(request, response);
其實往里放置屬性值只需要遵循一個原則:在調(diào)用處理器目標(biāo)方法之前(參數(shù)封裝之前)任意地方放置即可,屬性值是都能被取到的。
原理剖析按照我的習(xí)慣,即使它很簡單,我也會扒開來看看它的原理部分嘛。
根據(jù)經(jīng)驗很容易想到解析它的是一個HandlerMethodArgumentResolver,它就是RequestAttributeMethodArgumentResolver
很明顯,它也是@since 4.3才出現(xiàn)的,命名上也很配套嘛。
public class RequestAttributeMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver { // 只處理標(biāo)注了@RequestAttribute注解的入?yún)? @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(RequestAttribute.class); } // 封裝此注解的屬性到NamedValueInfo 這里關(guān)于參數(shù)名的處理有這么一個處理 // info.name.isEmpty()也就說如果自己沒有指定,就用形參名parameter.getParameterName() @Override protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) { RequestAttribute ann = parameter.getParameterAnnotation(RequestAttribute.class); Assert.state(ann != null, "No RequestAttribute annotation"); return new NamedValueInfo(ann.name(), ann.required(), ValueConstants.DEFAULT_NONE); } // 從request請求域去找屬性值 @Override @Nullable protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request){ return request.getAttribute(name, RequestAttributes.SCOPE_REQUEST); } // 若值不存在,拋出異常ServletRequestBindingException @Override protected void handleMissingValue(String name, MethodParameter parameter) throws ServletException { throw new ServletRequestBindingException("Missing request attribute "" + name + "" of type " + parameter.getNestedParameterType().getSimpleName()); } }
源碼短小精悍,非常簡單。
其實它解析入?yún)⒎矫娴暮诵慕馕隽鞒淘谄涓割?b>AbstractNamedValueMethodArgumentResolver身上,但并不是本文的重點,請詳見HandlerMethodArgumentResolver的章節(jié)~
@RequestAttribute屬性required默認為true, request.getAttribute獲取不到參數(shù)就會拋出異常ServletRequestBindingException;required設(shè)置為false,即使沒有從request中獲取到就忽略跳過,賦值為null;總結(jié)
這篇文章介紹了@RequestAttribute的使用Demo,以及它很簡單的原理分析。相較于之前所有文章,這篇是非常輕松的,希望可以提供給大家一個思路,來使用@RequestAttribute提高你的逼格,哈哈(友情提示:裝逼需謹慎哦~)
說明:因為@SessionAttribute的使用甚至原理幾乎一毛一樣,所以不用再重復(fù)篇幅了總結(jié)
這篇文章介紹了@SessionAttributes的核心處理原理,以及也給了一個Demo來介紹它的基本使用,不出意外閱讀下來你對它應(yīng)該是有很好的收獲的,希望能幫助到你簡化開發(fā)~
相關(guān)閱讀從原理層面掌握HandlerMethod、InvocableHandlerMethod、ServletInvocableHandlerMethod的使用【一起學(xué)Spring MVC】
從原理層面掌握@SessionAttributes的使用【一起學(xué)Spring MVC】
從原理層面掌握@ModelAttribute的使用(核心原理篇)【一起學(xué)Spring MVC】
從原理層面掌握@ModelAttribute的使用(使用篇)【一起學(xué)Spring MVC】
==The last:如果覺得本文對你有幫助,不妨點個贊唄。當(dāng)然分享到你的朋友圈讓更多小伙伴看到也是被作者本人許可的~==
**若對技術(shù)內(nèi)容感興趣可以加入wx群交流:Java高工、架構(gòu)師3群。
若群二維碼失效,請加wx號:fsx641385712(或者掃描下方wx二維碼)。并且備注:"java入群" 字樣,會手動邀請入群**
若文章格式混亂或者圖片裂開,請點擊`:原文鏈接-原文鏈接-原文鏈接
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/75947.html
摘要:和一起使用參照博文從原理層面掌握的使用一起學(xué)。至于具體原因,可以移步這里輔助理解從原理層面掌握的使用核心原理篇一起學(xué)再看下面的變種例子重要訪問。 每篇一句 每個人都應(yīng)該想清楚這個問題:你是祖師爺賞飯吃的,還是靠老天爺賞飯吃的 前言 上篇文章 描繪了@ModelAttribute的核心原理,這篇聚焦在場景使用上,演示@ModelAttribute在不同場景下的使用,以及注意事項(當(dāng)然有些...
摘要:見名之意,它是處理器,也就是解析這個注解的核心。管理通過標(biāo)注了的特定會話屬性,存儲最終是委托了來實現(xiàn)。只會清楚注解放進去的,并不清除放進去的它的唯一實現(xiàn)類實現(xiàn)也簡單。在更新時,模型屬性與會話同步,如果缺少,還將添加屬性。 每篇一句 不是你當(dāng)上了火影大家就認可你,而是大家都認可你才能當(dāng)上火影 前言 該注解顧名思義,作用是將Model中的屬性同步到session會話當(dāng)中,方便在下一次請求中...
摘要:雖然它不是必須,但是它是個很好的輔助官方解釋首先看看官方的對它怎么說它將方法參數(shù)方法返回值綁定到的里面。解析注解標(biāo)注的方法參數(shù),并處理標(biāo)注的方法返回值。 每篇一句 我們應(yīng)該做一個:胸中有藍圖,腳底有計劃的人 前言 Spring MVC提供的基于注釋的編程模型,極大的簡化了web應(yīng)用的開發(fā),我們都是受益者。比如我們在@RestController標(biāo)注的Controller控制器組件上用@...
摘要:對于暫存在會話中的用作控制器工作流一部分的模型屬性,要像使用存儲模型屬性到請求共享的會話一節(jié)中描述的那樣使用。 ??本篇示例見這個項目的 mvc 分支下的 SesAndReqAttrController.java ① 使用@SessionAttribute來訪問預(yù)先存在的全局會話屬性 ??如果你需要訪問預(yù)先存在的、以全局方式管理的會話屬性的話,比如在控制器之外(比如通過過濾器)可能或...
摘要:并且,并且如果或者不為空不為且不為,將中斷處理直接返回不再渲染頁面對返回值的處理對返回值的處理是使用完成的對異步處理結(jié)果的處理使用示例文首說了,作為一個非公開,如果你要直接使用起來,還是稍微要費點勁的。 每篇一句 想當(dāng)火影的人沒有近道可尋,當(dāng)上火影的人同樣無路可退 前言 HandlerMethod它作為Spring MVC的非公開API,可能絕大多數(shù)小伙伴都對它比較陌生,但我相信你對它...
閱讀 2809·2021-11-19 11:30
閱讀 3086·2021-11-15 11:39
閱讀 1835·2021-08-03 14:03
閱讀 2017·2019-08-30 14:18
閱讀 2071·2019-08-30 11:16
閱讀 2225·2019-08-29 17:23
閱讀 2631·2019-08-28 18:06
閱讀 2563·2019-08-26 12:22