Spring boot中使用servlet filter

liuyuhang原创,未经允许请勿转载!

在web项目中经常需要一些场景,如参数过滤防止sql注入,防止页面攻击,空参数矫正等,

也可以做成token验证,session验证,点击率统计等。

为了这种业务,经常会需要写过滤器(Filter)。

servlet提供的默认过滤器比较好用,配置也还算方便;

转入springboot开发后,注解也并不复杂,原理依旧。

使用filter的步骤并不复杂,主要分为几个步骤:

  1、新建class 实现Filter抽象类(javax.servlet.Filter)

  2、override三个方法(init,doFilter,destroy)

  3、编写ParameterRequestWrapper类继承HttpServletRequestWrapper类(稍后说明原因)

  4、ParameterRequestWrapper类构造器

  5、构造器中复写父类构造器并将request.getParameterMap加入子类成员变量

  6、编写addParam方法留用

  7、修改参数并调用ParameterRequestWrapper实例保存params

  8、调用doFilter方法中的FilterChain变量,将修改后的request重新封装

  9、在springboot入口方法中添加注解@ServletComponentScan注册filter

其中1、2步骤为必须的,其余的步骤为修改request参数使用的封装方式。

1、新建class实现Filter抽象类(javax.servlet.Filter);

2、override三个方法(init,doFilter,destroy);代码如下:

 package lyh.java.filterAndInteceptor;

 import java.io.IOException;

 import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter; import org.springframework.core.annotation.Order; @Order(1)//多个filter的时候,该序号越小,越早执行
@WebFilter(filterName = "FirstFilter", urlPatterns = "/*")//url过滤配置,并非包配置
public class MyMvcFilter implements Filter{ @Override
public void init(FilterConfig filterConfig) throws ServletException {
//这里写init逻辑,该init将在服务器启动时调用
} @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//request处理逻辑
//request在封装逻辑
//chain重新写回request和response
} @Override
public void destroy() {
//这里写destroy逻辑,该destroy逻辑将在服务器关闭时调用
}
}

9、在springboot入口方法中添加注解@ServletComponentScan注册filter,代码如下:

 package lyh.java;

 import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.web.servlet.ServletComponentScan; import lyh.java.config.DataSourceConfig; @SpringBootConfiguration//springboot基础配置注解
@ServletComponentScan//springboot servlet filter
public class Run { public static void main(String[] args) throws Exception {
SpringApplication.run(Run.class, args);
}
}

到这里,就完成了Filter的简单创建了,可以自行测试使用

创建Filter,一般目的是为了过滤一些参数,如果是为了中断该访问,应该是创建Interceptor

对于java中的mvc,过滤或者修改参数,针对的主要是request中的parameterMap的修改。

当然还有很多好用的操作,这里不做讨论了。

修改request实例,思路上有两个步骤是必须要考虑的:

①如何获取request中的parameterMap并且修改?

②如何将修改后的parameterMap重新传递回去,使得controller能够不受影响?

对于如何解决以上两个问题,思路上也要经过两个步骤:

①常用的是request.getParameter或request.getParamerterMap方法,但是ServletRequest是一个接口;

该接口定义了getParameterMap抽象方法,只要找到该接口的实现类,继承该类,利用java继承原理,

相互继承的类,调用父类方法的时候,若子类复写了该方法,则默认调用子类方法。

以此来实现request的重新封装。

②在子类中定义add方法,来添加新的param,同时该param与request中原有的param进行校对,去重,

保证子类的覆盖父类的,这样获取param的时候,不会有所察觉。

在一番查找之后,发现了一个类,来专门处理request对象的,截图如下

注意类注解:Methods default to calling through to the wrapped request object.意为request默认调用该封装对象

注意截图中的构造器,该构造器传入servletRequest对象,因此该带参构造器肯定要被子类重写

于是,编写一个类,继承该类,同时修改构造器,复写getParameter方法,提供一个map作为request内容的缓存;

使得复写的getParameter能够从此缓存中获取param即可,代码如下,注释完善,不再赘述:

 package lyh.java.tools;

 import java.util.HashMap;
import java.util.Map; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper; /**
* 重写ParameterRequestWrapper继承HttpServletRequestWrapper并重写部分方法
* 构造器调用父类构造器
* 重写param作为缓存
* 重写getParameter获取子类缓存
* 增加两个add方法修改该缓存
* @author Liuyuhang
*
*/
public class ParameterRequestWrapper extends HttpServletRequestWrapper { /**
* 初始化params,作为getParameter方法获取的参数列表,内首先包含req中的paramMap,再修改
*/
private Map<String , String[]> params = new HashMap<String, String[]>(); /**
* 重载构造器,并调用父类构造器,将参数写入子类params
* @param request
*/
public ParameterRequestWrapper(HttpServletRequest request) {
super(request);// 将request交给父类,以便于调用对应方法的时候,将其输出,其实父亲类的实现方式和第一种new的方式类似
this.params.putAll(request.getParameterMap());//将参数表,赋予给当前的Map以便于持有request中的参数
} /**
* 重写getParameter,代表参数从当前类中的map获取
*/
@Override
public String getParameter(String name) {
String[]values = params.get(name);
if(values == null || values.length == 0) {
return null;
}
return values[0];
} /**
* 获取子类param缓存的方法
*/
public Map<String,String[]> getParamsMap(){
return this.params;
}
/**
* 写入一个map的方法
* @param map
*/
public void addParamsMap(Map<String , Object> map) {
for(Map.Entry<String , Object>entry : map.entrySet()) {
addParam(entry.getKey() , entry.getValue());
}
}
/**
* 写入一个参数的方法
* @param name
* @param obj
*/
public void addParam(String name , Object obj) {
if(obj != null) {
if(obj instanceof String[]) {
params.put(name , (String[])obj);
}else if(obj instanceof String) {
params.put(name , new String[] {(String)obj});
}else {
params.put(name , new String[] {String.valueOf(obj)});
}
}
} }

返回Filter类中的doFilter方法,对该方法进行加工。思路是:

①封装ServletRequest实例为子类抽象HttpServletRequest对象实例,调用刚刚写的方法的构造器

将ParameterRequestWrapper实例化得实例对象rpw;

②获取该prw的param,一一过滤,如字符串trim,修改null或者空字符串,修改时间日期格式,

获取token来进行身份验证之类。

③调用doFilter中的FilterChain参数,将重新写过的request和response写回。

具体代码如下:

     @Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
//将request封装为子类
HttpServletRequest httpReq = (HttpServletRequest) req;
//调用复写的构造器重新封装request
ParameterRequestWrapper prw = new ParameterRequestWrapper(httpReq);
//这里写requtst过滤内容的逻辑,如字符串trim,修改null或者空字符串,修改时间日期格式,获取token来进行身份验证之类。
prw.addParam("user", "Filter-user");
//调用chain执行filter并写回参数
chain.doFilter(prw, resp);
}

写个类测试下。代码如下:

 package lyh.java.controller;

 import javax.servlet.http.HttpServletRequest;

 import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; @RestController//restFull Controller注解,返回json格式
public class hello { @RequestMapping("/hello")
public String helloTest(HttpServletRequest req) throws Exception {
String user = req.getParameter("user");
System.out.println("user:"+user);
return "hello world! "+user;
} }

运行结果如下:

完工!

以上!✧(∗≧ꇴ≦)人(≧ꈊ≦∗)✧

Spring boot中使用servlet filter的更多相关文章

  1. 从零开始的Spring Boot(2、在Spring Boot中整合Servlet、Filter、Listener的方式)

    在Spring Boot中整合Servlet.Filter.Listener的方式 写在前面 从零开始的Spring Boot(1.搭建一个Spring Boot项目Hello World):http ...

  2. Spring Boot中使用Servlet与Filter

    在Spring Boot中使用Servlet,根据Servlet注册方式的不同,有两种使用方式.若使用的是Servlet3.0+版本,则两种方式均可使用:若使用的是Servlet2.5版本,则只能使用 ...

  3. Spring boot中注册Servlet

    Spring boot中注册Servlet 如何在spring boot项目中注册Servlet呢? 如何在spring boot项目中注册Servlet呢? 由于没有web.xml,无法直接在xml ...

  4. spring boot中使用servlet、listener和filter

    spring boot中支持使用java Web三大组件(servlet.listener和filter),但是坑比较多,主要是spring boot内嵌tomcat和独立tomcat服务器有一些细节 ...

  5. 解决Spring Boot中,通过filter打印post请求的 request body 问题

    http://slackspace.de/articles/log-request-body-with-spring-boot/ (filter + RequestWrapper:最优雅的写法) ht ...

  6. spring boot 中使用servlet

  7. Spring Boot中一个Servlet主动断开连接的方法

    主动断开连接,从而返回结果给客户端,并且能够继续执行剩余代码. 对于一个HttpServletResponse类型的对象response来说,执行如下代码: response.getWriter(). ...

  8. 传统的Servlet在spring boot中怎么实现的?

    传统的Servlet在spring boot中怎么实现的? 本文主要内容: 1:springboot一些介绍 2:传统的servlete项目在spring boot项目中怎么实现的?web.xml.u ...

  9. Spring Boot 自定义注册 Servlet、Filter、Listener

    前言 在 Spring Boot 中已经移除了 web.xml 文件,如果需要注册添加 Servlet.Filter.Listener 为 Spring Bean,在 Spring Boot 中有两种 ...

随机推荐

  1. java使用poi.3.10读取excel 2007以上版本(xlsx格式)

    1.在使用过程中,一直报错 throw new ClassNotFoundException(name);原因:没有导入xmlbeans-2.6.0.jar包,建议在使用poi时,将所有包都导入进工程 ...

  2. 网页设计,Access入门 2010,语文

    Access入门 2010(select查询) order by(按升序排列)?+desc(按降序排列) group by(进行分组,下一行只能用having) sum(数值总数)?+as?(新字段的 ...

  3. idea 正则全局替换文件文本

    上一遍写到了log4j2分层输出日志的内容,但因为项目原先采用的log4j,现使用log4j2,需将原有log4j的代码进行替换,以前的代码类似如下: private static final Log ...

  4. java常用API之System类

    System中代表程序所在系统,提供了对应的一些系统属性信息,和系统操作.System类不能手动创建对象,因为构造方法被private修饰,阻止外界创建对象.System类中的都是static方法,类 ...

  5. scss-&父选择器标识符

    在使用选择器嵌套的时候有一种情况需要特别注意,先看一段scss代码实例: .text a { color: blue; :hover { color: red } } 也许写此段代码目的是为了将其编译 ...

  6. vue学习笔记之基础篇

    本文主要记录学习vue的一些基础内容及常用知识点的记录. 1.搭建脚手架 vue init webpack vue-demo 初始化一个使用webpack打包的vue项目 npm install 安装 ...

  7. [原创]vs2012创建的ado.net模型无法实例化的问题

    最近从vs2010升级到vs2012,建立数据模型,发现生成的东西跟以前不一样了,而且也无法实例化使用.百度尝试了n种关键词,终于被我找到解决的方法.在这里记录一下. 1.打开设计器,也就是双击这个 ...

  8. 创建 XMLHttpRequest 对象时IE的兼容问题解决办法

    为了应对所有的现代浏览器,包括 IE5 和 IE6,请检查浏览器是否支持 XMLHttpRequest 对象.如果支持,则创建 XMLHttpRequest 对象.如果不支持,则创建 ActiveXO ...

  9. 关于String s = new String("xyz");创建了几个字符串对象?的问题

    引用自这位朋友:http://blog.sina.com.cn/s/blog_6a6b14100100zn6r.html 首先让我们了解几个概念: 栈:由JVM分配区域,用于保存线程执行的动作和数据引 ...

  10. db2的count()函数和sum()函数的用法

    一.count()函数可以使用参数,例如count(*)和count(列名) count(*)用来计算在指定条件下,满足条件的行数,例如: select count(*) from tablename ...