最近看组内一个哥们写了一个HandlerAdapter,能自动获取Http请求里面的Cookie并组装成一个Model来直接使用。觉得很牛逼。因此自己做了一个,特来分享。
原理:
利用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter。
在DispatcherServlet里面定义了:
private List<HandlerAdapter> handlerAdapters;
用于Servlet初始化的时候查找配置了的HandlerAdapter。再在Servlet请求到来之时通过调用doService层层调用
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
if (ha.supports(handler)) {
return ha;
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: Does your handler implement a supported interface like Controller?");
}
让它们去处理Handler。此处贴上一种实现代码:
Demo.java:
package com.hp.share.annocation;
public class Demo {
private int id;
private String name;
private byte sex;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public byte getSex() {
return sex;
}
public void setSex(byte sex) {
this.sex = sex;
}
public Demo() {
this.id = 1001;
this.name = "hello world";
this.sex = 1;
}
@Override
public String toString() {
return "Demo [id=" + id + ", name=" + name + ", sex=" + sex + "]";
}
}
DemoAnnotation.java:
package com.hp.share.annocation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.PARAMETER })
public @interface DemoAnnotation {
}
DemoProcessor.java:
package com.hp.share.handler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
import com.hp.share.annocation.Demo;
import com.hp.share.annocation.DemoAnnotation;
public class DemoProcessor implements HandlerMethodArgumentResolver {
private static Logger logger = LoggerFactory.getLogger(DemoProcessor.class);
public boolean supportsParameter(MethodParameter parameter) {
boolean res = parameter.getParameterAnnotation(DemoAnnotation.class) != null;
logger.info("开始校验 : {}", res);
return res;
}
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
logger.info("这是注解执行的标志~~~");
return new Demo();
}
}
DemoController.java:
package com.hp.share.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.google.common.base.Preconditions;
import com.hp.share.annocation.Demo;
import com.hp.share.annocation.DemoAnnotation;
@Controller
public class DemoController {
@RequestMapping("/hello")
@ResponseBody
public String demo(@DemoAnnotation Demo req) {
Preconditions.checkNotNull(req);
System.out.println(String.valueOf(req));
return "success";
}
}
需要配置:
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="customArgumentResolvers">
<list>
<bean class="com.hp.share.handler.DemoProcessor" />
</list>
</property>
</bean>
<mvc:annotation-driven />
此处切记 <mvc:annotation-driven />并且它得在所有bean的下面。如果你配置了AnnotationMethodHandlerAdapter,就更应该将其放在配置的最后面了。
具体原因可查看Spring源码(跟DispatcherServlet即可)
如果测试时发现自己的代码不好使,可debug DispatcherServlet。多半是因为【配置出错或者是HandlerAdapter引用错误(还是配置错误)
就这样,就可以轻轻松松的获取到自己自定义注解的内容了。如果想对Method进行注解,依然可以使用这个类的,详情可查看源码。