SpringBoot自定义参数解析
1.为什么要自定义参数解析
1.原因
如不自定义参数解析
假如说需要获取Token,如果直接处理,需要在每个接口上都要添加
HttpServletRequest request
或者
@RequestHeader("token") String token
这样显得非常麻烦
@RequestMapping(value = "/user/findAll", method = RequestMethod.GET)
public RestBean findAllUser(HttpServletRequest request) throws Exception {
//token在请求头中,需要获取请求头中的token
//获取请求头中的Token,并判断
String token = request.getHeader("token");
//判断Token是否为空
if (StringUtils.hasText(token)) {
//解析Token获取用户id
Claims claims = JwtUtil.parseJWT(token);
//获取用户id
String id = claims.getSubject();
//打印用户id
System.out.println(id);
}
List<User> userList = userService.findAllUser();
//判断是否查询到用户
if (userList.isEmpty())
return new RestBean(500, "查询失败");
else
return new RestBean(200, "查询成功", userList);
}
//查询所有用户
@RequestMapping(value = "/user/findAll1", method = RequestMethod.GET)
public RestBean findAllUser1(@RequestHeader("token") String token) throws Exception {
//判断Token是否为空
if (StringUtils.hasText(token)) {
//解析Token获取用户id
Claims claims = JwtUtil.parseJWT(token);
//获取用户id
String id = claims.getSubject();
//打印用户id
System.out.println(id);
}
List<User> userList = userService.findAllUser();
//判断是否查询到用户
if (userList.isEmpty())
return new RestBean(500, "查询失败");
else
return new RestBean(200, "查询成功", userList);
}
如果自定义参数解析,在获取一些参数的时候会更加的方便,也有助于提高代码的复用性
假如很多接口需要这些参数,就显得非常麻烦
2.自定义参数解析
1.自定义解析
如果我们想要实现像获取请求体数据那样,在方法的参数上添加一个@RequestBody注解就可以获取到对应的数据的话
public RestBean findUserById(@RequestBody("id") int id)
就需要使用HandlerMethodArgumentResolver来实现自定义参数的解析
HandlerMethodArgumentResolver是Spring MVC框架中的一个接口,它用于解析处理方法参数。
2.自定义的注解
package jiasen.resolver;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//@ElementType.PARAMETER:用于描述参数
//@ElementType.METHOD:用于描述方法
//Retention:注解的生命周期
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUserID {
}
3.实现自定义解析
需要实现HandlerMethodArgumentResolver
需要将该方法注册到Spring容器中,所以需要添加@Component注解注入Spring容器
package jiasen.resolver;
import io.jsonwebtoken.Claims;
import jiasen.util.JwtUtil;
import org.apache.ibatis.annotations.Param;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
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;
@Component
//自定义参数解析器
public class UserIdArgumentResolver implements HandlerMethodArgumentResolver {
//判断方法参数是否能使用当前的参数解析器进行解析
@Override
public boolean supportsParameter(MethodParameter parameter) {
//判断方法参数是否有某些注解
//如果方法参数上有@CurrentUserID注解,返回值为true,则会调用resolveArgument方法进行参数解析,如果为false,则不会调用
return parameter.hasParameterAnnotation(CurrentUserID.class);
}
//进行参数解析的方法,可以在方法中获取对应的数据,然后将数据作为返回值返回.
//方法的返回值就会赋值给赋值给对应的方法参数
/*
* 1.MethodParameter parameter:获取当前方法的参数信息
* 可以通过该参数获取方法的参数名称,参数类型,参数上的注解等信息
* 2.ModelAndViewContainer mavContainer:当前方法所在的类的方法的参数信息
* 用于方法参数的绑定
* 3.NativeWebRequest webRequest:用于获取请求相关的信息
* 可以获取请求参数,请求头,session,cookie等用于解析参数的信息
* 4.WebDataBinderFactory binderFactory:用于创建WebDataBinder对象,用于数据绑定和验证
* 如果需要进行数据绑定和验证,可以通过该参数获取WebDataBinder对象
* */
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
//获取请求值中的Token
String token = webRequest.getHeader("Token");
if (StringUtils.hasText(token)){
//解析Token,获取用户ID
Claims claims = JwtUtil.parseJWT(token);
//将用户ID转换为字符串
String userid = claims.getSubject();
//返回用户ID
return userid;
}
return null;
}
}
supportsParameter:该方法用于判断解析器是否支持给定的方法参数,开发人员可以在这个方法中定义自己的逻辑,根据参数类型/注解...条件来判断是否可以解析该参数
resolveArgument该方法用于解析给定的方法参数并返回解析结果,如果上面的方法为true,将会使用该方法进行解析
resolveArgument方法中的参数
- MethodParameter parameter: 表示要解析的方法参数。通过该参数可以获取参数的类型、注解、泛型信息等。
- ModelAndViewContainer mavContainer: 用于处理返回视图的容器。在参数解析期间,可以使用该容器来设置或获取与请求处理相关的模型和视图信息
- NativeWebRequest webRequest: 表示当前的原生Web请求对象。通过该对象可以获取请求的各种属性和参数,例如请求头、请求参数、路径变量,request,Session等
- WebDataBinderFactory binderFactory: 用于创建和获取数据绑定器的工厂对象。数据绑定器用于将请求数据绑定到目标对象上。通过该工厂对象,可以获取数据绑定器以进行进一步的数据绑定操作。
通过parameter参数获取方法参数的类型信息,根据类型信息进行不同的处理逻辑。
使用webRequest参数获取请求中的数据,例如请求参数、请求头等。根据这些数据进行相应的处理和转换。
使用mavContainer参数设置或获取与请求处理相关的模型和视图信息。可以将解析结果放入模型中,以供后续的视图渲染使用。
使用binderFactory参数创建数据绑定器,并根据需要进行数据绑定操作,将请求数据绑定到目标对象上。
4.配置
和其他例如拦截器,跨域配置一样,需要实现WebMvcConfigurer,重写其中的方法
package jiasen.config;
import jiasen.resolver.UserIdArgumentResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
//自定义参数解析器配置
@Configuration
public class ArgumentResolverConfig implements WebMvcConfigurer {
//将参数解析器注入到spring容器中
@Autowired
private UserIdArgumentResolver userIdArgumentResolver;
//添加参数解析器
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(userIdArgumentResolver);
}
}
5.测试
没有添加自定义注解,需要使用request请求,从请求头中获取token进行解析,或者使用@RequestHeader注解进行解析
//第一种
@RequestMapping(value = "/user/findAll", method = RequestMethod.GET)
public RestBean findAllUser(HttpServletRequest request) throws Exception {
//token在请求头中,需要获取请求头中的token
//获取请求头中的Token,并判断
String token = request.getHeader("token");
//判断Token是否为空
if (StringUtils.hasText(token)) {
//解析Token获取用户id
Claims claims = JwtUtil.parseJWT(token);
//获取用户id
String id = claims.getSubject();
//打印用户id
System.out.println(id);
}
List<User> userList = userService.findAllUser();
//判断是否查询到用户
if (userList.isEmpty())
return new RestBean(500, "查询失败");
else
return new RestBean(200, "查询成功", userList);
}
//第二种
@RequestMapping(value = "/user/findAll", method = RequestMethod.GET)
public RestBean findAllUser2(@RequestHeader("token") String token) throws Exception {
//判断Token是否为空
if (StringUtils.hasText(token)) {
//解析Token获取用户id
Claims claims = JwtUtil.parseJWT(token);
//获取用户id
String id = claims.getSubject();
//打印用户id
System.out.println(id);
}
List<User> userList = userService.findAllUser();
//判断是否查询到用户
if (userList.isEmpty())
return new RestBean(500, "查询失败");
else
return new RestBean(200, "查询成功", userList);
}
使用自定义注解后,可以直接获取,不需要使用request请求中解析,并且可以将解析Token逻辑写在实现了HandlerMethodArgumentResolver方法的类上
//查询所有用户
@RequestMapping(value = "/user/findAll1", method = RequestMethod.GET)
public RestBean findAllUser1(@CurrentUserID String userID) throws Exception {
System.out.println(userID);
List<User> userList = userService.findAllUser();
//判断是否查询到用户
if (userList.isEmpty())
return new RestBean(500, "查询失败");
else
return new RestBean(200, "查询成功", userList);
}