常用SpringMVC参数绑定的注解有很多,如@RequestParam,@RequestBody,@PathVariable,@RequestHeader,@CookieValue等。这些注解的实现方式很类似,都是有一个对应的解析器,解析完返回一个对象,放在方法的参数上。
日常业务经常遇到,前端上送用户信息,部门信息,这样后台可能需要多个controller去处理具体业务逻辑,这样的代码就很烂。如何精简呢?答案就是自定义注解实现多个参数绑定。
1.定义注解
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CurrentUser {
String value() default "";
}
2.实现解析器
public class CurrentUserUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
/** 用于判定是否需要处理该参数分解,返回true为需要,并会去调用下面的方法resolveArgument。*/
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.hasParameterAnnotation(CurrentUser.class);
}
/** 真正用于处理参数分解的方法,返回的Object就是controller方法上的形参对象。*/
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer , NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
String name = methodParameter.getParameterAnnotation(CurrentUser.class).value();
HttpServletRequest httpServletRequest = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
Map<String, String[]> map = httpServletRequest.getParameterMap();
Class clazz = methodParameter.getParameterType();
if (Collection.class.isAssignableFrom(clazz)) {
// 集合泛型
Type genericType = clazz.getComponentType();
JSONArray jsonArray = new JSONArray();
for (Map.Entry<String, String[]> entry : map.entrySet()) {
String key = entry.getKey();
String[] keys = key.split("\\.");
if (Objects.equals(name, keys[0])) {
String[] values = entry.getValue();
for (String value : values) {
Map<String, Object> paramMap = new HashMap();
paramMap.put(keys[1], value);
jsonArray.add(paramMap);
}
}
}
return JSON.parseArray(jsonArray.toJSONString(), genericType.getClass());
}
Map<String, Object> paramMap = new HashMap();
for (Map.Entry<String, String[]> entry : map.entrySet()) {
String key = entry.getKey();
String[] keys = key.split("\\.");
if (Objects.equals(name, keys[0])) {
paramMap.put(keys[1], entry.getValue());
}
}
return JSON.parseObject(JSONObject.toJSONString(paramMap), clazz);
}
}
3.加入配置
@Configuration
public class WebConfig implements WebMvcConfigurerAdapter {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new CurrentUserUserHandlerMethodArgumentResolver());
}
}
4.定义实体类
//用户实体类
public class User {
private String userName;
private String pwd;
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName= userName;
}
}
//部门实体类
public class Dept {
private String name;
private String dept;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept= dept;
}
}
5.测试类
@RestController
public class UserController {
@PostMapping("/saveUserInfo")
public Map<String, String> saveUserInfo(@CurrentUser("user") User user, @CurrentUser("dept") Dept dept) {
Map<String, String> result = new HashMap<>();
result.put("userName", user.getUserName());
result.put("pwd", user.getPwd());
result.put("dept", user.getDept());
//TODO 此处可以保存用户信息,用户部门信息
return result;
}
}
至此,Spring MVC的多个参数绑定注解就实现了,看起来很难,实现起来则很简单,作为一名程序员,多学习,多钻研一些源码,对我们有很大的提升。
总结:万事开头难,遇到问题不要退缩,努力去克服困难,当你克服困难之后,你就会觉得很有成就感!!!