2.SpringBoot学习笔记—过滤器、监听器、拦截器

本文围绕SpringBoot展开,介绍了过滤器、监听器和拦截器。过滤器可对请求过滤和响应后处理,实现访问权限控制等功能;监听器能监听域对象的创建和销毁事件,可统计在线人数;拦截器在方法访问前后加入功能,用于权限验证等,还提及了相关配置类和测试Controller。

过滤器

过滤器 (filter)简介

过滤器 (filter): 用于对指定的请求进行 过滤,然后将请求交给对应的 servlet 进行处理并生成响应,最后filter再对服务器响应进行后处理。

  • 可以实现 访问权限控制过滤敏感词汇压缩响应信息 等功能。

过滤器 配置类: FilterConfig.java

// 标识本类为配置类
@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<LoginFilter> registFilter() {
        // 创建注册器
        FilterRegistrationBean<LoginFilter> registration = new FilterRegistrationBean<LoginFilter>();
        // 设置过滤器
        registration.setFilter(new LoginFilter());

        // 设置属性exclusions,不需要过滤的URL
        registration.addInitParameter("exclusions", "/user/login");

        // 添加过滤规则
        registration.addUrlPatterns("/*");
        // 过滤器设置名称
        registration.setName("LoginFilter");
        // 设置过滤器顺序,值越小优先级越高
        registration.setOrder(1);

        return registration;
    }
}

登录过滤器: LoginFilter.java

public class LoginFilter implements Filter {

    // 存储不需要过滤的URLs,一个对象
    private static String exclusions;
    // 存储不需要过滤的URLs,exclusions分解而来的字符串数组
    private static String[] ALLOWEDURLS;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub
        // 获取在filterconfig中配置好的,不需要过滤的URLs
        exclusions = filterConfig.getInitParameter("exclusions");
        if (!exclusions.isEmpty()) {
            // 获取不需要过滤的URLs,可以直接访问的URLs
            ALLOWEDURLS = exclusions.split(",");
        }
    }

    @Override
    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse, FilterChain chain)
            throws IOException, ServletException {

        // 强转
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;

        // 获取当前请求的URL
        String url = request.getRequestURI();

        // 获取session,false表示如果没有获取到也不会创建
        HttpSession session = request.getSession(false);
        // 如果当前请求的URL不需要过滤或者已经登录的用户的请求,则继续处理
        if (isAllowed(url) || session != null && session.getAttribute("user") != null) {
            chain.doFilter(request, response);
        } else {
            // 若用户没有登录,否则直接返回
            render(response, "not login");
        }
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    // 当前请求是否需要过滤
    public boolean isAllowed(String url) {
        for (String ALLOWEDURL: ALLOWEDURLS) {
            if (ALLOWEDURL.equals(url)) {
                return true;
            }
        }
        return false;
    }

    // 返回请求失败消息
    public void render(HttpServletResponse response, String msg) throws IOException {
        // 构造返回消息
        ResultObject resultObject = new ResultObject(-1, "fail", msg);

        // 生成json数据
        JSONObject object = new JSONObject(resultObject);

        // 返回json数据
        response.setContentType("application/json;charset=UTF-8");
        OutputStream out = response.getOutputStream();
        out.write(object.toString().getBytes("UTF-8"));
        out.flush();
        out.close();
    }

}

监听器

监听器 (listener)简介

监听器 (listener): 用于监听 servletContextHttpSessionservletRequest域对象创建销毁 事件。在事件发生前后做一些必要的处理。

  • 可以实现 在线人数统计 等功能。

监听器 配置类: ListenerConfig.java

// 标识本类为配置类
@Configuration
public class ListenerConfig {

    @Bean
    public OnlineListener init() {
        return new OnlineListener();
    }
}

在线人数监听器: OnlineListener.java

@WebListener
public class OnlineListener implements HttpSessionListener{

    // 记录当前登录用户数
    private int onlineNumber = 0;

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        // 监听到创建了新的session,在线用户累加1
        onlineNumber++;
        // 设置session属性
        se.getSession().getServletContext().setAttribute("onlineNumber", onlineNumber);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        // 监听到销毁了旧的session,在线用户减少1
        onlineNumber--;
        // 设置session属性
        se.getSession().getServletContext().setAttribute("onlineNumber", onlineNumber);
    }

}

拦截器

拦截器 (interceptor)简介

拦截器 (interceptor): 在 面向切面编程 (AOP) 中用于在 某个方法 被访问之前进行 拦截,然后在处理前后 加入某些功能

  • 一般拦截器方法都是通过 动态代理 的方式实现,可以通过它来进行 权限验证判断用户是否登陆日志记录

拦截器 配置类: InterceptorConfig.java

// 标识本类为配置类
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport{

    @Autowired
    private WordInterceptor wordInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册敏感词汇拦截器,设置拦截路径
        registry.addInterceptor(wordInterceptor).addPathPatterns("/user/search");

        super.addInterceptors(registry);
    }
}

单词统计拦截器: WordInterceptor.java

@Component
public class WordInterceptor implements HandlerInterceptor{

    // 设置敏感词汇
    private static final String[] forbitWords = {"apple", "pear", "peach", "Lemon "};

    // 处理前方法
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws Exception {
        // 获取请求中的参数word
        String word = request.getParameter("word");
        // 与敏感词汇对比
        for (String forbitWord: forbitWords) {
            if (word.equals(forbitWord)) {
                render(response, "search word " + "'" + word + "'" + " is not allowed.");
                // 返回假,中断请求
                return false;
            }
        }

        // 返回真,继续处理请求
        return true;
    }

    // 处理后方法
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
    }

    // 完成后方法
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
    }

    // 返回失败消息
    public void render(HttpServletResponse response, String msg) throws IOException {
        ResultObject resultObject = new ResultObject(-1, msg, null);

        JSONObject object = new JSONObject(resultObject);

        response.setContentType("application/json;charset=UTF-8");
        OutputStream out = response.getOutputStream();
        out.write(object.toString().getBytes("UTF-8"));
        out.flush();
        out.close();
    }
}

测试Controller

UserController.java

@RestController
@RequestMapping("user")
public class UserController {

    // 统计在线用户数,请求方法类型get,URL:/user/online
    @GetMapping("online")
    public ResultObject setSession(HttpServletRequest request,
                                   HttpServletResponse response) {
        // 获取session
        HttpSession session = request.getSession();
        // 获取sessionid,即JSESSIONID
        String sessionId = session.getId();
        System.out.println(sessionId);

        // 获取session属性
        Object onlineNumber = session.getServletContext().getAttribute("onlineNumber");
        System.out.println(onlineNumber);
        // 返回结果
        return new ResultObject(onlineNumber);
    }

    // 登录验证用户,请求方法类型post,URL:/user/login
    @PostMapping("login")
    public ResultObject login(@RequestBody User user, HttpServletRequest request, HttpServletResponse response) {

        // 正确账号密码,模拟数据库中的信息
        User realUser = new User("jacky", "112233");
        // 判断账号、密码是否正确
        if (realUser.equals(user)) {
            // 获取session,获取不到则新建
            HttpSession session = request.getSession();

            // 获取sessionid,即JSESSIONID
            String sessionId = session.getId();
            System.out.println(sessionId);

            // 设置session属性user
            session.setAttribute("user", user);

            return new ResultObject("login success");
        } else {
            return new ResultObject(-1, "fail", "login fail");
        }
    }

    // 搜索功能,过滤敏感词汇,请求方法类型get,URL:/user/search
    @GetMapping("search")
    public ResultObject search(@RequestParam String word) {
        // 若关键字是敏感词,在拦截器中已经被拦截不可能走到这里
        return new ResultObject("search word " + "'" + word + "'" + " is valid.");
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BinarySage

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值