天天看點

SpringMvc通過自定義注解在方法的參數中注入資料

說一個場景,有時候我們做背景業務的時候,經常需要取session中存儲的使用者資訊,是以免不了一直需要寫下面這一段又長又無聊的代碼:

那麼怎麼避免這個事情呢,下面我們就來通過一個自定義注解@MemberDetail和SpringMvc的HandlerMethodArgumentResolver接口來實作這個功能。

首先來建立我們的自定義注解:

/**
 * 
 * @Description 方法的參數上加了這個注解,會自動注入目前登入使用者放在session中的使用者對象
 * @author chenbin.sun
 * @date 2017年8月30日上午11:23:02
 *
 */
@Documented
@Target({ ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface MemberDetail {

}
           

然後實作HandlerMethodArgumentResolver接口,來寫我們的注入邏輯,url請求進來後走完其他一些攔截器等之後會在進入方法之前執行supportsParameter依次傳入要請求方法的參數,我們隻需要在這裡判斷這個參數,是否符合我們的要求,是否是我們想要注入的參數就可以了,如果是傳回true,否則傳回false,如果傳回的是true那麼他就會執行resolveArgument方法,此時我們隻需要把我們要注入的資料return出去就可以了,詳情請看下面代碼。

/** 
 * @Description 用于方法參數上加MemberDetail标簽擷取目前登入使用者的資訊
 * @author chenbin.sun
 * @date 2017年8月30日下午3:50:00
 * 
 */  
public class MemberDetailHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {

    /** 登入使用者資訊session中的key */
    private String              sessionKey         = SessionAttr.MEMBER_DETAIL;

    /** 登入使用者資訊的class類型 */
    private Class<?>            sessionMemberClass = MemberCommand.class;

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        // 過濾出符合條件的參數,這裡指的是加了MemberDetail注解的參數
        if (parameter.hasParameterAnnotation(MemberDetail.class)) {
            return true;
        }
        return false;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);

        // 擷取session中存放的使用者資訊
        Object sessionMember = WebUtils.getSessionAttribute(request, sessionKey);

        if (null == sessionMember){
            return null;
        }

        // session中對象與加了MemberDetail注解的參數的類型相同是指派給這個參數
        Class<?> klass = parameter.getParameterType();
        if (klass.isAssignableFrom(sessionMemberClass)){
            return sessionMember;
        }

        return null;
    }

}
           

當然拉,這個實作類需要在xml中配置一下才能生效,下面看真名配置,很簡單的。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        ">

    <mvc:annotation-driven>
        <mvc:argument-resolvers>
            <bean class="chenbin.sun.MemberDetailHandlerMethodArgumentResolver"></bean>
        </mvc:argument-resolvers>
    </mvc:annotation-driven>

</beans>
           

使用的時候隻需要像下面這樣将注解配置到要注入的參數上,那麼請求進來後,如果session中有這個值,那麼你的方法上的這個參數就一定是有值的了。

@RequestMapping("/doTest")
public String test(@MemberDetail MemberCommand memberCommand){
    System.out.println(memberCommand.getName());
}
           

OK,就到這裡,個人覺得這個還是挺實用的。