通过注解实现拦截器

一、目的

在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就结束了,有什么问题,欢迎来吐槽!!!

猜你喜欢

转载自blog.csdn.net/qq_31289187/article/details/81020304