SprintBoot配置Filter、Servlet

Easter79
• 阅读 733

今天想要手动的实现以下Filter权限控制,但是发现使用springboot的filter和之前的不一样,之前使用Servlet3.0只需要使用@WebFilter注解或者在web.xml文件中配置以下即可。但是springboot中没有web.xml文件,于是我很自然的使用注解,然后发现怎么也配置不上去,那么怎么办呢,没错,查文档。

经过一番查阅,原来spring中提供了三个注册器:FilterRegistrationBean、ServletRegistrationBean、ListenerRegistrationBean,分别用来配置Filter、Servlet和Listener,那么知道怎么回事了,下面先写一个Filter

package xin.sun.filter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * Created by sun on 2017/8/4.
 */

public class LoginFilter extends  HttpFilter{

    /**
     * ajax请求头key
     */
    public static final String AJAX_HEAD_KEY = "x-requested-with";

    /**
     * ajax请求头值
     */
    public static final String AJAX_HEAD_VALUES = "XMLHttpRequest";

    private String uncheckedUrl;
    private String sessionKey;

    @Override
    public void doFilter(HttpServletRequest servletRequest, HttpServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpSession session = servletRequest.getSession();

        List<String> urls = Arrays.asList(uncheckedUrl.split(","));
        String servletPath = servletRequest.getServletPath();
        //不需要过滤的URL直接放行
        if(urls.contains(servletPath)){
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }

        String username = (String) session.getAttribute(sessionKey);
        if (username == null || "".equals(username)) {

            //判断Ajax请求
            String reqMethod = servletRequest.getHeader(AJAX_HEAD_KEY);
            if (AJAX_HEAD_VALUES.equalsIgnoreCase(reqMethod)) {
                servletResponse.setHeader("sessionstatus","timeout");
                servletResponse.sendError(518, "session timeout.");
                filterChain.doFilter(servletRequest, servletResponse);
                return ;
            }

            //非ajax请求
            servletResponse.setHeader("Cache-Control", "no-store");
            servletResponse.setDateHeader("Expires", 0);
            servletResponse.setHeader("Prama", "no-cache");

            //获取绝对路劲的根路径
            String basePath = servletRequest.getScheme()+"://"+servletRequest.getServerName()+":"+
                    servletRequest.getServerPort()+servletRequest.getContextPath();

            //重定向到登录页面
            servletResponse.sendRedirect(basePath+"/login");
            return;
        }

        filterChain.doFilter(servletRequest,servletResponse);
    }

    /**
     * 初始化,获取初始化参数
     */
    public void init(){
        uncheckedUrl = getFilterConfig().getInitParameter("uncheckedUrl");
        sessionKey = getFilterConfig().getInitParameter("sessionKey");
    }
}

其实很多人在拦截的时候没有拦截ajax请求,那么会导致一个什么问题呢?当你的session超时后,你在页面中还可以发送ajax请求,是不是很荒唐,没错filter拦截ajax请求是需要做判断的,上面也给出了代码。

这个HttpFilter是我仿照HttpServlet写的,还是很实用的,我也贴出来一份

package xin.sun.filter;

import javax.servlet.*;
import javax.servlet.FilterConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by sun on 2017/8/4.
 * 仿照HttpServlert,自定义HttpFilter,简化开发,
 */
public abstract class HttpFilter implements Filter {

    private FilterConfig filterConfig;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
        this.init();
    }

    /**
     * 获取过滤器配置对象
     * @return
     */
    public FilterConfig getFilterConfig(){
        return this.filterConfig;
    }

    /**
     * 获取初始化参数
     * @param key
     * @return
     */
    public String getInitParameter(String key){
        return  getFilterConfig().getInitParameter(key);
    }

    /**
     * 获取应用上下文
     * @return
     */
    public ServletContext getServletContext() {
        return this.getFilterConfig().getServletContext();
    }

    /**
     * 提供用户初始化方法
     * @throws ServletException
     */
    public void init() throws ServletException {
    }

    /**
     * 重写doFilter(),把Servlert***转换为HttpServlert***
     * @param servletRequest
     * @param servletResponse
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request;
        HttpServletResponse response;
        try {
            request = (HttpServletRequest)servletRequest;
            response = (HttpServletResponse)servletResponse;
        } catch (ClassCastException var6) {
            throw new ServletException("non-HTTP request or response");
        }
        this.doFilter(request,response,filterChain);
    }

    /**
     * 提供一个doFilter()方法,用户必须实现
     * @param servletRequest
     * @param servletResponse
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    public abstract void doFilter(HttpServletRequest servletRequest, HttpServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException ;

    @Override
    public void destroy() {

    }
}

好了,重头戏来了,在springboot中配置这个filter

package xin.sun.filter;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Created by sun on 2017/8/4.
 * 该类用于注册Filter
 */

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean loginFilterRegistration(){

        FilterRegistrationBean registration = new FilterRegistrationBean();

        //注入过滤器
        registration.setFilter(new LoginFilter());

        //拦截规则
        registration.addUrlPatterns("/*");

        //初始化参数
        registration.addInitParameter("uncheckedUrl","/login,/registry,/loginServlet");
        registration.addInitParameter("sessionKey","SESSIONKEY");

        //过滤器名称
        registration.setName("loginFilter");

        //是否自动注册 ,false 取消Filter的自动注册
        registration.setEnabled(true);

        //过滤器顺序
        registration.setOrder(10);

        return registration;
    }


}

那么Servlet其实原理是一样的,只是配置上略有不同罢了,自己去体会一下,这里就只给出代码了

package xin.sun.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by sun on 2017/8/4.
 */
public class LoginServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //获取绝对路劲的根路径
        String basePath = req.getScheme()+"://"+req.getServerName()+":"+
                req.getServerPort()+req.getContextPath();
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if(username.equals("admin")&&password.equals("123456")){
            req.getSession().setAttribute("SESSIONKEY",username);
            resp.sendRedirect(basePath + "/indexPage");
        }else {
            resp.sendRedirect(basePath + "/login");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}


package xin.sun.servlet;

import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by sun on 2017/8/4.
 */

@Configuration
public class ServletConfig {

    @Bean
    public ServletRegistrationBean loginServletRegistration(){
        ServletRegistrationBean registration = new ServletRegistrationBean();

        //设置servlet
        registration.setServlet(new LoginServlet());

        //是否自动注册 ,false 取消Filter的自动注册
        registration.setEnabled(true);

        //设置URL映射地址
        List urlMapping = new ArrayList<String>();
        urlMapping.add("/loginServlet");
        registration.setUrlMappings(urlMapping);

        //设置加载就启动
        registration.setLoadOnStartup(1);

        //设置初始化参数
        Map initParams = new HashMap<String, String>();
        initParams.put("key1","value1");
        registration.setInitParameters(initParams);

        return registration;
    }

}

那么Listener也是一样的操作,照葫芦画瓢,留给大家去试试吧

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k