天天看點

Spring自定參數解析器之《自動注入已登入使用者》

前言

Spring項目的企業開發中,在Controller層的某一個方法中擷取目前登入人的資訊是一個非常常見的需求,比如你可以根據目前登入人資訊判斷是否有操作權限、記錄記錄檔等等,但是如何更好、更簡單的擷取到該資訊?今天就教大家一個使用自定參數解析器來完成的擷取登入人的方法。

期望

我們以檢視目前登入人畫像資訊為例,看看我們所期望的擷取方式。

畫像接口定義:
package com.zhuma.demo.web.demo3;

import com.zm.zhuma.commons.annotations.LoginAuth;
import com.zm.zhuma.commons.web.annotations.ResponseResult;
import com.zm.zhuma.user.model.bo.LoginUser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

/**
 * @desc  Spring自定參數解析器之《自動注入已登入使用者》
 * 
 * @author zhumaer
 * @since 3/5/2018 23:57 PM
 */
@Api(value = "我的賬戶", description = "我的賬戶")
@ResponseResult
@RestController
@RequestMapping("demo3/my-account")
public class MyAccountController {

    @ApiOperation("查詢我的畫像")
    @LoginAuth
    @GetMapping("profile")
    public LoginUser myAccount(@ApiIgnore LoginUser loginUser) {
        return loginUser;
    }

}
           

備注

  • 期望隻需要在Controller方法上使用LoginUser loginUser這個對象類作為參數,便可以自動擷取到登入人資訊(@ApiIgnore增加這個注解是因為使用了swagger文檔,讓其生成文檔時忽略該對象,如果你沒有使用它,這個注解不需要考慮)
  • 同時在目前方法或類上需增加@LoginAuth注解,該注解是代表該方法通路時使用者必須是在登入狀态下(如果不清楚該功能怎麼實作,可以看下我的這篇文章Spring攔截器+注解實作《登入校驗》)
PostMan調用截圖
Spring自定參數解析器之《自動注入已登入使用者》

代碼實作

現在我們來說下本篇文章的重頭戲,HandlerMethodArgumentResolver接口,在spring mvc中用于處理方法參數的解析,其下僅僅有兩個方法

//根據方法參數判斷是否需要對其做轉換
boolean supportsParameter(MethodParameter parameter);
//supportsParameter方法傳回true後,進入該方法,傳回值即為要轉化對象的結果
Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,  
            NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;  
           

可能你還不是特别清楚,下面我們以上述功能的實作,看看這個類在具體功能上的使用

登入使用者參數解析器
package com.zm.zhuma.commons.web.resolver;

import com.zm.zhuma.commons.annotations.LoginAuth;
import com.zm.zhuma.user.model.bo.LoginUser;
import com.zm.zhuma.user.token.helper.LoginTokenHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.lang.reflect.Method;

/**
 * @desc 登入使用者參數解析器
 *
 * @author zhumaer
 * @since 3/5/2017 3:00 PM
 */
@Slf4j
public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {

	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		final Method method = parameter.getMethod();
		final Class<?> clazz = parameter.getMethod().getDeclaringClass();

		boolean isHasLoginAuthAnn = clazz.isAnnotationPresent(LoginAuth.class) || method.isAnnotationPresent(LoginAuth.class);
		boolean isHasLoginUserParameter = parameter.getParameterType().isAssignableFrom(LoginUser.class);

		return isHasLoginAuthAnn && isHasLoginUserParameter;
	}

	@Override
	public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
		return LoginTokenHelper.getLoginUserFromRequest();
	}
}

           

備注

  • 可以看到在方法supportsParameter中有isHasLoginAuthAnn和isHasLoginUserParameter參數,代表着目前方法或類上有@LoginAuth注解并且有LoginUser這個類型的參數時進行轉化。
  • 在resolveArgument中僅僅隻有一句LoginTokenHelper.getLoginUserFromRequest(),這個其實是我們早在攔截器層就已經把使用者的登入資訊放入request中了,是以現在直接通過該類擷取登入使用者資訊即可,具體的實作邏輯,可以看Spring攔截器+注解實作《登入校驗》
配置自定義解析器
package com.zhuma.demo.config.web;

import com.zm.zhuma.commons.web.resolver.LoginUserArgumentResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.List;

@Configuration
public class ArgumentResolverConfig extends WebMvcConfigurerAdapter {

	@Override
	public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
		argumentResolvers.add(new LoginUserArgumentResolver());
	}

}
           

備注

  • 在spring boot中需要如上配置,才能讓你的自定義參數解析器生效哈

最後

好了,就是這麼簡單,不知道你是否清楚了呢?可以關注公衆号或留言,更多更好的代碼方案将會不定期分享給你O(∩_∩)O~

附上github位址:https://github.com/zhumaer/zhuma/tree/master/zhuma-demo

本執行個體代碼示範在,zhuma-demo項目下的demo3下

源碼github位址:https://github.com/zhumaer/zhuma

QQ群号:629446754(歡迎加群)

Spring自定參數解析器之《自動注入已登入使用者》

歡迎關注我們的公衆号或加群,等你哦!

Spring自定參數解析器之《自動注入已登入使用者》
Spring自定參數解析器之《自動注入已登入使用者》
Spring自定參數解析器之《自動注入已登入使用者》

繼續閱讀