详细介绍了Java Web Servlet中的Filter过滤器的原理以及常见用法。

文章目录

  • 1 Filter接口
    • 1.1 过滤器的生命周期
    • 1.2 doFilter过滤方法
  • 2 Filter的使用
  • 3 Filter的执行顺序
    • 3.1 多个过滤器
  • 4 Filter的应用
    • 4.1 脏话过滤器
    • 4.2 编码过滤器
    • 4.3 统计IP访问次数
    • 4.4 禁止动态资源缓存的过滤器
    • 4.5 html标记过滤器

过滤器属于Servlet规范,从2.3版本就开始有了。主要用于对到资源的请求或来自资源的响应执行过滤、筛选操作。

当存在过滤器的时候,对于来自客户端的请求来说,请求必须先经过滤器,放行之后,才能到达Web资源;对于返回的响应来说,响应同样会经过滤器,才能到达Web服务器,进而响应给客户端。

过滤器可以做很多事情,常见的包括:

  1. 过滤脏敏感字符(绿一些敏感的字符串);
  2. 避免中文乱码(统一设置请求和响应的编码);
  3. 权限验证(规定只有带指定Session或Cookie的请求,才能访问资源);
  4. 用于实现自动登录;

1 Filter接口

过滤器在Java中对应着javax.servlet.Filter接口,仅此而已,实现了Filter接口的类就可以被称作过滤器,就是这么简单。

Filter接口中有三个抽象方法,其中init和destroy方法作为过滤器的申请周期方法!

public interface Filter {default public void init(FilterConfig filterConfig) throws ServletException {}public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain)throws IOException, ServletException;default public void destroy() {}
}

1.1 过滤器的生命周期

  1. 诞生:过滤器的实例是在web应用被加载时就完成的实例化,并调用init方法初始化的。servlet 容器在实例化Filter后只调用init方法一次。在要求过滤器执行任何过滤工作之前,init 方法必须成功完成。区别于Servlet,过滤器会全部立即初始化。
  2. 每个过滤器在init初始化方法都会传递一个 FilterConfig 对象,从该对象可以获取其初始化参数。并可通过FilterConfig获取 ServletContext对象,比如可以使用该对象加载筛选任务所需的资源。
  3. 存活:和应用的生命周期一致的。在内存中是单例的。针对拦截范围内的资源,每次访问都会调用void doFIlter(request,response.chain)进行拦截。
  4. 死亡:应用被卸载时,Filter将被调用,此时会调用destroy方法,该方法只会被调用一次。

1.2 doFilter过滤方法

过滤器在 doFilter 方法中执行过滤操作。

doFilter方法中有一个FilterChain 参数对象,该对象由Servlet容器创建并传递给开发人员的。FilterChain表示一个过滤器链,客户端请求的资源在链的末尾。

在当前过滤器中,如果复合过滤规则,那么可以使用FilterChain#doFilter方法调用链中的下一个过滤器器,或者如果调用过滤器是链中的最后一个过滤器,则该方法将调用链末尾的资源。

也就是说,一个Web应用中可以有多个过滤器,它们将会按照一定顺序形成一个过滤器链,在链的最末尾就是要访问的资源,当一个请求到来的时候,他必须通过所有的过滤器,才能访问到真正的资源。

2 Filter的使用

开发一个过滤器很简单,只需要实现Filter接口,实现doFilter方法。

public class FirstFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) {System.out.println("init");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("放行前");HttpServletRequest httpServletRequest= (HttpServletRequest) request;//获取当前请求的URLSystem.out.println(httpServletRequest.getRequestURL());//放行,调用下一个过滤器或者访问资源chain.doFilter(request, response);System.out.println("放行后");}@Overridepublic void destroy() {System.out.println("destroy");}
}

随后我们还需要部署这个filter。通常情况下,Filter过滤器在 Web 应用程序的部署描述符中配置,也就是web.xml文件,这类似于Servlet。

首先是定义一个Filter:

<filter><filter-name>FirstFilter</filter-name><filter-class>com.example.filter.FirstFilter</filter-class><!--当前过滤器的初始化参数,可以通过在init方法的参数FilterConfig对象获取--><init-param><param-name>aaa</param-name><param-value>bbb</param-value></init-param><init-param><param-name>ccc</param-name><param-value>ddd</param-value></init-param>
</filter>

一个<filter/>标签表示定义一个过滤器,<filter-name/>表示当前过滤器的name,<filter-class/>表示当前过滤器的类全路径名,<init-param/>表示当前过滤器的初始化参数,可以通过在init方法的参数FilterConfig对象获取这些参数。

随后我们还需要定义这个过滤器可以作用于哪些资源或者哪些Servlet!

<filter-mapping><filter-name>FirstFilter</filter-name><!--指定拦截指定路径的资源URL--><url-pattern>/aa/*</url-pattern>
</filter-mapping>
<filter-mapping><filter-name>FirstFilter</filter-name><!--指定拦截指定的ServletName--><servlet-name>Servlet2</servlet-name><!--调度程序--><!--<dispatcher>REQUEST</dispatcher>-->
</filter-mapping>

通过多个<filter-mapping/>标签可以为一个过滤器配置多个过滤映射,当然也可以将多个映射一个到一个<filter-mapping/>标签中

  1. <filter-name/>指定某个过滤器的名字
  2. <url-pattern/>指定过滤器所拦截的资源路径URL,“/”表示所有的Web资源都需要途径该过滤器,“.xxx”表示拦截访问xxx后缀的资源的请求。
  3. <servlet-name/>指定过滤器所拦截的某个Servlet的名字。
  4. <dispatcher/>指定过滤器在拦截时所应用的调度模式,一共有五个可选配置:FORWARD, REQUEST, INCLUDE, ASYNC, ERROR。
    1. FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问的,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
    2. REQUEST:当用户直接通过普通路径访问资源时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。这是默认的模式。
    3. INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问的,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
    4. ERROR:如果目标资源是通过声明式的异常处理机制调用的,那么该过滤器将被调用。除此之外,过滤器不会被调用。
    5. SYNC:意味着过滤器将在从异步上下文AsyncContext的调用下应用。

在Servlet 3.0以及之后,支持在Filter实现类上直接使用@WebFilter注解的方式配置过滤器,降低了配置文件的复杂度。例如:

@WebFilter(urlPatterns = "/aa/*",servletNames = "Servlet2")

下面简单测试,如下有三个Servlet:

@WebServlet(name = "Servlet1", value = "/aa/Servlet1")
public class Servlet1 extends HttpServlet {@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {System.out.println("请求到达");response.setContentType("text/html;charset=utf-8");PrintWriter out = response.getWriter();out.println("Servlet1");}
}@WebServlet(name = "Servlet2", value = "/bb/Servlet2")
public class Servlet2 extends HttpServlet {@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {System.out.println("请求到达");response.setContentType("text/html;charset=utf-8");PrintWriter out = response.getWriter();out.println("Servlet2");}
}@WebServlet(name = "Servlet3", value = "/bb/Servlet3")
public class Servlet3 extends HttpServlet {@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {System.out.println("请求到达");response.setContentType("text/html;charset=utf-8");PrintWriter out = response.getWriter();out.println("Servlet3");}
}

如果我们采用上面的过滤器设置,那么在访问Servlet1和Servlet2的时候,将会经过过滤器,而访问Servlet3的时候则不会经过过滤器,控制台输出为:

如果我们注释掉chain.doFilter方法,即不放行,那么访问Servlet1和Servlet2的时候,页面上不会有任何输出,也不会输出控制台也不会输出“请求到达”字符串,因为请求被拦截了,而访问Servlet3的时候则可以正常访问:

3 Filter的执行顺序

上面的简单测试,我们可能会发现,在chain.doFilter之前的逻辑在请求到达指定的Servlet之前执行,chain.doFilter之后的逻辑则是在请求到达指定的Servlet并离开之后执行。

过滤器链的完整流程顺序是这样的:客户端发送http请求到Web服务器上,Web服务器对该请求URL找到对应负责的过滤器形成过滤器链,接着从第一个过滤器开始进行过滤操作,也就是调用Filter.doFilter方法,这个方法的逻辑是开发者编写的,当当前请求满足当前过滤器的要求或者是过滤操作完毕之后,应在调用chain.doFilter方法进行放行,该方法又会调用链中的下一个过滤器的doFilter方法继续过滤,如果当前过滤器是过滤器链的最后一个过滤器,那么chain.doFilter方法将会执行资源访问操作,访问完毕之后,将会依照最开始过滤器的调用顺序倒序的返回,接着执行chain.doFilter方法后面的代码。最终将响应结果交给Web服务器,Web服务器再将响应返回给客户端。

3.1 多个过滤器

当某个请求对应存在多个过滤器时,过滤器之间的执行顺序是通过在web.xml文件中某个Filter的首个<filter-mapping/>定义的先后顺序决定的。

如下,两个Filter:

public class Filter1 implements Filter {@Overridepublic void init(FilterConfig filterConfig) {System.out.println("Filter1-init");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("-----Filter1放行前-----");HttpServletRequest httpServletRequest= (HttpServletRequest) request;//获取当前请求的URLSystem.out.println(httpServletRequest.getRequestURL());//放行,调用下一个过滤器或者访问资源chain.doFilter(request, response);System.out.println("-----Filter1放行后-----");}@Overridepublic void destroy() {System.out.println("destroy");}
}public class Filter2 implements Filter {@Overridepublic void init(FilterConfig filterConfig) {System.out.println("Filter2-init");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("-----Filter2放行前-----");HttpServletRequest httpServletRequest= (HttpServletRequest) request;//获取当前请求的URLSystem.out.println(httpServletRequest.getRequestURL());//放行,调用下一个过滤器或者访问资源chain.doFilter(request, response);System.out.println("-----Filter2放行后-----");}@Overridepublic void destroy() {System.out.println("destroy");}
}

以下是映射配置:

<filter><filter-name>Filter1</filter-name><filter-class>com.example.filter.Filter1</filter-class>
</filter>
<filter><filter-name>Filter2</filter-name><filter-class>com.example.filter.Filter2</filter-class>
</filter><!--Filter2的mapping在前-->
<filter-mapping><filter-name>Filter2</filter-name><!--指定拦截指定的ServletName--><servlet-name>Servlet2</servlet-name>
</filter-mapping>
<filter-mapping><filter-name>Filter1</filter-name><!--指定拦截指定路径的资源URL--><url-pattern>/aa/*</url-pattern><!--指定拦截指定的ServletName--><servlet-name>Servlet2</servlet-name>
</filter-mapping>
<filter-mapping><filter-name>Filter2</filter-name><!--指定拦截指定路径的资源URL--><url-pattern>/aa/*</url-pattern>
</filter-mapping>

可以看到Filter2的mapping在前,因此Filter2将先被执行,但是在资源访问完毕返回时,则是倒序执行!

我们访问Servlet1和Servlet2,将会得到如下结果:

如果是通过注解的方式配置,就比较urlPatterns的字符串优先级。

4 Filter的应用

Filter的简单应用包括:

  1. 可以在Filter中根据条件决定是否调用chain.doFilter(request,response)方法,即是否让目标资源能够访问。
  2. 在访问目标资源之前,可以对request\response作预处理。
  3. 在目标资源访问之后,可以捕获目标资源的执行结果,从而实现一些特殊的功能。

4.1 脏话过滤器

脏话过滤器,将参数中的脏话替换为**。

/*** 脏话过滤器,拦截所有访问路径** @author lx*/
@WebFilter("/*")
public class DirtyWordsFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) {System.out.println("DirtyWordsFilter-init");}@Overridepublic void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException {HttpServletRequest request;HttpServletResponse response;try {request = (HttpServletRequest) req;response = (HttpServletResponse) resp;} catch (Exception e) {throw new RuntimeException("non-http request or response");}//传递一个装饰类,该类的getParameter能够过滤某些脏话DWHttpServletRequest dwrequest = new DWHttpServletRequest(request);chain.doFilter(dwrequest, response);}@Overridepublic void destroy() {System.out.println("destroy");}
}/*** 装饰类,接收一个request对象*/
class DWHttpServletRequest extends HttpServletRequestWrapper {/*** 脏话词典*/private String[] strs = {"坤坤", "凡凡", "禽兽", "畜生", "傻B"};public DWHttpServletRequest(HttpServletRequest request) {super(request);}/*** 增强了getParameter方法* <p>* 将参数中的脏话替换为**才返回*/@Overridepublic String getParameter(String name) {String value = super.getParameter(name);if (value == null) {return value;}for (String s : strs) {//将脏话替换为**才返回value = value.replace(s, "**");}return value;}
}

测试Servlet:

@WebServlet("/DirtyWordsServlet")
public class DirtyWordsServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {String name = req.getParameter("name");resp.setContentType("text/html;charset=utf-8");PrintWriter out = resp.getWriter();out.println("<h1>" + name + "</h1>");}
}

尝试请求http://localhost:8081/filter/DirtyWordsServlet?name=坤坤,返回结果如下:

4.2 编码过滤器

我们前面说过,tomcat8以下的版本默认对于URL采用iso-8859-1解码,那么get请求参数具有中文等特殊字符时,获取参数值的时候需要进行转码,并且在对于post请求的参数也需要通过setCharacterEncoding设置编码,非常麻烦。

现在有了Filter过滤器,我们可以使用一个Filter解决全部的get请求的乱码问题,这里涉及到动态代理的应用(tomcat8及其以上不适用,因为tomcat8默认对于URL采用utf-8解码,可以直接获取正常的参数值)。

同时,还能统一设置Post请求编码,以及响应编码,有了这个过滤器,就不必在各个Servlet中设置请求编码或者响应编码了。

Spring MVC中的CharacterEncodingFilter就是一个编码过滤器的实现!

@WebFilter("/*")
public class EncodingFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) {System.out.println("EncodingFilter-init");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {//将request和response强转成http协议的HttpServletRequest req = (HttpServletRequest) request;HttpServletResponse resp = (HttpServletResponse) response;/** 通用编码设置*///解决post请求提交参数的乱码问题req.setCharacterEncoding("UTF-8");//统一设置响应编码resp.setContentType("text/html;charset=UTF-8");//使用JDK的动态代理,动态的增强req对象的getParameter(name)方法//解决tomcat8一下的版本的get请求url乱码的问题(tomcat8之后的版本不需要了)HttpServletRequest myReq = (HttpServletRequest) Proxy.newProxyInstance(HttpServletRequest.class.getClassLoader(), new Class[]{HttpServletRequest.class}, (proxy, method, args) -> {Object obj;//如果是getParameter方法被调用if ("getParameter".equalsIgnoreCase(method.getName())) {//获取本次的请求方法String md = req.getMethod();//解决get请求提交参数的乱码问题,动态增强if ("get".equalsIgnoreCase(md)) {//调用目标对象的getParameter方法String v = (String) method.invoke(req, args);//对获取到的结果进行转码(tomcat8之后的版本不需要了)return new String(v.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);}//其他请求obj = method.invoke(req, args);}//如果是其他方法被调用,那么直接通过目标对象调用else {obj = method.invoke(req, args);}return obj;});//将代理对象放行chain.doFilter(myReq, response);}@Overridepublic void destroy() {System.out.println("destroy");}
}

4.3 统计IP访问次数

IP工具类:

/*** @author lx*/
public class IpUtil {/*** 获取用户真实IP地址** @param request 请求* @return ip*/public static String getIpAddr(HttpServletRequest request) {String ip = request.getHeader("x-forwarded-for");System.out.println("x-forwarded-for ip: " + ip);if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {// 多次反向代理后会有多个ip值,第一个ip才是真实ipif (ip.contains(",")) {ip = ip.split(",")[0];}}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP");System.out.println("Proxy-Client-IP ip: " + ip);}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");System.out.println("WL-Proxy-Client-IP ip: " + ip);}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("HTTP_CLIENT_IP");System.out.println("HTTP_CLIENT_IP ip: " + ip);}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("HTTP_X_FORWARDED_FOR");System.out.println("HTTP_X_FORWARDED_FOR ip: " + ip);}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("X-Real-IP");System.out.println("X-Real-IP ip: " + ip);}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();System.out.println("getRemoteAddr ip: " + ip);}System.out.println("获取客户端ip: " + ip);return ip;}
}

IP统计过滤器:

/*** 根据ip统计访问次数** @author lx*/
@WebFilter("/*")
public class IPCountFilter implements Filter {private FilterConfig config;/*** 在init方法中初始化一个map集合,用于存放ip以及它们的访问次数,将map存入ServletContext域对象中* <p>* 这个方法只会调用一次*/@Overridepublic void init(FilterConfig config) {this.config = config;//准备一个map空集合:Map<String, Integer> map = new HashMap<>();//将map集合存放在ServletContext域对象当中:ServletContext context = config.getServletContext();//存进去:context.setAttribute("map", map);}@Overridepublic void doFilter(ServletRequest req,ServletResponse res, FilterChain chain)throws IOException, ServletException {/** 开发步骤:* 1:获得当前请求的ip地址:* 2:从一个map集合当中进行查询,*   如果查询不到,存1进去。*   如果查询到,将值+1后存进去。* 3:在页面上展示即可*///强制转换:HttpServletRequest request;HttpServletResponse response;try {request = (HttpServletRequest) req;response = (HttpServletResponse) res;} catch (ClassCastException e) {throw new ServletException("non-HTTP request or response");}//获取ip地址String ip = request.getRemoteAddr();//从context当中获得map集合:ServletContext context = config.getServletContext();Map<String, Integer> map = (Map<String, Integer>) context.getAttribute("map");//从map集合当中获得ip对应的值,并且记录访问次数Integer count = map.computeIfAbsent(ip, s -> 0);//将值存回map集合当中map.put(ip, ++count);//map集合存回ServletContext当中:context.setAttribute("map", map);//放行chain.doFilter(request, response);}@Overridepublic void destroy() {}
}

IPCountServlet:

@WebServlet("/IPCountServlet")
public class IPCountServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=utf-8");PrintWriter out = resp.getWriter();ServletContext servletContext = getServletContext();//从context当中获得map集合:Map<String, Integer> map = (Map<String, Integer>) servletContext.getAttribute("map");for (Map.Entry<String, Integer> stringIntegerEntry : map.entrySet()) {out.println("IP: " + stringIntegerEntry.getKey() + "的访问次数为: " + stringIntegerEntry.getValue());}}
}

注意,如果是localhost,那么可能将获取0:0:0:0:0:0:0:1的IPV6的形式地址,对应ipv4来说相当于127.0.0.1,也就是本机。

4.4 禁止动态资源缓存的过滤器

假设动态资源访问路径为“/Servlet”和“.JSP”。Servlet、JSP等动态资源不应该被浏览器缓存,因为响应结果随时可能改变。

@WebFilter(urlPatterns = {"/servlet/*", "*.jsp"})
public class NocacheFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) {System.out.println("NocacheFilter-init");}@Overridepublic void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException {//强制转换: HttpServletRequest request;HttpServletResponse response;try {request = (HttpServletRequest) req;response = (HttpServletResponse) resp;} catch (ClassCastException e) {throw new ServletException("non-HTTP request or response");}//设置动态资源的过期时间和浏览器不缓存response.setHeader("Expires", "-1");response.setHeader("Cache-Control", "no-cache");response.setHeader("Pragma", "no-cache");//放行:chain.doFilter(request, response);}@Overridepublic void destroy() {System.out.println("destroy");}
}

4.5 html标记过滤器

@WebFilter("/*")
public class HTMLFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) {System.out.println("HTMLFilter-init");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {//增强对象HTMLHttpServlet htmlHttpServlet = new HTMLHttpServlet((HttpServletRequest) request);//放行chain.doFilter(htmlHttpServlet, response);}@Overridepublic void destroy() {System.out.println("destroy");}
}/*** html标记过滤器,增强类*/
class HTMLHttpServlet extends HttpServletRequestWrapper {/*** Constructs a request object wrapping the given request.** @param request the {@link HttpServletRequest} to be wrapped.* @throws IllegalArgumentException if the request is null*/public HTMLHttpServlet(HttpServletRequest request) {super(request);}/*** 增强getParameter方法*/@Overridepublic String getParameter(String name) {String value = super.getParameter(name);return filter(value);}/*** tomcat 当中webapps/examples项目下的/WEB-INF/classes/utils下的工具类* <p>* Filter the specified message string for characters that are sensitive* in HTML.  This avoids potential attacks caused by including JavaScript* codes in the request URL that is often reported in error messages.** @param message The message string to be filtered* @return the filtered version of the message*/public static String filter(String message) {if (message == null)return null;char content[] = new char[message.length()];message.getChars(0, message.length(), content, 0);StringBuilder result = new StringBuilder(content.length + 50);for (char c : content) {switch (c) {case '<':result.append("&lt;");break;case '>':result.append("&gt;");break;case '&':result.append("&amp;");break;case '"':result.append("&quot;");break;default:result.append(c);}}return result.toString();}
}

如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!

Java Servlet中Filter过滤器的原理以及使用方式相关推荐

  1. java中servlet filter_lua学习笔记(二)仿java servlet中Filter功能

    2)代码 Filter.lua--[[ 过滤器接口 ]]-- local FilterChain = require("FilterChain") local Filter = { ...

  2. 关于Servlet中filter过滤器的小问题

    刚进入filter的学习,一开始认为这东西也就不过如此了. 但是,我必须得承认,我错了! 刚开始学的时候,老师让我们自己做一个小程序. 就是:输入一串字符,点击发送,在另一个窗口显示.要求是把字符串中 ...

  3. java 过滤器 中文_java中Filter过滤器解决中文乱码办法

    java中Filter过滤器解决中文乱码办法 发布时间:2020-04-07 10:19:09 来源:亿速云 阅读:16 作者:小新 这篇文章主要为大家详细介绍了java中Filter过滤器解决中文乱 ...

  4. Filter过滤器工作原理

    Filter过滤器工作原理 Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术之一,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Js ...

  5. Java开发中Netty线程模型原理解析!

    Java开发中Netty线程模型原理解析,Netty是Java领域有名的开源网络库具有高性能和高扩展性的特点,很多流行的框架都是基于它来构建.Netty 线程模型不是一成不变的,取决于用户的启动参数配 ...

  6. java serlet清空cookie_如何删除Java Servlet中的Cookie

    如何删除Java servlet中的cookie? 编辑:以下现在工作成功,似乎是以下的组合: response.setContentType("text/html"); 和 co ...

  7. Java Servlet 中的 ServletConfig 和 ServletContext 之间的区别

    ServletConfig 和 ServletContext 是 Java Servlet 中的两个重要接口,它们都是用来存储 servlet 的配置信息的. ServletConfig 是针对单个 ...

  8. 【Servlet】Filter过滤器详解、使用示例

    Filter过滤器讲解 定义 过滤器处于浏览器与servlet之间,是一个实现了 javax.servlet.Filter 接口的 Java 类 客户端发送的请求.服务器发送的资源,需要通过过滤器,才 ...

  9. java后端通过Filter过滤器解决跨域问题

    此方案只需服务端的代码修改 因为现在要前后端分离开发,那必不可免的会出现跨域问题,以下是自己实际测试过的有效代码: 步骤: 一.在 web.xml文件中添加 <!-- 2019-01-15 解决 ...

最新文章

  1. Spring框架之(无参、有参)构造方法与setter方法的初始化
  2. 图灵奖得主Bengio明星创业公司被「贱卖」| AI日报
  3. WF4B1 的有返回值的Activity,Bookmark,有返回值Bookmark
  4. 浅谈主流内存发展历史
  5. 练习7-11 字符串逆序 (15分)
  6. linux基础命令怎么记,linux基础命令--笔记(示例代码)
  7. Python实战从入门到精通第十七讲——将单方法的类转换为函数
  8. 从总数中生成一定数量的随机数
  9. NYOJ65 - 另一种阶乘问题
  10. 成为Oracle 10g DBA之路
  11. 【200个】电子病历系统(EMR)精华资料汇总【HC3i年终盘点】
  12. verilog 3段式状态机
  13. 网页顶部广告展开与收起
  14. 独角兽云发卡系统源码下载
  15. 异步方法中取消异步操作
  16. chromecast 断电重启后时间错误
  17. Android远程桌面助手(B1309)
  18. fstream、ifstream、ofstream
  19. CoinGeek直播大会(2020)将在著名的纽约曼哈顿中心举行
  20. JavaScript中基本数据类型的强制转换

热门文章

  1. PHP Twitter 推特 第三方登录
  2. 关于论文分两栏的问题
  3. Mysql——存储引擎
  4. LibROSA库提取MFCC特征的过程解析
  5. linux6查看光纤网卡wwn,怎样查看Redhat Linux的光纤卡WWN
  6. vincent的歌词
  7. openstack私有云布署实践【16.1 CentOS7.1 只有根分区镜像制作】
  8. 大学计算机一级网络题,大学计算机一级考试试题选择题
  9. ASCII码表和转义字符表
  10. 读取豆瓣图书API并下载封面图片的Qt程序