文章目录
- JavaWeb - 04
- 一、Filter
- 1. 概述
- 2. 实现步骤
- 3. 运行结果
- 二、Filter 应用:实现权限拦截
- 1. 登录步骤
- 2. 添加的过滤器部分
- 3. 运行结果
- 4. 总结
- 三、监听器
- 注意:
JavaWeb - 04
一、Filter
1. 概述
Filter:过滤器,可以用来过滤网站的数据,例如:处理中文乱码、登陆验证等。
注意:
- 在 Web 浏览器传入的请求中可能有一些垃圾请求,此时可以用 Filter 过滤器用来过滤网站的数据;
- Filter 过滤器可以应用在客户端和 Servlet 之间、Servlet 和 Servlet/JSP 之间,并且可以通过配置信息,灵活使用过滤器;
- 必须要让过滤器继续前行,链调用
doFilter
方法:filterChain.doFilter(servletRequest, servletResponse);
。
2. 实现步骤
实现 Filter 过滤器的步骤有三步:导入依赖、编写过滤器、在 web.xml
中进行配置。
测试:编写一个处理中文乱码的过滤器,对过滤前后的输出进行对比。
-
创建一个普通 Maven 项目(不创建模块了),然后转换为 Web 项目(右键项目,选择
Add Framework Support...
) -
在
pom.xml
中添加依赖
<!-- Servlet 依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!-- JSP 依赖 -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
</dependency>
<!-- JSTL 表达式依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- standard 标签库 -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!-- mysql 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
- 编写过滤器,实现
Filter
接口(注意是:javax.servlet.Filter
),重写对应的方法
- 编写一个 Servlet,用来测试
- 在
web.xml
中进行配置,对过滤器Filter
的配置与普通 Servlet 的配置类似,只要是/filter/
都可以经过过滤
<!-- 用于对比 -->
<servlet>
<servlet-name>TestServlet</servlet-name>
<servlet-class>com.Sun3285.servlet.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>/filter/test</url-pattern>
</servlet-mapping>
<!-- 对过滤器的配置 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.Sun3285.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/filter/*</url-pattern>
</filter-mapping>
- 配置 Tomcat
3. 运行结果
通过运行结果还可以看到:
-
Web 服务器启动时,过滤器就已经初始化
init
了,随时等待过滤对象出现; -
Web 服务器关闭的时候,过滤销毁
destroy
。
二、Filter 应用:实现权限拦截
举例:实现用户登录,用户登陆后才能进入主页,用户注销后就不能进入主页。
思路:
- 用户登录之后,向 Session 中存放用户的数据,相反,用户注销后,在 Session 中移除用户的数据;
- 可能会出现的问题:直接在地址栏中输入成功登录的 url,就可以直接访问成功登录的界面;
- 解决上述问题:使用过滤器:在登录之后,跳转成功页面之前走这个过滤器,判断是否有登录的这个过程,如果进行了登录,并且信息正确(此时 Session 中存放了用户的数据),就可以访问成功页面;如果直接在地址栏中输入成功登录的 url(Session 中没有用户的数据),没有权限进入。
1. 登录步骤
- 三个 JSP 页面:登录页面、登录成功页面、登录失败页面
<%-- login.jsp:登录页面 --%>
<h1>登录</h1>
<form action="${pageContext.request.contextPath}/servlet/login" method="post">
用户名:<input type="text" name="username"> <br>
密码:<input type="password" name="password"> <br>
<input type="submit">
</form>
<%-- success.jsp:登录成功页面 --%>
<h1>登录成功,这是主页</h1>
<h2>
<a href="${pageContext.request.contextPath}/servlet/logout">注销</a>
</h2>
<%-- error.jsp:登录失败页面 --%>
<h1>登录失败</h1>
<h2>用户名或密码错误,也可能没有权限</h2>
<h3>
<a href="${pageContext.request.contextPath}/servlet/logout">返回重新登录</a>
</h3>
注意:
form
是表单、href
是超链接、${pageContext.request.contextPath}
表示当前项目路径。
- 登录:
LoginServlet.java
- 注销(退出登录):
LogoutServlet.java
web.xml
配置
<!-- 登录配置 -->
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.Sun3285.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.Sun3285.servlet.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/servlet/logout</url-pattern>
</servlet-mapping>
2. 添加的过滤器部分
为了解决用户直接在地址栏中输入成功登录的 url 就可以进入主页的问题,在登录之后,跳转成功页面之前走过滤器。
- 过滤器:
LoginFilter.java
web.xml
可以配置使用过滤器的时间:只要路径经过sys
,过滤器就会发生作用,进行过滤
<!-- 过滤器 -->
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>com.Sun3285.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/sys/*</url-pattern>
</filter-mapping>
3. 运行结果
- 用户名或密码错误时,跳转到登录错误页面;用户名或密码正确时,跳转到成功页面
- 当用户不登陆,直接输入成功页面的 url 时,会通过过滤器过滤,跳转到登录错误页面
4. 总结
- 不同的代码放入不同的包中,如可以分为
filter
、servlet
、utils
包等,然后分别编写对应的代码; - 在编写过滤器时,需要注意,参数类型为
ServletRequest
,此时需要强制转换为它的子类HttpServletRequest
,因为现在的 request 不能得到 Session; - 过滤时需要加一层,将需要经过过滤的代码或页面放入这一层中,通过
web.xml
配置可以保证这一层的代码或页面都会经过过滤,而其他代码或页面不会受影响。如这里加了sys
这一层,所有经过sys
的才都会经过过滤,其他页面不受影响; - 项目名是在配置 Tomcat 时设置的,对应了
web
文件夹; - 可以把经常使用的变量或常量单独放在一个类中,使用时通过类来调用,这样在修改时,只需要修改一次即可,如这里的常量
USER_SESSION
单独放在了Constant
类中,使用时通过类直接调用; - 通过过滤器的执行过程:先通过过滤器,过滤后放行
chain.doFilter(req, resp)
,执行 Servlet 或 JSP 后,返回时会再次通过过滤器,此时会从chain.doFilter(req, resp)
后开始执行,如果没有代码则不执行; - 出现重定向次数过多的原因:由于设置或代码问题,导致重定向循环;
- 路径问题:
- 重定向时:路径从项目名开始,即带有项目名的 url 路径;
- 请求转发时:路径是不带有项目名的 url 路径;
- JSP 页面时:路径是带有项目名的 url 路径,获取当前项目路径为:
${pageContext.request.contextPath}
;
注意:这里的 url 路径,既可以是在
web.xml
配置好的路径,也可以是 JSP 页面所在位置的路径,项目名对应了web
文件夹。
三、监听器
步骤:编写监听器、在 web.xml
中进行配置
- 编写监听器,实现接口(接口有很多),重写方法
// 举例
public class OnlineCountListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent httpSessionEvent) {}
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {}
}
- 在
web.xml
中进行配置
<!-- 注册监听器 -->
<listener>
<listener-class>com.Sun3285.listener.OnlineCountListener</listener-class>
</listener>
注意:
- int 类型的数据不能赋值为 null,Integer 类型的数据为引用类型,可以为 null。Integer 类型的数据转换为 int 类型,可以对象调用
intValue
方法。 - 每一个请求都对应一个 servlet,每一个 servlet 都需要进行配置。