java 自定义注解 学习笔记一

HandlerMethodArgumentResolver简介

HandlerMethodArgumentResolver接口有以下两个方法
参考:https://blog.youkuaiyun.com/qq_36285124/article/details/64438245

	//是否支持要转换的参数类型
	boolean supportsParameter(MethodParameter parameter);
	
	//如果支持的话进行转换
	@Nullable
	Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;

自定义当前用户注解

/**
 * 当前用户注解
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(value = ElementType.PARAMETER)
public @interface CurrentUser {

}

自定义参数解析

/**
 * 当前用户MethodArgumentResolver
 */
public class CurrentUserMethodArgumentResolver implements HandlerMethodArgumentResolver {

	@Inject
	private UserService userService;

	/**
	 * 是否支持参数
	 */
	@Override
	public boolean supportsParameter(MethodParameter methodParameter) {
		//判断方法参数是否带有@CurrentUser注解且参数类型为User或其子类
		return methodParameter.hasParameterAnnotation(CurrentUser.class) && User.class.isAssignableFrom(methodParameter.getParameterType());
	}

	/**
	 * 解析变量
	 */
	@SuppressWarnings("unchecked")
	@Override
	public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
		//获取当前用户
		return userService.getCurrent();
	}

}

传统项目注册自定义解析器

<mvc:annotation-driven>
   <mvc:argument-resolvers>
      <bean class="xx.xx.xx.currentUserMethodArgumentResolver" />
   </mvc:argument-resolvers>
</mvc:annotation-driven>

使用@CurrentUser注解获取当前用户

@Controller
@RequestMapping("/test")
public class TestController {

	@GetMapping("/currentUser")
	public String test(@CurrentUser User currentUser) {
		......
	}

}

问题场景

场景一:平时controller层想要接收多个实体对象时,只能通过@RequestBody的形式,后台接口还需要建立大量的VO,很不方便,能否通过HandlerMethodArgumentResolver自定义解析器,让接口参数接口更方便呢?

项目经理说:可通过拦截的形式,解析参数,封装到对应的实体中。
老A说:在前端时间看spring源码时,发现HandlerMethodArgumentResolver就可以实现。

自定义参数解析demo:

EntityResolve.java类

@Documented
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface EntityResolve {

    String value();

}

EntityResolveHandler.java核心解析类

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.core.MethodParameter;
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;


public class EntityResolveHandler implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(final MethodParameter parameter) {
        return parameter.hasParameterAnnotation(EntityResolve.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
            throws Exception {
        // 获取http参数值
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        Map<String, String[]> parameterMap = request.getParameterMap();


        EntityResolve entityResolve = parameter.getParameterAnnotation(EntityResolve.class);
        String paramName = entityResolve.value();
        Class<?> parameterType = parameter.getParameterType();

        Type parameterizedType = parameter.getParameter().getParameterizedType();
        if (parameterizedType instanceof ParameterizedType) {
            Type[] types = ((ParameterizedType) parameterizedType).getActualTypeArguments();// 泛型类型列表
            List<Object> list = new ArrayList<Object>();
            for (Type type : types) {
                for (String s : parameterMap.keySet()) {
                    if (s.startsWith(paramName)) {
                        for (String paramValue : parameterMap.get(s)) {
                            Class clazz = (Class) type;
                            Object object = clazz.newInstance();
                            String[] split = s.split("\\.");
                            String p = split[1];
                            String methodName = getMethodName(p);
                            Method method = clazz.getMethod(methodName, String.class);
                            method.invoke(object, paramValue);
                            list.add(object);
                        }
                    }
                }
            }
            return list;
        } else {
            Object object = parameterType.newInstance();
            // 从request中能拿到参数值
            for (String s : parameterMap.keySet()) {
                if (s.startsWith(paramName)) {
                    String paramValue = parameterMap.get(s)[0];
                    String[] split = s.split("\\.");
                    String p = split[1];
                    String methodName = getMethodName(p);
                    Method method = parameterType.getMethod(methodName, String.class);
                    method.invoke(object, paramValue);
                }
            }
            return object;
        }
    }

    public Object resolveArgument1(final MethodParameter parameter, final ModelAndViewContainer mavContainer,
                                   final NativeWebRequest webRequest, final WebDataBinderFactory binderFactory) throws Exception {
        // 获取http参数值
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        Map<String, String[]> parameterMap = request.getParameterMap();


        EntityResolve entityResolve = parameter.getParameterAnnotation(EntityResolve.class);
        String paramName = entityResolve.value();
        Class<?> parameterType = parameter.getParameterType();

        Type parameterizedType = parameter.getParameter().getParameterizedType();
        if (parameterizedType instanceof ParameterizedType) {
            Type[] types = ((ParameterizedType) parameterizedType).getActualTypeArguments();// 泛型类型列表
            List<Object> list = new ArrayList<Object>();
            for (Type type : types) {
                for (String s : parameterMap.keySet()) {
                    if (s.startsWith(paramName)) {
                        for (String paramValue : parameterMap.get(s)) {
                            Class clazz = (Class) type;
                            Object object = clazz.newInstance();
                            String[] split = s.split("\\.");
                            String p = split[1];
                            String methodName = getMethodName(p);
                            Method method = clazz.getMethod(methodName, String.class);
                            method.invoke(object, paramValue);
                            list.add(object);
                        }
                    }
                }
            }
            return list;
        } else {
            Object object = parameterType.newInstance();
            // 从request中能拿到参数值
            for (String s : parameterMap.keySet()) {
                if (s.startsWith(paramName)) {
                    String paramValue = parameterMap.get(s)[0];
                    String[] split = s.split("\\.");
                    String p = split[1];
                    String methodName = getMethodName(p);
                    Method method = parameterType.getMethod(methodName, String.class);
                    method.invoke(object, paramValue);
                }
            }
            return object;
        }

    }

    String getMethodName(final String paramName) {
        StringBuffer sb = new StringBuffer();
        sb.append("set");
        sb.append(paramName.substring(0, 1).toUpperCase());
        sb.append(paramName.substring(1));
        return sb.toString();
    }

    public boolean isListParam(final Class<?> clazz) {

        if (List.class.isAssignableFrom(clazz)) {
            return true;
        }
        return false;
    }

}

controller层

@RestController
@RequestMapping("/user")
public class SpringTestController {
    private static final Logger LOGGER = LoggerFactory.getLogger(SpringTestController.class);


    @PostMapping("/test")
    public void getUserInfo(HttpServletRequest request, @FormModel("user")User userInfo, @FormModel("dept") Dept dept) {
        System.out.println(userInfo.getUsername());
        System.out.println(userInfo.toString());
        System.out.println(dept.toString());
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值