从零开始学springboot-6.手写拦截器和自定义注解

Posted DaenMax

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从零开始学springboot-6.手写拦截器和自定义注解相关的知识,希望对你有一定的参考价值。

我们想实现 不同的请求路由、参数(例如token识别用户)对不同的请求做出处理和拒绝的情况,可以使用shiro和spring security,这里我们为了学习,所以我们尝试通过写自定义注解和拦截器来满足我们比较个性化的需求。

新建注解

在base目录下新建一个目录

annotation

在annotation目录下新建一个注解Admin.java,代码如下

package com.example.demo.base.annotation;

import java.lang.annotation.*;

//定义可以在方法和类上使用此注解
@Target(ElementType.METHOD,ElementType.TYPE)
//定义的这个注解是注解,会在class字节码文件中存在,在运行时可以通过反射获取到。
@Retention(RetentionPolicy.RUNTIME)
//定义子类可以继承父类中的该注解
@Inherited

public @interface Admin 


新建拦截器

在base目录下新建一个目录

interceptor

在interceptor目录下新建一个文件MyInterceptor.java,代码如下

package com.example.demo.base.interceptor;

import com.example.demo.base.annotation.Admin;
import com.example.demo.base.vo.Result;
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;

public class MyInterceptor implements HandlerInterceptor 
    /**
     * 在请求处理之前进行调用(Controller方法调用之前)
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception 
        response.setHeader("content-type","application/json; charset=utf-8");
        //判断请求的方法上是否有注解
        boolean haveAnnotataion = handler.getClass().isAssignableFrom(HandlerMethod.class);
        //如果有注解,判断是否是MyAnnotation
        if (haveAnnotataion)
            Admin admin = ((HandlerMethod)handler).getMethodAnnotation(Admin.class);
            //判断是否有admin注解
            if(admin != null)
                String id = request.getParameter("id");
                if("1".equals(id))
                    return true;
                else
                    response.getWriter().write(Result.error("你没有权限").toJsonString());
                    return false;
                
            
        
        return true;
    

    /**
     * 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception 
    

    /**
     * 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception 
    


说明

我们主要在preHandle方法下业务代码,这里的例程是请求参数中id=1代表是admin,可以正常使用接口,否则就返回无权限

配置拦截器

在interceptor目录下新建一个文件MyInterceptorConfig.java,代码如下

package com.example.demo.base.interceptor;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 拦截器配置类
 */
@Configuration
public class MyInterceptorConfig implements WebMvcConfigurer 
    @Override
    public void addInterceptors(InterceptorRegistry registry)
        //注册拦截器
        InterceptorRegistration registration = registry.addInterceptor(new MyInterceptor());

        //添加拦截请求
        registration.addPathPatterns("/user/**");

        //添加不拦截的请求
        registration.excludePathPatterns("/test/**");
    



如何使用

在我们控制器中,想要加权限的方法上,加上@Admin即可

测试效果演示

成功的

失败的

后话

以上只是一个例子,大家可以在HttpServletRequest request中拿到各种参数,例如token,然后进行你的鉴权业务,同时,可以写很多个注解,以满足不同的业务需求。

至此,项目结构如下

以上是关于从零开始学springboot-6.手写拦截器和自定义注解的主要内容,如果未能解决你的问题,请参考以下文章

从零开始学spring源码之xml解析:默认标签解析

从零开始学spring源码之xml解析:默认标签解析

《从零开始学Swift》学习笔记(Day58)—— Swift编码规范之变量或常量声明规范

java 从零开始手写 RPC (07)-timeout 超时处理

java 从零开始手写 redisLRU 缓存淘汰策略详解

从零开始手写 mybatis- mybatis 事务管理机制详解