SpringMVC implementation controller gets the session instance code

  • 2020-06-03 06:22:30
  • OfStack

Using springMVC on a regular basis, Servlet API is often called naturally from accessing session in a method. It's very intuitive and easy to use, and I didn't think much about it.

Like this:


@RequestMapping(value = "/logout")
public String logout(HttpSession session) {
 session.removeAttribute("user");
 return "/login";
} 

But after all, I became dependent on Servlet API and felt that it was not enough.

So I tried to solve the problem.

I'm going to use one annotation. It's called "sessionScope". Target can be either an Method or an Parameter.

In other words:


 import java.lang.annotation.Documented;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 @Target({ ElementType.PARAMETER,ElementType.METHOD })
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 public @interface SessionScope {
  String value();
 }

Then I have to register an ArgumentResolver that addresses annotated items and replace them all with session.

The code is as follows:


import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

public class SessionScopeMethodArgumentResolver implements
  HandlerMethodArgumentResolver {

 @Override
 public boolean supportsParameter(MethodParameter parameter) {
  // Let's make methods and parameters, two target through 
  if(parameter.hasParameterAnnotation(SessionScope.class))return true;
  else if (parameter.getMethodAnnotation(SessionScope.class) != null)return true;
  return false;
 }

 @Override 
 public Object resolveArgument(MethodParameter parameter,
   ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
   WebDataBinderFactory binderFactory) throws Exception {
  String annoVal = null;

  if(parameter.getParameterAnnotation(SessionScope.class)!=null){
   logger.debug("param anno val::::"+parameter.getParameterAnnotation(SessionScope.class).value());
   annoVal = parameter.getParameterAnnotation(SessionScope.class).value();
  }else if(parameter.getMethodAnnotation(SessionScope.class)!=null){
   logger.debug("method anno val::::"+parameter.getMethodAnnotation(SessionScope.class).value());
   annoVal = parameter.getMethodAnnotation(SessionScope.class)!=null?
          StringUtils.defaultString(parameter.getMethodAnnotation(SessionScope.class).value())
            :StringUtils.EMPTY;
  }
                                
  if (webRequest.getAttribute(annoVal,RequestAttributes.SCOPE_SESSION) != null){
   return webRequest.getAttribute(annoVal,RequestAttributes.SCOPE_SESSION);
  }
  else
   return null;
 }
                                      
 final Logger logger = LoggerFactory.getLogger(SessionScopeMethodArgumentResolver.class);
}

supportParameter determines whether an object is annotated and resolve is annotated.

When resolve gets the annotation value, the annotation value is session key, and the value is taken from session scope with webRequest.

Also need to put this configuration in org. springframework. web. servlet. mvc. method. annotation. RequestMappingHandlerAdapter customArgumentResolvers list, you can use bean label configuration, also can use mvc tags directly.

That is:

namespace is: xmlns: mvc = "http: / / www. springframework. org schema/mvc"

schema location is: http: / / www springframework. org/schema/mvc

http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd


<mvc:annotation-driven>
 <mvc:argument-resolvers>
  <bean class="pac.common.SessionScopeMethodArgumentResolver" />
 </mvc:argument-resolvers>
</mvc:annotation-driven>
<mvc:default-servlet-handler />

Say that the order of mvc: ES91en-driven and mvc: default-ES95en-handler cannot be reversed. I am not the only one who has this situation.

It can now be used in controller, for example:


@RequestMapping(value = "/index")
@SessionScope("currentUser")
public ModelAndView index(User currentUser) {
 ModelAndView mav;
 if (currentUser==null || currentUser.getId()==null)
  mav = new ModelAndView("/login");
 else {
  mav = new ModelAndView("/index");
 }
 return mav;
}

Or annotate the parameters:


@RequestMapping(value = "/welcome")
public String welcome(@SessionScope("currentUser")User currentUser) {
 return "/main";
}

As for updating session, it is only using @ES107en in conjunction with ModelMap.

Or I can integrate Apache Shiro and getSubject() directly in controller without doing so.

Put the user information entirely in shiro's hands. Well, that's good.


Related articles: