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自定参数解析器之《自动注入已登录用户》_第1张图片

代码实现

现在我们来说下本篇文章的重头戏,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(欢迎加群)

欢迎关注我们的公众号或加群,等你哦!

你可能感兴趣的:(企业实战之切面编程)