JSP ---[过滤器]
Posted 小智RE0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JSP ---[过滤器]相关的知识,希望对你有一定的参考价值。
过滤器
过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息。
- 过滤器位于客户端和web应用程序之间,用于检查和修改两者之间流过的请求.
- 在客户端的请求访问后端资源之前,拦截某些请求。(
在请求到达Servlet/JSP之前
) - 在服务器的响应发送回客户端之前,处理这些响应。
- 过滤器用来实现通用的功能,
减少代码冗余
,提高可维护性 - 一个过滤器可以配置给多个资源使用
一个资源可以配置多个过滤器,按照配置顺序调用
- 可以将一个或多个过滤器附加到一个 Servlet 或一组 Servlet。过滤器也可以附加到 JavaServer Pages (JSP) 文件和 html 页面。
- 过滤器是可用于 Servlet 编程的 Java 类
相关API接口
Filter ; FilterChain ; FilterConfig
Filter 接口
过滤器是一个实现了 javax.servlet.Filter 接口的 Java 类。javax.servlet.Filter 接口定义了三个方法:
public void init(FilterConfig filterConfig)
该方法对filter对象进行初始化,仅在容器初始化filter对象结束后被调用一次。参数FilterConfig可以获得filter的初始化参数。
web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。
public void doFilter (ServletRequest, ServletResponse, FilterChain)
该方法是filter进行过滤操作的方法。当客户端的请求与过滤器设置的 URL 匹配时,Servlet 先调用过滤器的 doFilter 方法。方法体中可以对request和response进行预处理。其中FilterChain可以将处理后的request和response对象传递到过滤链上的下一个资源。
public void destroy( )
该方法在容器销毁过滤器对象前被调用;在该方法中释放Servlet过滤器占用的资源。
FilterChain接口
FilterChain接口类型作为Filter接口中doFilter方法的参数使用
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse)
将当前的请求和响应传递到当前过滤链上的下一个资源,可能是下一个过滤器,可能是目标资源。
FilterConfig接口
FilterConfig接口类型作为Filter接口中的init方法的参数使用
public String getInitParameter(String s),
获得过滤器的初始化参数值 ;在web.xml中,可以为每一个filter配置需要的初始化参数,与Servlet的类似。过滤器的初始化参数即可通过FilterConfig中的getInitParameter方法获取。如果指定名称的初始化参数不存在,则返回 null
public String getFilterName( )
用于返回在 web.xml 文件中为 Filter 所设置的名称,即返回 <filter-name> 元素的设置值
public ServletContext getServletContext( )
返回 FilterConfig 对象中所包装的 ServletContext 对象的引用
public Enumeration
<String>
getInitParameterNames( )
返回一个 Enumeration 集合对象,该集合对象包含在 web.xml 文件中为当前 Filter 设置的所有初始化参数的名称
案例
(1)在过滤器中为所有servlet配置公用的编码规则处理
注意导包时用的是import javax.servlet.*
;
注意在原有项目包的基础上建立一个存放过滤类的工具包;例如名为filter
的包
编写EncodingFilter过滤类,实现 Filter接口
public class EncodingFilter implements Filter {
//初始化方法;不写时默认调用接口方法;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化方法");
}
//当客户端的请求与过滤器设置的 URL 匹配时,Servlet 先调用过滤器的 doFilter 方法。
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤处理方法");
//设置字符编码过滤;
servletRequest.setCharacterEncoding("utf-8");
//使得请求继续向下执行;到达过滤链的下一个资源;
filterChain.doFilter(servletRequest,servletResponse);
}
//销毁过滤器对象方法;不写时默认调用接口方法;
@Override
public void destroy() {
System.out.println("释放资源方法");
}
}
配置web.xml文件
;在过滤器映射中可以直接用<url-pattern>/*</url-pattern>
,将过滤器作用于当前的项目所有url地址.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--配置字符编码过滤器-->
<filter>
<!--filter-name:过滤器名称-->
<filter-name>aboutEncodingFilter</filter-name>
<!--filter-class:过滤器在当前项目的路径-->
<filter-class>com.xiaozhi.filter.EncodingFilter</filter-class>
</filter>
<!--过滤器的映射-->
<filter-mapping>
<!--需要映射的过滤器名称-->
<filter-name>aboutEncodingFilter</filter-name>
<!--<url-pattern>:设置过滤器的作用地址;匹配对应url地址,有多个地址时可以写多个 -->
<!-- <url-pattern>/login.jsp</url-pattern>-->
<!--或者直接写 /* 匹配当前项目所有的地址-->
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--配置默认首选加载页-->
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
</web-app>
LoginServlet文件
//使用注解方式配置servlet
@WebServlet(name = "login",urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取到session对象; 直接调用强制销毁会话的方法;
req.getSession().invalidate();
//重定向到登录页面;
resp.sendRedirect("login.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取页面中对应name的值;
String account = req.getParameter("account");
String password = req.getParameter("password");
//是否记住密码的标记;
String rememberPW = req.getParameter("RememberPW");
//创建session对象;
HttpSession session;
//这里仅仅是用equals方法进行了判断;
if (account.equals("xiaozhi") && password.equals("123456")) {
//当拿到的标记不为空时;创建cookie对象封装数据;
if(rememberPW!=null){
Cookie name=new Cookie("name",account);
Cookie pw=new Cookie("password",password);
//设置Cookie的有效期(以秒为单位)
name.setMaxAge(365*24*3600);
pw.setMaxAge(365*24*3600);
//在响应时将cookie对象传到客户端;
resp.addCookie(name);
resp.addCookie(pw);
}
//从请求对象中获取对应的session对象;
session = req.getSession();
//将上面获取到的account的值设置给名为 name的属性;(以键值对的形式);
session.setAttribute("name",account);
//若符合条件,则重定向到页面LoginSuccess.jsp;
resp.sendRedirect("loginSuccess.jsp");
} else {
//从请求对象中获取对应的session对象;
session=req.getSession();
//设置属性名为 errorMsg 的值为 "账号或密码错误!"
session.setAttribute("errorMsg", "账号或密码错误!");
//将页面重定向到login.jsp;
resp.sendRedirect("login.jsp");
}
}
}
登录login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<%--在服务器端获取到cookie--%>
<%
//定义用户名和密码两个变量;
String name = "";
String password = "";
//获取请求中的所有cookie;
Cookie[] cookies = request.getCookies();
//对获取的cookie判空;避免出现空指针异常;
if (cookies != null) {
//遍历获取到的cookie数组;
for(Cookie ck:cookies){
//得到对应name的cookie后;取到对应的值;
if(ck.getName().equals("name")){
name=ck.getValue();
}
if(ck.getName().equals("password")){
password=ck.getValue();
}
}
}
%>
<div>
<%--获取到session对象中属性名为 errorMsg 的值 ;若不存在,则返回 null 值--%>
<%--此时获取到的session对象和客户端访问服务器的是同一个;(都在同一个浏览器)--%>
<%
String errorMsg =(String) session.getAttribute("errorMsg");
out.print(errorMsg+"<br/>");
%>
<%--这里直接在用户名和密码标签的value输入值;--%>
</div>
<form action="login" method="post">
账号:<input type="text" name="account" value="<%out.print(name);%>"/><br/>
密码:<input type="password" name="password" value="<%out.print(password);%>"/><br/>
<input type="submit" value="登录"/><br/>
记住密码:<input type="checkbox" name="RememberPW" value="RememberPW"/>
</form>
</body>
</html>
登陆成功loginSuccess.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录成功</title>
<script type="text/javascript">
function logout() {
var result = confirm("确定退出?");
//取到的result是布尔值;
if(result){
//使用replace方法获取一个url; 可用一个新页面取代当前页面。这里默认请求方式为 get;
location.replace("login");
}
}
</script>
</head>
<body>
<%--通过getAttribute方法获取到指定的参数名(name)对应的值;若不存在,则返回 null 值--%>
<%--此时获取到的session对象和客户端访问服务器的是同一个;(都在同一个浏览器)--%>
<%
String account = (String) session.getAttribute("name");
%>
<%
out.print("用户==> "+account+"你来了!"+"<br/>");
%>
<input type="button" value="安全退出的按钮" onclick="logout()"/><br/>
</body>
</html>
启动服务器;初始化方法执行;
关闭服务器后,销毁过滤器对象;销毁方法执行.
(2)得到登录成功的地址时,进行非法访问登陆成功页面,过滤器首先会判断是否已经登录账号;若未登录则拦截当前请求,拒绝访问资源;
创建AccessViolationFilter判断登录类
public class AccessViolationFilter implements Filter {
//过滤处理方法;
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//判断用户是否已登录;
//ServletRequest作为 HttpServletRequest 的父类;需要向下转型;
HttpServletRequest httpServletRequest=(HttpServletRequest) servletRequest;
//获取到session对象;
HttpSession session = httpServletRequest.getSession();
//获取到设置的用户名的值;
String name = (String) session.getAttribute("name");
if(name==null){
//若为空值,则重定向到登录页面;
HttpServletResponse httpServletResponse= (HttpServletResponse) servletResponse;
httpServletResponse.sendRedirect("login.jsp");
}else{
//使请求继续向下执行;到达过滤链的下一个资源;
filterChain.doFilter(servletRequest,servletResponse);
}
}
}
配置web.xml;
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--配置字符编码过滤器-->
<filter>
<!--filter-name:过滤器名称-->
<filter-name>aboutEncodingFilter</filter-name>
<!--filter-class:过滤器在当前项目的路径-->
<filter-class>com.xiaozhi.filter.EncodingFilter</filter-class>
</filter>
<!--过滤器的映射-->
<filter-mapping>
<!--需要映射的过滤器名称-->
<filter-name>aboutEncodingFilter</filter-name>
<!--<url-pattern>:设置过滤器的作用地址;匹配对应url地址,有多个地址时可以写多个 -->
<!-- <url-pattern>/login.jsp</url-pattern>-->
<!--或者直接写 /* 匹配当前项目所有的地址-->
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--配置判断登录过滤器-->
<filter>
<!--filter-name:过滤器名称-->
<filter-name>AccessViolationFilter</filter-name>
<!--filter-class:过滤器在当前项目的路径-->
<filter-class>com.xiaozhi.filter.AccessViolationFilter</filter-class>
</filter>
<!--过滤器的映射-->
<filter-mapping>
<!--需要映射的过滤器名称-->
<filter-name>AccessViolationFilter</filter-name>
<!--<url-pattern>:设置过滤器的作用地址;匹配对应url地址-->
<url-pattern>/loginSuccess.jsp</url-pattern>
</filter-mapping>
<!--配置默认首选加载页-->
<!--设置默认加载页面-->
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
</web-app>
当未登录时,访问登录成功页面;会被重定向到登录页面
以上是关于JSP ---[过滤器]的主要内容,如果未能解决你的问题,请参考以下文章