IDEA项目搭建十一——添加拦截器、忽略URL大小写、启动事件

程序启动时如果需要添加某些初始化代码可以使用以下事件处理

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 * 程序初始化事件
 */
@Component
public class ApplicationEventListener implements ApplicationListener {
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
//        if (event instanceof ApplicationEnvironmentPreparedEvent) {
//            // 初始化环境变量
//        }else if(event instanceof ApplicationPreparedEvent){
//            // 初始化完成
//        }else if (event instanceof ContextRefreshedEvent) {
//            // 应用刷新
//        }else if (event instanceof ApplicationReadyEvent) {
//            // 应用已启动完成
//        }else if (event instanceof ContextStartedEvent) {
//            // 应用启动,需要在代码动态添加监听器才可捕获
//        }else if (event instanceof ContextStoppedEvent) {
//            // 应用停止
//        }else if (event instanceof ContextClosedEvent) {
//            // 应用关闭
//        }else {}
    }
}

过滤用户登录状态验证时普遍使用拦截器或过滤器spring boot 2.0使用以下方式

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 请求拦截器
 * 参考资料:https://www.cnblogs.com/holly8/p/6178828.html
 * 普遍继承HandlerInterceptorAdapter抽象类,其中多提供了一个异步拦截方法afterConcurrentHandlingStarted(),我们用不到所以直接实现基础接口
 * 调用顺序:preHandler(可多个) -> Controller -> postHandler(可多个) -> model渲染-> afterCompletion(可多个)
 */
public class RequestInterceptor implements HandlerInterceptor {

    /**
     * Action执行前调用
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        try {
            System.out.println("调用拦截器");
            //判断用户会话状态
            if (0 > 0) {
                System.out.println("拦截验证-已登录");
                return true;
            } else {
                System.out.println("拦截验证-未登录");
                //根据header标识判断当前请求是否为Ajax请求
                if (request.getHeader("x-requested-with") == null){
                    //如果不是Ajax请求则重定向
                    response.sendRedirect("/admin");//重定向回登录页
                }else {
                    //如果是Ajax则更改状态码通知前端
                    //response.sendError(580,"自定义错误");//如果想提示错误并根据配置文件自动跳转到错误页面,则使用sendError
                    response.setStatus(401);//登录异常(401)权限验证不通过(403)如果只是改变状态码自己做后续处理,则使用setStatus
                    /*
                    下面是直译官方API文档的内容:
                    sendError(int sc):使用指定的状态码并清空缓冲,发送一个错误响应至客户端。如果响应已经被提交,这个方法会抛出IllegalStateException。使用这个方法后,响应则应该被认为已被提交,且不应该再被进行写操作了。
                    sendError(int sc, String msg):使用指定的状态码发送一个错误响应至客户端。服务器默认会创建一个HTML格式的服务错误页面作为响应结果,其中包含参数msg指定的文本信息,这个HTML页面的内容类型为“text/html”,
                    保留cookies和其他未修改的响应头信息。如果一个对应于传入的错误码的错误页面已经在web.xml中声明,那么这个声明的错误页面将会优先于建议的msg参数服务于客户端。(ps:相比较上面的方法,我更倾向于前者。
                    使用上面的方法,可以通过定制不同状态的响应结果显示于客户端,我们应该不想让客户端看到服务器创建出的简单粗暴的页面吧?)
                    setStatus(int sc):设置响应的状态码。这个方法被用于当响应结果正常时(例如,状态码为SC_OK或SC_MOVED_TEMPORARTLY)设置响应状态码。如果发生错误,而且来访者希望调用在web应用中定义的错误页面作为显示,
                    那么应该使用sendError方法代替之。使用setStatus方法之后,容器会清空缓冲并设置Location响应头,保留cookies和其他响应头信息。
                    总结:sendError适用于报错且存在对应的报错页面配置作为输出显示的情况,而setStatus适用于正常响应的情况,仅仅可以改变响应状态码而已。
                     */
                }
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Action执行后,View渲染前调用
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {

    }

    /**
     * View渲染后调用,整个流程执行结束调用
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

    }
}

 注入拦截器到web中

import org.springframework.context.annotation.Configuration;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 配置类
 * WebMvcConfigurerAdapter已被废弃,官方推荐改用WebMvcConfigurer
 */
@Configuration
public class MyInterceptorConfig implements WebMvcConfigurer {

    /**
     * 注入拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //将拦截器注入进程序,可同时注入多个拦截器
        //registry.addInterceptor(new RequestInterceptor()).addPathPatterns("/**");
        /*
        使用addPathPatterns增加拦截规则,使用excludePathPatterns排除拦截规则
        /admin/**:代表http://域名/admin/** 拦截该目录下的所有目录及子目录
        /admin:代表http://域名/admin 仅拦截此形式访问(无法拦截/admin/ 形式)
        /admin/*:代表http://域名/admin/* 拦截该目录的所有下级目录不包含子目录(可以拦截/admin/ 形式)
         */
        registry.addInterceptor(new RequestInterceptor())
                .addPathPatterns("/admin/**")
                .excludePathPatterns("/admin")
                .excludePathPatterns("/admin/*")
                .excludePathPatterns("/admin/content/**");
    }

    /**
     * 注入路径匹配规则
     */
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        //设置忽略请求URL的大小写
        AntPathMatcher matcher = new AntPathMatcher();
        matcher.setCaseSensitive(false);
        configurer.setPathMatcher(matcher);
        //设置匹配规则
        /*
         setUseSuffixPatternMatch : 设置是否是后缀模式匹配,如“/user”是否匹配/user.*,默认true即匹配
         setUseTrailingSlashMatch : 设置是否自动后缀路径模式匹配,如“/user”是否匹配“/user/”,默认true即匹配
         */
        configurer.setUseSuffixPatternMatch(false).setUseTrailingSlashMatch(true);
    }
}

 

posted @ 2018-07-19 11:44  taiyonghai  阅读(2191)  评论(0编辑  收藏  举报