Spring MVC如何实现自定义注解,如@RequestParam

本文介绍了如何在Spring MVC中实现自定义注解以替代@RequestParam等标准注解,达到精简代码和提高复用性的目的。通过定义注解、实现解析器、配置加入、创建实体类和编写测试类,详细阐述了自定义注解的步骤,强调了学习源码对程序员的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

常用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的多个参数绑定注解就实现了,看起来很难,实现起来则很简单,作为一名程序员,多学习,多钻研一些源码,对我们有很大的提升。

总结:万事开头难,遇到问题不要退缩,努力去克服困难,当你克服困难之后,你就会觉得很有成就感!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值