通过前面的阅读,想必大家对注解都有了一个简单的理解,能够进行简单的应用了。下面我再给大家讲一种注解的使用。
其实,千变万化,注解还是那样子,就是通过反射获取注解,然后分析注解,从而实现逻辑的处理。
不知道大家有没有遇到过,一个controller类上加上了一个注解,然后所有的方法都会进行权限过滤或者身份验证什么的,我第一次碰到这种的时候,只有一个感觉---------厉害!
心里想的就是不愧是大神,随便搞搞就搞定一切!
其实现在回顾起来,也就是一个拦截加上注解的解析,实现了请求的过滤或者拦截,并没有什么特别高深的知识,还是那句话,会者不难,难者不会,真的深入进去,你就会发现,哦, 原来是这样!
下面我通过Spring中的拦截器处理,实现注解对方法的过滤。
新建一个拦截器。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface TestAnno {
//多个或者多种过滤,也可以直接使用下面的单种
String[] values() default {TestConstant.BOSS,TestConstant.STAFF};
// String value();
}
这个注解很好理解,就是一个数组集合,定义权限为BOSS或者STAFF,为了方便起见,我创建了一个存储常量的接口
package com.example.demoproject.constant;
public interface TestConstant {
String BOSS = "boss";
String STAFF = "staff";
}
下面就是构造一个拦截器,当然我需要构造一个拦截器的bean。因为加载拦截器是在加载ApplicationContext之前,直接加@Service或者@Component是无法注入成功的。所以要创建一个配置,把拦截器加载到Spring容器中。
package com.example.demoproject.filter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {
@Bean
public TestInterceptor testInterceptor(){
return new TestInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry){
// 拦截所以请求
registry.addInterceptor(this.testInterceptor()).addPathPatterns("/**");
}
}
这个配置类就是加载了一个TestInterceptor 的 Bean,然后把这个拦截器添加到拦截器集合中去。
接着就是实现这个拦截器了。我们先看下下Controller
package com.example.demoproject.controller;
import com.example.demoproject.annotion.TestAnno;
import com.example.demoproject.constant.TestConstant;
import com.example.demoproject.emun.TestEnum;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@TestAnno(values = TestConstant.BOSS)
public class TestController {
@PostMapping("/test")
@TestAnno(values = TestConstant.STAFF)
public Map<String,String> get(){
Map<String,String> map = new HashMap();
map.put("response","success");
return map;
}
}
因为这个注解是可以加到方法和类上的,所以我都加了一个示范(@Target({ElementType.TYPE,ElementType.METHOD}))
好,接下来我们看下拦截器的实现:
package com.example.demoproject.filter;
import com.alibaba.fastjson.JSON;
import com.example.demoproject.annotion.TestAnno;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.Method;
public class TestInterceptor implements HandlerInterceptor {
// 在业务处理器处理请求之前被调用
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
if(handler instanceof HandlerMethod){
HandlerMethod handlerMethod = (HandlerMethod)handler;
Method method = handlerMethod.getMethod();
System.out.println(method);
Class<?> aClass = method.getDeclaringClass();
TestAnno anno = aClass.getAnnotation(TestAnno.class);
System.out.println("anno:"+ JSON.toJSONString(anno.values()));
TestAnno anno1 = method.getAnnotation(TestAnno.class);
System.out.println("anno1:"+ JSON.toJSONString(anno1.values()));
System.out.println("--------------");
String name = request.getParameter("name");
System.out.println("name:"+name);
}
// System.out.println("输出request"+JSON.toJSON(request));
return true;
}
// 在业务处理器处理请求完成之后,生成视图之前执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception{
}
// 在DispatcherServlet完全处理完请求之后被调用,可用于清理资源
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception{
}
}
拦截器想必大家都有所了解,我就不多做介绍了,在这里主要处理的就是preHandle,在方法之前做处理。这个方法有一个返回值,boolean类型,返回true,继续向下走,返回false,直接被拦截。
从代码中可以看出,我们可以获取请求的方法,类,然后获取他们的注解,然后可以判断这个注解与预期是否一致,接着就是判断逻辑了(这一部分我没写,需要根据实际情况处理),如果校验不通过,返回false,校验通过的话就返回true。
这样的话,一个注解拦截请求或者过滤权限的结构就完成了,是不是不过如此?
感觉还行的话,就给个赞呗~