Spring Extension (2) — Annotation RequestAttribute for Controller method Parameter Injection

本文介绍如何在Spring MVC中通过自定义注解实现Controller方法参数注入,特别是针对HttpServletRequest.attribute的需求。通过创建注解、定义Resolver并配置Interceptor,实现对Http请求参数的自动处理,避免直接依赖HttpServletRequest。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

场景:

SpringMVC3.x 中一个http 请求被controller handler处理的时候,需要将请求中的某些参数根据特定的逻辑生成一些特定的数值供每个controller handler使用。这个特定的逻辑可以抽取到SpringMVC Interceptor中,然后将计算的特定数据以HttpServletRequest.attribute的方式传送到controller handler中。SpringMVC 3.x 没有提供类似@RequestParamPARAMETER  Annotation用来自动注入HttpServletRequest.attribute参数到handler method中。有2中选择:

1、将HttpServletRequest当做参数注入到handler method中,每个Controller中的每个方法都要注入request对象。。。这种方案就是一个大杯具!

2、自定义一个Annotation来实现HttpServletRequest.attribute自动注入


代码

1、定义Annotation

  /**
   * get parameter from Request Attribute
   */
  @Target(ElementType.PARAMETER)
  @Retention(RetentionPolicy.RUNTIME)
  @Documented
  public @interface RequestAttribute {
  
  	/**
  	 * The request attribute parameter to bind to.
  	 */
  	String value() ;
  	
  }


2、在目标类定义:

@Controller
@RequestMapping("/")
public class UserController{
	@RequestMapping(value="/demo")
	public @ResponseBody Map<String, String>> demo(@RequestAttribute("loginUserId") long loginUserId){
		return Collections.emptyMap();
	}
}


3、自定义Resolver

最重要的步骤,实现WebArgumentResolver接口来实现"特殊请求参数"的解析器Resolver,然后将这个Resolver加入到org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.customArgumentResolver。同时不能使用schema方式启用SpringMVC: <mvc:annotation-driven/>,使用xml定义的方式启用SpringMVC。

public class RequestAttributeArgumentResolver implements WebArgumentResolver {
 
    public Object resolveArgument(MethodParameter param,
                                  NativeWebRequest request) throws Exception {
 
        Annotation[] paramAnns = param.getParameterAnnotations();
 
        Class paramType = param.getParameterType();
 
        for (Annotation paramAnn : paramAnns) {
            if (RequestAttribute.class.isInstance(paramAnn)) {
                RequestAttribute reqAttr = (RequestAttribute) paramAnn;
                HttpServletRequest httprequest = (HttpServletRequest) request.getNativeRequest();
                Object result = httprequest.getAttribute(reqAttr.value());
 				/**
                  * result 校验是否为null
  */              
                return result;
            }
        }
 
        return WebArgumentResolver.UNRESOLVED;
  }
}

4、启用Resolver方式:


<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
		<property name="customArgumentResolver">
			<bean class="com.netease.lovefront.web.extention.RequestAttributeArgumentResolver"></bean>
		</property>
		<property name="messageConverters">
			<list>
				<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
				<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"></bean>
				<bean class="org.springframework.http.converter.StringHttpMessageConverter"></bean>
				<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"></bean>
				<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"></bean>
				<bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"></bean>
			</list>
		</property>
	</bean>

5、Interceptor for Http URL Request

生成loginUserId的Interceptor

  /**
   * <li>init the user info, user id  when {@code preHandle}.</li>
   */
  @Component
  public class UserInterceptor extends HandlerInterceptorAdapter {
      @Resource
      private UserService userService;
      @Override
      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
          String email = CookieUtils.getLoginEmail(request);
          if(StringUtils.isNotBlank(email)) {
              long userId = userService.getUserId(email);
              request.setAttribute("loginUserId", userId);
          }
          return true;
      }
  }

UserInterceptor 会拦截每一个http 请求。

  <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
  		<property name="interceptors">
  			<list>
  				<ref bean="userInterceptor " />
  			</list>
  		</property>
  	</bean>


ps

还有一种方法来类似的Interceptor逻辑:通过@ModelAttribute method方式来实现数据转换,然后在 handler method中使用@ModelAttribute 修饰的参数来实现参数注入。如果Controller太多,需要继承BaseController来抽取@ModelAttribute修饰的方法,这种也是一种可选方案。。。


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值