一、目的
在web项目中,定义拦截器就是为了防止用户没有登录而可以访问app、网页等,常用的方式就是拦截所有请求,从session中获取用户实例对象,判断是否为空。这种拦截,完全可以通过token和注解实现拦截,在调用action之前,判断是否登录,这种方式更加灵活多变。
二、注解小案例
1、需求:
定义了一个Persion类,四个属性:分别是姓名、年龄、电话号码、性别,分别对应四个get方法,只要是加了注解(@Intercept,并且返回值为true),就不能直接访问。
2、实现
定义Intercept注解
package cn.test.token;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by Tiger on 2018/7/12.
*/
@Target({ElementType.METHOD, ElementType.TYPE})//注解的范围是类、接口、枚举的方法上
@Retention(RetentionPolicy.RUNTIME)//被虚拟机保存,可用反射机制读取
public @interface Intercept {
boolean required() default true; //设置返回的默认值为true
}
定义Persion类
package cn.test.token;
/**
* Created by Tiger on 2018/7/12.
*/
public class Persion {
//姓名
private String name;
//年龄
private int age;
//电话号码
private String mobile;
//性别
private String sex;
public Persion(){}
public Persion(String name,int age){
this.name = name;
this.age = age;
}
public String getName(){
return name;
}
@Intercept
public int getAge() {
return age;
}
@Intercept
public String getMobile() {
return mobile;
}
public String getSex() {
return sex;
}
}
定义测试类
package cn.test.token;
import org.junit.Test;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Created by Tiger on 2018/7/12.
*/
public class AnnotationTest {
@Test
public void test() throws Exception {
//实例化一个对象
Persion persion = new Persion("Tiger",25,"157****3859","男");
//获取Persion类中所有方法
Method[] methods = Persion.class.getMethods();
//遍历methods,判断哪些方法有@AnnotationDemo这个注解
for(Method m : methods){
String methodName = m.getName();
//如果方法名中没有get,跳过
if(! methodName.contains("get")){
continue;
}
Intercept intercept = m.getDeclaredAnnotation(Intercept.class);
//判断annotationDemo是否为空
if(intercept != null){
continue;
}
System.out.println(methodName+":"+m.invoke(persion));
}
}
}
测试结果
在获取年龄和电话号码的方法上加了拦截,所有不能访问
可以在方法上设置值
小案例就share这么多,主要看token和注解实现app和web项目的拦截!!!
三、创建springboot Demo
1、demo结构
2、pom文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>springBootDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springBootDemo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--springboot的核心包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--springboot-mybatis的核心包-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<!--连接mysql驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--lombok,可以不要写bean的get、set、toString等方法-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.6</version>
</dependency>
<!--util-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<!-- 登录token用-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.0.2</version>
</dependency>
</dependencies>
<profiles>
<!--使用resource.tiger包写的配置文件application.properties-->
<profile>
<id>tiger-test</id>
<properties>
<deploy.type>tiger</deploy.type>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3、Controler类:
package com.example.demo;
import com.example.demo.annotation.Intercept;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* Created by yangyd on 2018/6/29.
*/
@RestController
@RequestMapping("spring")
public class Controller {
@RequestMapping(value = "say",method = RequestMethod.POST)
public Map say(HttpServletRequest request, HttpServletResponse response){
Map map = new HashMap<>();
map.put("name","tiger");
map.put("age",25);
return map;
}
@GetMapping(value = "user_info" )
@Intercept
public Response userInfo(){
User user = new User();
user.setAmount(new BigDecimal("0.2415"));
user.setMoney(new BigDecimal("12.1200000"));
user.setDete(new Date());
return new Response(user);
}
}
4、Intercept接口:
package com.example.demo.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by Tiger on 2018/7/9.
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Intercept {
//检验是否登录
boolean required() default true;
}
5、ControllerConfiguration类:
package com.example.demo.config;
import com.example.demo.interceptor.DemoInterceptor;
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.WebMvcConfigurer;
/**
* Created by Tiger on 2018/7/9.
*/
@Configuration
public class ControllerConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new DemoInterceptor()).addPathPatterns("/**");
}
@Bean
public DemoInterceptor demoInterceptor() {
return new DemoInterceptor();
}
}
6、DemoInterceptor类:
package com.example.demo.interceptor;
import com.example.demo.annotation.Intercept;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Created by Tiger on 2018/7/9.
* 配置拦截器进行拦截
*/
public class DemoInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle 运行了这里");
//判断如果不是请求control方法直接返回true
if(! (handler instanceof HandlerMethod)){
return true;
}
HandlerMethod method = (HandlerMethod) handler;
//判断访问的control是否添加LoginRequired注解
Intercept loginRequired = method.getMethodAnnotation(Intercept.class);
boolean required = true;
if (loginRequired != null){
required = loginRequired.required();
//如果添加了requird注解,则在消息请求头中查看token是否存在
String token = request.getHeader("token");
if (StringUtils.isEmpty(token)) {
return false;
}
System.out.println("token----------------:"+token);
// 从 http 请求头中取出 token,获取token的内容并解析,然后判断用户是否存在、是否登录、是否在线超时等
if ("token".equals(token)){
return true;
}else {
throw new Exception("用户没有登录,登录超时等");
}
}else {
return true;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
System.out.println("postHandle()");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
System.out.println("afterCompletion()");
}
}
Controler的userInfo方法上了注解:我这里主要是在请求头里加上token:token就可以访问,如果没有加或者token的值不是token会抛出异常
7、测试1:在请求头中没有加token
结果:
8、测试2:在请求头中加token,值不是token
结果:
9、测试3:在请求头中加token,值为token,测试结果
到这里,通过注解和token实现拦截器的demo就结束了,有什么问题,欢迎来吐槽!!!