HandlerMethodArgumentResolver,中文称为方法参数解析器,是Spring Web(SpringMVC)组件中的众多解析器之一,主要用来对Controller中方法的参数进行处理。
在一般的接口调用场景下,每次调用Controller都需要检查请求中的token信息,并根据token还原用户信息,然后将用户信息封装到Controller的方法参数中,供方法中接下来的逻辑使用。
需求:系统有两种用户老师和学生,鉴权是需要根据不同的channel来区分不同的用户。
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;
}
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 {
}
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);
}
}
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;
}
}
调用接口/getTeacherOrUser,channel=1,返回值
{
"id": 11,
"name": "张三"
}
调用接口/getTeacherOrUser,channel=2,返回值
{
"id": 12,
"name": "李四"
}
share: 分享仓库 - Gitee.com