Each one
We have to change on a whim: its essence, to its dregs. Otherwise meaningful wood
Foreword
If know @SessionAttributes
this comment very few people, you do not need statistics I can say with certainty: Know @RequestAttribute
notes even fewer. I think there are two reasons:
@RequestAttribute
This comment is very new,Spring4.3
only after there- We can use API calls (
ServletRequest.getAttribute()
) to achieve their goals, without comment. And the cost is not too high
Since Spring launched this comment, it must have its advantages. This article will take you a taste of what it's coquettish place.
Spring
These notes offer such as@ModelAttribute
,@SessionAttributes
,@RequestAttribute
is to simplify development, improve reusability. While a further object is to completely shield off the API Primal the Servlet , increase its scalability.
In this paper I have to
@RequestAttribute
explain, for example, because@SessionAttribute
(after Spring4.3 also introduced notes) Whether from the use and principles are exactly the same. You can be understood as the only difference isServletRequest.getAttribute()
andHttpSession.getAttribute()
the difference between
Again here, this case is:org.springframework.web.bind.annotation.SessionAttribute
rather thanorg.springframework.web.bind.annotation.SessionAttributes
@RequestAttribute
It than those previously described @ModelAttribute
, @SessionAttributes
and other notes much simpler, it can only be used in the method to the Senate on . Action: take the request from the corresponding attribute value .
Many small partner of
getParameter()
andgetAttribute()
related methods silly you could not tell. I suggest you can be clearparam
andattribute
the difference between ~
// @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;
}
The next sentence is important : @RequestAttribute
only take charge of the property value from the request which, as you value when put inside, there is a variety of ways that can be achieved:
@ModelAttribute
Notes storedHandlerInterceptor
Interceptor stored- Come forward with a request
The following were used in accordance with the three scenarios, using given Demo
:
@ModelAttribute
Notes stored
Relatively simple, @ModelAttribute
using the method of label originated by the HttpServletRequest
discharge to a value
@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)
}
}
Request /testRequestAttr
, the result is printed as follows:
fsx-application
fsx-application
null
Person(name=非功能方法, age=50)
Be sure to note here: @RequestAttribute("myApplicationName")
NOTE If omitted, is not binding properties of Oh attr (must be annotated) ~
However, this is possible:
@RequestAttribute String myApplicationName
(if annotation is not specified,Spring MVC
will then go to confirm the parameter name automatically bound)
but if you wrote this@RequestAttribute String aaa
, that the request directly to the 400 error thrown:org.springframework.web.bind.ServletRequestBindingException
HandlerInterceptor
Interceptor stored
Simple, direct on the code:
public class SimpleInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
request.setAttribute("myApplicationName", "fsx-application");
return true;
}
...
}
Test code: slightly.
forward
Come forward with a request
Thus the form:
request.setAttribute("myApplicationName", "fsx-application");
request.getRequestDispatcher("/index").forward(request, response);
In fact, the property value is placed inside only need to follow a principle: the target method call processor 之前
placement can be anywhere (before parameter package), the property value is being able to take.
Principle analysis
According to my habit, even if it is simple, I will take a look at clawed its principles part of the thing.
According to experience it is easy to think it is a resolve HandlerMethodArgumentResolver
, it isRequestAttributeMethodArgumentResolver
RequestAttributeMethodArgumentResolver
Obviously, it is also @since 4.3
only appeared, the name is also supporting the thing.
public class RequestAttributeMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
// 只处理标注了@RequestAttribute注解的入参
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(RequestAttribute.class);
}
// 封装此注解的属性到NamedValueInfo 这里关于参数名的处理有这么一个处理
// 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());
}
}
Source dapper, very simple.
In fact, it resolves into the core of the resolution process parameters in terms of its parent AbstractNamedValueMethodArgumentResolver
body, but not the focus of this article, please refer to HandlerMethodArgumentResolver
section ~
@RequestAttribute
Propertyrequired
defaults to true,request.getAttribute
not obtain parameters will throw an exceptionServletRequestBindingException
; required is set to false, even if not get to ignore the request from skipping, assigned to null;
to sum up
This article describes the @RequestAttribute
use of Demo
analysis, and it is very simple principle. Compared to all previous articles, this is very easy, hope to provide everyone an idea to use @RequestAttribute
to improve your force grid, ha ha (Tips: loaded to force need to be cautious Oh ~)
Note: Because
@SessionAttribute
of the use of even a gross principle is almost the same, so we do not repeat the space
to sum up
This article describes @SessionAttributes
the core principles of treatment, and also gave a Demo
to introduce its basic use, not surprisingly down to read it you should have a good harvest, hoping to help you simplify the development ~
Related Reading
In principle level to master the use HandlerMethod, InvocableHandlerMethod, ServletInvocableHandlerMethod with the [school] Spring MVC
master the use of @SessionAttributes from the principle of level [together] Spring MVC learn
from the master @ModelAttribute principle level of use (the core principles of article) [together] to learn Spring MVC
in principle grasp @ModelAttribute level of use (use articles) [together] to learn Spring MVC
Knowledge Exchange
== The last: If you think this article helpful to you, may wish to point a praise chant. Of course, your circle of friends to share so that more small partners also are seeing 作者本人许可的~
==
If interested in technology content can join the group wx exchange: Java高工、架构师3群
.
If the group fails two-dimensional code, please add wx number: fsx641385712
(or two-dimensional code is scanned beneath wx). And Note: "java入群"
the word, will be invited into the group manually