Java Servlet中Filter过滤器的原理以及使用方式
详细介绍了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服务器,进而响应给客户端。
过滤器可以做很多事情,常见的包括:
- 过滤脏敏感字符(绿一些敏感的字符串);
- 避免中文乱码(统一设置请求和响应的编码);
- 权限验证(规定只有带指定Session或Cookie的请求,才能访问资源);
- 用于实现自动登录;
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 过滤器的生命周期
诞生
:过滤器的实例是在web应用被加载时就完成的实例化,并调用init方法初始化的。servlet 容器在实例化Filter后只调用init
方法一次。在要求过滤器执行任何过滤工作之前,init 方法必须成功完成。区别于Servlet,过滤器会全部立即初始化。- 每个过滤器在init初始化方法都会传递一个 FilterConfig 对象,从该对象可以获取其初始化参数。并可通过FilterConfig获取 ServletContext对象,比如可以使用该对象加载筛选任务所需的资源。
存活
:和应用的生命周期一致的。在内存中是单例的。针对拦截范围内的资源,每次访问都会调用void doFIlter(request,response.chain)进行拦截。死亡
:应用被卸载时,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/>
标签中
<filter-name/>
指定某个过滤器的名字<url-pattern/>
指定过滤器所拦截的资源路径URL,“/”表示所有的Web资源都需要途径该过滤器,“.xxx”表示拦截访问xxx后缀的资源的请求。<servlet-name/>
指定过滤器所拦截的某个Servlet的名字。<dispatcher/>
指定过滤器在拦截时所应用的调度模式,一共有五个可选配置:FORWARD, REQUEST, INCLUDE, ASYNC, ERROR。FORWARD
:如果目标资源是通过RequestDispatcher的forward()方法访问的,那么该过滤器将被调用,除此之外,该过滤器不会被调用。REQUEST
:当用户直接通过普通路径访问资源时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。这是默认的模式。INCLUDE
:如果目标资源是通过RequestDispatcher的include()方法访问的,那么该过滤器将被调用,除此之外,该过滤器不会被调用。ERROR
:如果目标资源是通过声明式的异常处理机制调用的,那么该过滤器将被调用。除此之外,过滤器不会被调用。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的简单应用包括:
- 可以在Filter中根据条件决定是否调用
chain.doFilter(request,response)
方法,即是否让目标资源能够访问。 - 在访问目标资源之前,可以对request\response作预处理。
- 在目标资源访问之后,可以捕获目标资源的执行结果,从而实现一些特殊的功能。
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("<");break;case '>':result.append(">");break;case '&':result.append("&");break;case '"':result.append(""");break;default:result.append(c);}}return result.toString();}
}
如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!
Java Servlet中Filter过滤器的原理以及使用方式相关推荐
- java中servlet filter_lua学习笔记(二)仿java servlet中Filter功能
2)代码 Filter.lua--[[ 过滤器接口 ]]-- local FilterChain = require("FilterChain") local Filter = { ...
- 关于Servlet中filter过滤器的小问题
刚进入filter的学习,一开始认为这东西也就不过如此了. 但是,我必须得承认,我错了! 刚开始学的时候,老师让我们自己做一个小程序. 就是:输入一串字符,点击发送,在另一个窗口显示.要求是把字符串中 ...
- java 过滤器 中文_java中Filter过滤器解决中文乱码办法
java中Filter过滤器解决中文乱码办法 发布时间:2020-04-07 10:19:09 来源:亿速云 阅读:16 作者:小新 这篇文章主要为大家详细介绍了java中Filter过滤器解决中文乱 ...
- Filter过滤器工作原理
Filter过滤器工作原理 Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术之一,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Js ...
- Java开发中Netty线程模型原理解析!
Java开发中Netty线程模型原理解析,Netty是Java领域有名的开源网络库具有高性能和高扩展性的特点,很多流行的框架都是基于它来构建.Netty 线程模型不是一成不变的,取决于用户的启动参数配 ...
- java serlet清空cookie_如何删除Java Servlet中的Cookie
如何删除Java servlet中的cookie? 编辑:以下现在工作成功,似乎是以下的组合: response.setContentType("text/html"); 和 co ...
- Java Servlet 中的 ServletConfig 和 ServletContext 之间的区别
ServletConfig 和 ServletContext 是 Java Servlet 中的两个重要接口,它们都是用来存储 servlet 的配置信息的. ServletConfig 是针对单个 ...
- 【Servlet】Filter过滤器详解、使用示例
Filter过滤器讲解 定义 过滤器处于浏览器与servlet之间,是一个实现了 javax.servlet.Filter 接口的 Java 类 客户端发送的请求.服务器发送的资源,需要通过过滤器,才 ...
- java后端通过Filter过滤器解决跨域问题
此方案只需服务端的代码修改 因为现在要前后端分离开发,那必不可免的会出现跨域问题,以下是自己实际测试过的有效代码: 步骤: 一.在 web.xml文件中添加 <!-- 2019-01-15 解决 ...
最新文章
- Spring框架之(无参、有参)构造方法与setter方法的初始化
- 图灵奖得主Bengio明星创业公司被「贱卖」| AI日报
- WF4B1 的有返回值的Activity,Bookmark,有返回值Bookmark
- 浅谈主流内存发展历史
- 练习7-11 字符串逆序 (15分)
- linux基础命令怎么记,linux基础命令--笔记(示例代码)
- Python实战从入门到精通第十七讲——将单方法的类转换为函数
- 从总数中生成一定数量的随机数
- NYOJ65 - 另一种阶乘问题
- 成为Oracle 10g DBA之路
- 【200个】电子病历系统(EMR)精华资料汇总【HC3i年终盘点】
- verilog 3段式状态机
- 网页顶部广告展开与收起
- 独角兽云发卡系统源码下载
- 异步方法中取消异步操作
- chromecast 断电重启后时间错误
- Android远程桌面助手(B1309)
- fstream、ifstream、ofstream
- CoinGeek直播大会(2020)将在著名的纽约曼哈顿中心举行
- JavaScript中基本数据类型的强制转换