Filter (Servlet过滤器)
Filter (Servlet过滤器)
Filter:是Servlet2.3新增的一个特性,同时它也是Servlet技术中最实用的技术。开发人员可以通过Filter技术,能够实现对所有Web资源的管理,如实现权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
-
Filter 过滤器它是 JavaWeb 的三大组件之一。三大组件分别是Servlet 程序、Listener 监听器、Filter 过滤器。
-
Filter 过滤器它是 JavaEE 的规范,也就是一个接口。
-
Filter 过滤器它的作用是:
拦截请求和过滤响应。拦截请求常见的应用场景有权限检查、日记操作、事务管理等等。例如:登录验证,统一编码处理,敏感字符过滤~~
Servlet需要拿到response和request两个对象,Filter同样需要拿到response和request对象才能进行过滤处理,所以过滤器和Servlet类似,只是Servlet实现HttpServlet接口,过滤器实现Filter接口,注意有很多Filter的接口,实现Maven导的servlet的包的Filter接口
Servlet 的 Filter 特点:
- 声明式的
通过在 web.xml 配置文件中声明,允许添加、删除过滤器,而无须改动任何应用程序代码或 JSP 页面。 - 灵活的
过滤器可用于客户端的直接调用执行预处理和后期的处理工作,通过过滤链可以实现一些灵活的功能。 - 可移植的
由于现今各个 Web 容器都是以 Servlet 的规范进行设计的,因此 Servlet 过滤器同样是跨容器的。 - 可重用的
基于其可移植性和声明式的配置方式,Filter 是可重用的。
总的来说,Servlet 的过滤器是通过一个配置文件来灵活的声明的模块化可重用组件。过滤器动态的截获传入的请求和传出的响应,在不修改程序代码的情况下,透明的添加或删除他们。其独立于任何平台和 Web 容器。
核心方法:
返回值 | 方法名 | 作用 |
---|---|---|
void | init(FilterConfig config) | 初始化方法 |
void | doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | 对请求资源和响应资源进行拦截 |
void | destroy() | 销毁方法 |
Filter开发步骤:
-
导包
-
编写过滤器
例子:处理乱码的过滤器
public class CharacterEncodingFilter implements Filter { //初始化:web服务器启动的时候,就已经执行了初始化,随时等待过滤对象出现 @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("CharacterEncodingFilter初始化"); } //对请求资源和响应资源进行拦截 @Override //chain:链 /* * 1. 过滤中的所有代码,在过滤特定请求的时候都会执行 * 2. 必须要让过滤器继续执行,所以必须要写 * filterChain.doFilter(servletRequest,servletResponse); * */ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { servletRequest.setCharacterEncoding("utf-8"); servletResponse.setCharacterEncoding("utf-8"); servletResponse.setContentType("text/html;charset=UTF-8"); System.out.println("CharacterEncodingFilter执行前..."); filterChain.doFilter(servletRequest,servletResponse);//让我们的请求继续走,如果不写程序就会在在这里被拦截停止 System.out.println("CharacterEncodingFilter执行后"); } //销毁:服务器关闭时,过滤器会销毁 @Override public void destroy() { System.out.println("CharacterEncodingFilter销毁"); } }
-
在web.xml中配置过滤器
<filter> <filter-name>characterEncodingFiter</filter-name> <filter-class>com.yue.filter.CharacterEncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>characterEncodingFiter</filter-name> <!--servlet/下的任何请求都会经过这个过滤器--> <url-pattern>/servlet/*</url-pattern> </filter-mapping>
可以写一个会出现乱码的Servlet进行测试:
public class ShowServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("你好,世界");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
在web.xml中配置Servlet,配置两个请求路线,以用来测试过滤器的效果
<servlet>
<servlet-name>showServlet</servlet-name>
<servlet-class>com.yue.servlet.ShowServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>showServlet</servlet-name>
<url-pattern>/show</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>showServlet</servlet-name>
<url-pattern>/servlet/show</url-pattern>
</servlet-mapping>
由于上面的过滤器过滤的是servlet/下的任何请求,所以路径为/servlet/show的页面正常显示"你好,世界"的中文,而路径为/show的页面则会出现乱码
过滤器的常见应用:
例:用户登录后才能进入主页
有些页面需要用户登录才可以查看,如果不设置过滤器,则客户端可直接访问域名进入特定页面,故需要过滤器来筛选登录的客户端
-
创建一个util包,定义一个Constant类,用来定义一些常量,方便实用,这里只定义一个USER_SESSION,要在登录的session中添加这个属性
public class Constant { public final static String USER_SESSION = "USER_SESSION";//定义一个唯一的常量USER_SESSION }
-
自定义一个登录的servlet:LoginServlet
public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取前端请求的参数 String username = req.getParameter("username"); if (username.equals("admin")){//当输入为admin时就登陆成功,其他的就登录失败 req.getSession().setAttribute(Constant.USER_SESSION,req.getSession().getId());//在session中添加一个属性USER_SESSION,在Constant设置这个常量,方便日后维护 resp.sendRedirect(req.getContextPath()+"/sys/success.jsp");//因为有项目名所以写成:req.getContextPath()+"路径",等同于:"项目名/路径" }else {//登录失败 resp.sendRedirect(req.getContextPath()+"/error.jsp"); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
-
自定义一个注销登录的servlet:LogoutServlet
public class LogoutServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Object user_session = req.getSession().getAttribute(Constant.USER_SESSION); if (user_session!=null){ req.getSession().removeAttribute(Constant.USER_SESSION);//删除session中的USER_SESSION的属性,不必删除session,避免多次创建session resp.sendRedirect(req.getContextPath()+"/login.jsp"); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
-
在web.xml中注册LoginServlet和LogoutServlet:
<servlet> <servlet-name>loginServlet</servlet-name> <servlet-class>com.yue.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>loginServlet</servlet-name> <url-pattern>/servlet/login</url-pattern> </servlet-mapping> <servlet> <servlet-name>logoutServlet</servlet-name> <servlet-class>com.yue.servlet.LogoutServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>logoutServlet</servlet-name> <url-pattern>/servlet/logout</url-pattern> </servlet-mapping>
-
自定义一个登录的jsp页面:login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>登陆</h1> <form action="${pageContext.request.contextPath}/servlet/login" method="post"> <input type="text" name="username"> <input type="submit"> </form> </body> </html>
-
自定义一个登录失败的jsp页面:error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>错误</h1> <h4>用户名错误</h4> <h4>没有权限</h4> <a href="${pageContext.request.contextPath}/login.jsp">返回登录页面</a> </body> </html>
-
在web包下新建一个sys包,并在里面自定义一个登陆成功的jsp页面success.jsp,并设置注销按钮,注销后跳转到error.jsp页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>主页</h1> <p><a href="/javaweb_filter/servlet/logout">注销</a></p> </body> </html>
-
自定义一个只能让登录用户访问success.jsp页面的过滤器SysFilter,未登录用户则重定向至error.jsp页面
public class SysFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException { //ServletRequest是HttpServletRequest的父类,可以强转 HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; if (request.getSession().getAttribute(Constant.USER_SESSION)==null){//如果session中的USER_SESSION属性为空,则重定向至错误页面 response.sendRedirect(((HttpServletRequest) req).getContextPath()+"/error.jsp"); } filterChain.doFilter(req,resp); } @Override public void destroy() { } }
-
在web.xml中注册过滤器SysFilter,确保sys下的所有页面都需要权限。
<filter> <filter-name>sysFilter</filter-name> <filter-class>com.yue.filter.SysFilter</filter-class> </filter> <filter-mapping> <filter-name>sysFilter</filter-name> <url-pattern>/sys/*</url-pattern> </filter-mapping>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!