HandlerMethodArgumentResolver方法参数解析器支持多用户

1、概述

        HandlerMethodArgumentResolver,中文称为方法参数解析器,是Spring Web(SpringMVC)组件中的众多解析器之一,主要用来对Controller中方法的参数进行处理。

使用场景

        在一般的接口调用场景下,每次调用Controller都需要检查请求中的token信息,并根据token还原用户信息,然后将用户信息封装到Controller的方法参数中,供方法中接下来的逻辑使用。

2、示例代码

        需求:系统有两种用户老师和学生,鉴权是需要根据不同的channel来区分不同的用户。

2.1 用户类定义

package com.ybw.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 用户类
 *
 * @author weixiansheng
 * @version V1.0
 * @className User
 * @date 2023/11/3
 **/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {

    private Long id;
    private String name;

}
package com.ybw.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 老师
 *
 * 老师实体类,用于存储老师的相关信息
 *
 * @author ybw
 * @version V1.0
 * @className Teacher
 * @date 2023/11/4
 **/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Teacher {
    private Long id;
    private String name;
}

2.2 定义注解类

package com.ybw.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 当前学生
 *
 * @author weixiansheng
 * @version V1.0
 * @className CurrentUser
 * @date 2023/11/3
 **/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentStudent {
}
package com.ybw.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 当前老师
 *
 * @author ybw
 * @version V1.0
 * @className CurrentTeacher
 * @date 2023/11/4
 **/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentTeacher {
}

2.3 定义解析器

package com.ybw.config;

import com.ybw.annotation.CurrentTeacher;
import com.ybw.annotation.CurrentStudent;
import com.ybw.constant.AuthConstant;
import com.ybw.entity.Teacher;
import com.ybw.entity.Student;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
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 javax.servlet.http.HttpServletRequest;

/**
 * 用户解析器
 *
 * @author ybw
 * @version V1.0
 * @className CurrentUserResolver
 * @date 2023/11/4
 **/
@Slf4j
@Component
public class CurrentUserResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(CurrentStudent.class) || parameter.hasParameterAnnotation(CurrentTeacher.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
        //1、请求header中有channel的值,根据channel解析出当前用户的信息
        HttpServletRequest httpServletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
        String token = httpServletRequest.getHeader(AuthConstant.TOKEN);
        Integer channel = httpServletRequest.getIntHeader(AuthConstant.CHANNEL);
        //2、channel的解析过程
        if (AuthConstant.STUDENT.equals(channel) && Student.class == parameter.getParameterType()) {
            return new Student(11L, "张三");
        } else if (AuthConstant.TEACHER.equals(channel) && Teacher.class == parameter.getParameterType()) {
            return new Teacher(12L, "李四");
        }
        return null;
    }
}
package com.ybw.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.Resource;
import java.util.List;

/**
 * @className WebMvcConfig
 * @author ybw
 * @date 2023/11/4 
 * @version V1.0
 **/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Resource
    private CurrentUserResolver currentUserResolver;

    @Override
    public void addArgumentResolvers(List resolvers) {
        resolvers.add(currentUserResolver);
    }
}

2.4 定义接口

package com.ybw.controller;

import com.ybw.annotation.CurrentTeacher;
import com.ybw.annotation.CurrentStudent;
import com.ybw.entity.Teacher;
import com.ybw.entity.Student;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
public class MyController {

    /**
     * 获取当前学生
     *
     * @param currentStudent
     * @methodName: getStudent
     * @return: java.lang.String
     * @author: ybw
     * @date: 2023/11/4
     **/
    @GetMapping("/getStudent")
    public Student getStudent(@CurrentStudent Student currentStudent) {
        log.info("current user info: {}", currentStudent);
        return currentStudent;
    }


    /**
     * 获取当前老师信息
     *
     * @param
     * @methodName: getTeacher
     * @return: java.lang.String
     * @author: ybw
     * @date: 2023/11/4
     **/
    @GetMapping("/getTeacher")
    public Teacher getTeacher(@CurrentTeacher Teacher currentTeacher) {
        log.info("current teacher info: {}", currentTeacher);
        return currentTeacher;
    }


    /**
     * 获取当前用户或教师对象
     *
     * @param currentStudent 当前学生对象
     * @param teacher        当前教师对象
     * @return 当前用户对象或教师对象,如果两者都为空则返回null
     */
    @GetMapping("/getTeacherOrUser")
    public Object getTeacherOrUser(@CurrentStudent Student currentStudent, @CurrentTeacher Teacher currentTeacher) {
        log.info("currentUser: {},currentTeacher:{}", currentStudent, currentTeacher);
        if (currentTeacher != null) {
            return currentTeacher;
        } else if (currentStudent != null) {
            return currentStudent;
        }
        return null;
    }


}

3、测试

调用接口/getTeacherOrUser,channel=1,返回值

{
    "id": 11,
    "name": "张三"
}

调用接口/getTeacherOrUser,channel=2,返回值

{
    "id": 12,
    "name": "李四"
}

4、源码地址

share: 分享仓库 - Gitee.com

你可能感兴趣的:(spring,java,开发语言)