监听器
监听器就是一个实现了特定接口的Java类,这个类的作用是来监听另一个方法的调用或属性的改变。当被监听的对象发生了上述事件后,监听器某个方法将会立即被执行。
用来监听其他对象的变化的。主要应用在图形化界面开发中。
- 事件源:指被监听的对象(引发事件的东西),如汽车。JavaWeb中的事件源指的是三大域
- 监听器:指监听的对象,如汽车报警器
- 事件源和监听器绑定:在汽车上安装报警器
- 事件:指事件源对象的改变,如触碰汽车;主要功能是获得事件源对象
一个入门案例
Servlet中的监听器
Servlet中有多种类型的监听器,用于监听的事件源分别是: ServletContext、HttpSession、ServletRequest 三个域对象
监听器的分类:
- 监听三个域对象的创建和销毁的监听器(3个)
- ServletContextListener
- HttpSessionListener
- ServletRequestListener
- 监听三个域对象的属性变更(属性的添加、移除、替换)的监听器(3个)
- ServletContextAttributeListener
- HttpSessionAttributeListener
- ServletRequestAttributeListener
- 监听HttpSession中JavaBean的状态改变(钝化、活化、绑定、解除绑定)的监听器(2个)
- HttpSessionBindingListener
- HttpSessionActivationListener
ServletContextListener
作用:监听ServletContext域对象的创建和销毁的
ServletContext:在服务器启动的时候为每个web应用创建单独的ServletContext对象,在服务器关闭或者移除项目的时候销毁ServletContext(一个项目,只有一个)
用途:
- 加载框架的配置文件,如Spring框架(核心监听器:ContextLoadListener)
- 定时任务调度:服务器启动就开始计时,到达时间后执行程序
方法:
package com.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* ServletContextListener 监听器
* 事件源:ServletContext
* 监听器:MyServletContextListener
* 事件源和监听器绑定:通过配置绑定
*/
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext创建");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext销毁");
}
}
<?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">
<listener>
<listener-class>com.listener.MyServletContextListener</listener-class>
</listener>
</web-app>
HttpSessionListener
作用:监听HttpSession域对象的创建和销毁的
HttpSession:在服务器端第一次调用getSession()方法的时候创建,在非正常关闭服务器、session过期、手动调用session.invalidate方法时被销毁(一次用户的getSession创建一次)
方法:
package com.listener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* HttpSessionListener 监听器
* 事件源:HttpSession
* 监听器:MyHttpSessionListener
* 事件源和监听器绑定:通过配置绑定
*/
public class MyHttpSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("HttpSession创建");
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("HttpSession销毁");
}
}
<session-config>
<session-timeout>1</session-timeout>
</session-config>
<listener>
<listener-class>com.listener.MyHttpSessionListener</listener-class>
</listener>
ServletRequestListener
作用:监听ServletRequest域对象的创建和销毁的
ServletRequest:从客户端向服务器发送一次请求时创建请求对象,服务器对这次请求作出响应之后请求销毁。(每次请求都创建一次)
方法:
package com.listener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
/**
* ServletRequestListener 监听器
* 事件源:ServletRequest
* 监听器:MyServletRequestListener
* 事件源和监听器绑定:通过配置绑定
*/
public class MyServletRequestListener implements ServletRequestListener {
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("ServletRequest创建");
}
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("ServletRequest销毁");
}
}
<listener>
<listener-class>com.listener.MyServletRequestListener</listener-class>
</listener>
案例:统计当前在线人数
需求分析:
package com.onlinecount;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class OnlineCountServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
// 服务器启动时,初始化一个值为0。并且存入ServletContext中
sce.getServletContext().setAttribute("count", 0);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext销毁");
}
}
package com.onlinecount;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class OnlineCountHttpSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
// 在线的话,数值加1
HttpSession session = se.getSession();
System.out.println(session.getId() + "加入会议室");
Integer count = (Integer) session.getServletContext().getAttribute("count");
count++;
session.getServletContext().setAttribute("count", count);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
// 离线,数值减1
HttpSession session = se.getSession();
System.out.println(session.getId() + "退出会议室");
Integer count = (Integer) session.getServletContext().getAttribute("count");
count--;
session.getServletContext().setAttribute("count", count);
}
}
<?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">
<session-config>
<session-timeout>1</session-timeout>
</session-config>
<listener>
<listener-class>com.onlinecount.OnlineCountServletContextListener</listener-class>
</listener>
<listener>
<listener-class>com.onlinecount.OnlineCountHttpSessionListener</listener-class>
</listener>
</web-app>
<body>
<h1>会议室在线人数:${count}</h1>
</body>
域对象属性变更的监听器
ServletContextAttributeListener
作用:监听ServletContext域对象中属性变更(添加、移除、替换)的
HttpSessionAttributeListener
作用:监听HttpSession域对象中属性变更(添加、移除、替换)的
ServletRequestAttributeListener
作用:监听ServletRequest域对象中属性变更(添加、移除、替换)的
案例:
package com.listener1;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent se) {
System.out.println("Session中添加了属性");
}
@Override
public void attributeRemoved(HttpSessionBindingEvent se) {
System.out.println("Session中移除了属性");
}
@Override
public void attributeReplaced(HttpSessionBindingEvent se) {
System.out.println("Session中替换了属性");
}
}
<body>
<%
session.setAttribute("name", "name1");
session.setAttribute("name", "name2");
session.removeAttribute("name");
%>
</body>
JavaBean状态改变监听器
作用:监听HttpSession中JavaBean的状态改变的监听器
- 钝化即随session对象持久化到一个存储设备中(没有关闭和启动服务器)
- 活化即随session对象从一个存储设备中恢复(没有关闭和启动服务器)
- 绑定到session中(setAttribute)
- 从session中解除绑定(removeAttribute)
HttpSessionBindingListener接口、HttpSessionActivationListener接口
实现了这两个接口的类,是不需要在web.xml中进行配置的
HttpSessionBindingListener
监听绑定、解除绑定状态的方法:
package com.listener2;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
public class Bean1 implements HttpSessionBindingListener {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void valueBound(HttpSessionBindingEvent event) {
System.out.println("Bean1绑定session");
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println("Bean1解除绑定session");
}
}
<body>
<%
Bean1 bean1 = new Bean1();
bean1.setName("张三");
session.setAttribute("bean1", bean1); // 绑定
session.removeAttribute("bean1"); // 解绑
%>
</body>
HttpSessionActivationListener
这个主要是进行Session的优化工作。 钝化、活化的状态监听方法:
package com.listener2;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
import java.io.Serializable;
public class Bean2 implements HttpSessionActivationListener, Serializable {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void sessionDidActivate(HttpSessionEvent se) {
System.out.println("Bean2被session钝化(序列化)");
}
@Override
public void sessionWillPassivate(HttpSessionEvent se) {
System.out.println("Bean2被session活化(反序列化)");
}
}
过滤器
Filter过滤器,过滤从客户端向服务器发送的请求。
通过filter,可以对web服务器所管理的资源(JSP,Servlet,静态图片或静态html)进行拦截,从而实现特殊功能。
它可以让请求得到目标资源,也可以不让请求得达到目标资源。过滤器有拦截的能力。(对一组资源进行统一处理)
一个入门案例
package com.filter;
import javax.servlet.*;
import java.io.IOException;
/**
* 编写一个类实现Filter接口
*/
public class FilterDemo1 implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("FilterDemo1执行了...");
filterChain.doFilter(servletRequest, servletResponse);
}
}
<?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>FilterDemo1</filter-name>
<filter-class>com.filter.FilterDemo1</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterDemo1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
FilterChain对象
FilterChain 过滤器链:在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称为是一个过滤器链。
web服务器根据Filter在web.xml文件中的注册顺序(mapping的配置顺序)决定先调用哪个Filter,依次调用后面的过滤器。如果没有下一个过滤器了,会去调用目标资源。(调用完会回来)
Filter生命周期
Filter的创建和销毁,都是由web服务器负责的:
- web应用程序启动的时候,web服务器创建Filter的实例对象,并调用init方法进行初始化(filter只会创建一次,init方法只会执行一次)
- 每次filter进行拦截的时候,都会执行一次doFilter方法
- 当服务器关闭的时候或应用被移除的时候,服务器会销毁filter对象
FilterConfig对象
FilterConfig对象作用:用来获得Filter相关配置的对象。
方法:
案例:
package com.filter;
import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;
public class FilterDemo3 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 获得过滤器的名称
String filterName = filterConfig.getFilterName();
System.out.println("******filterName******" + filterName); // FilterDemo3
// 获得初始化参数
String username = filterConfig.getInitParameter("username");
System.out.println("******username******" + username); // root
// 获得所有初始化参数的名称
Enumeration<String> parameterNames = filterConfig.getInitParameterNames();
while (parameterNames.hasMoreElements()) {
String element = parameterNames.nextElement();
String value = filterConfig.getInitParameter(element);
System.out.println(element + ":" + value); // password:root111 username:root
}
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
<?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>FilterDemo3</filter-name>
<filter-class>com.filter.FilterDemo3</filter-class>
<!-- 配置过滤器的初始化参数 -->
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>root111</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>FilterDemo3</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
过滤器相关配置
- <url-pattern>
- 完全路径匹配:以/开始 /aaa /aaa/bbb
- 目录匹配:以/开始,以结束 /aaa/ /*
- 扩展名匹配:以*开始 *.jsp
- <servlet-name>
- 专门以Servlet配置的名称拦截servlet
- <dispatcher>
- 取值1:REQUEST:默认值,默认过滤器拦截的就是请求
- 取值2:FORWARD:转发,可以拦截转发
- 取值3:INCLUDE:页面包含的时候进行拦截
- 取值4:ERROR:页面出现全局错误页面跳转的时候进行拦截
<filter-mapping>
<filter-name>FilterDemo3</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Filter应用场景
1、执行目标资源之前做预处理工作,例如设置编码,这种试通常都会放行,只是在目标资源执行之前做一些准备工作。
(几乎所有的Servlet中都需要写request.setCharacterEncoding(),可以把它写到一个Filter中。这种过滤器不会做拦截操作,只是设置编码)
(或者分IP统计访问次数)
2、通过条件判断是否放行,例如校验当前用户是否已经登录,或者用户IP是否已经被禁用。(有拦截操作,判断Id是否在禁用区域)
(或粗粒度权限控制)
3、在目标资源执行后,做一些后续的特殊处理工作,例如把目标资源输出的数据进行处理。(批注:回程拦截)
(页面静态化)
案例
案例:分IP统计访问次数
需求:网站统计每个IP地址访问本网站的次数。
分析:
因为一个网站可能有多个页面,无论哪个页面被访问,都要统计访问次数,所以使用过滤器最为方便。
因为需要分IP统计,所以可以在过滤器中创建一个Map<String,Integer>,使用IP为key,访问次数为value
把这个Map存放到ServletContext中,使用ServletContextListener在服务器启动时完成创建(监听器)
1、首先创建一个监听器,用来创建map
package com.web.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.util.HashMap;
import java.util.Map;
public class AListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
// 服务器启动时创建Map,并保存到ServletContext
Map<String, Integer> map = new HashMap<>();
ServletContext servletContext = sce.getServletContext();
servletContext.setAttribute("map", map);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
2、过滤器实现访问记录
package com.web.filter;
import javax.servlet.*;
import java.io.IOException;
import java.util.Map;
/**
* 1、从application中获取Map
* 2、从request中获取当前客户端的IP
* 3、进行统计工作,结果保存到Map中
*/
public class AFilter implements Filter {
FilterConfig config = null;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.config = filterConfig;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
ServletContext servletContext = config.getServletContext();
Map<String, Integer> map = (Map<String, Integer>) servletContext.getAttribute("map");
String ip = servletRequest.getRemoteAddr();
if (map.containsKey(ip)) { // 不是第一次访问
Integer count = map.get(ip);
map.put(ip, count + 1);
} else { // 第一次访问
map.put(ip, 1);
}
servletContext.setAttribute("map", map);
filterChain.doFilter(servletRequest, servletResponse); // 放行不拦截
}
@Override
public void destroy() {
}
}
3、项目配置
<?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">
<jsp-config>
<taglib>
<taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/c.tld</taglib-location>
</taglib>
</jsp-config>
<!--过滤器配置-->
<filter>
<filter-name>AFilter</filter-name>
<filter-class>com.web.filter.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--监听器配置-->
<listener>
<listener-class>com.web.listener.AListener</listener-class>
</listener>
</web-app>
4、页面展示结果
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>当前网页访问次数</title>
</head>
<body>
<h1 align="center">访问次数</h1>
<table align="center" width="30%" border="1">
<tr>
<th>IP</th>
<th>访问次数</th>
</tr>
<c:forEach var="entry" items="${applicationScope.map}">
<tr>
<td>${entry.key}</td>
<td>${entry.value}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
案例:登录权限验证
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<h1>登录页面</h1>
<h3>${msg}</h3>
<form action="${pageContext.request.contextPath}/UserServlet" method="post">
<table border="1" width="400">
<tr>
<td>用户名</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="登录"></td>
</tr>
</table>
</form>
</body>
</html>
UserServlet.java
package com.login;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
if ("root".equals(username) && "root1234".equals(password)) { // 登录成功
req.getSession().setAttribute("user", username);
resp.sendRedirect(req.getContextPath() + "/success.jsp");
} else { // 登录失败
req.setAttribute("msg", "您的用户名或密码错误");
req.getRequestDispatcher("/login.jsp").forward(req, resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>欢迎光临,尊敬的${user}</h1>
</body>
</html>
PrivilegeFilter.java
package com.login;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class PrivilegeFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
String username = (String) request.getSession().getAttribute("user");
System.out.println("这里是doFilter,其中username=" + username);
if (username == null) {
request.setAttribute("msg", "请先登录再进行操作!");
request.getRequestDispatcher("/login.jsp").forward(request, servletResponse);
} else {
filterChain.doFilter(request, 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">
<!--配置Servlet-->
<servlet>
<!--配置Servlet名称-->
<servlet-name>UserServlet</servlet-name>
<!--配置Servlet全路径-->
<servlet-class>com.login.UserServlet</servlet-class>
</servlet>
<!--配置Servlet的一个映射-->
<servlet-mapping>
<!--配置Servlet名称-->
<servlet-name>UserServlet</servlet-name>
<!--配置访问的路径-->
<url-pattern>/UserServlet</url-pattern>
</servlet-mapping>
<!--过滤器配置-->
<filter>
<filter-name>PrivilegeFilter</filter-name>
<filter-class>com.login.PrivilegeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PrivilegeFilter</filter-name>
<url-pattern>/login.jsp</url-pattern>
</filter-mapping>
</web-app>
案例:粗粒度权限管理
user.jsp admin.jsp index.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>index.jsp 游客页面</h1>
<a href="<c:url value='/index.jsp'/>">游客入口</a> <br>
<a href="<c:url value='/users/user.jsp'/>">会员入口</a> <br>
<a href="<c:url value='/admin/admin.jsp'/>">管理员入口</a> <br>
</body>
</html>
login.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
<form action="<c:url value='/LoginServlet'/>" method="post">
用户名:<input type="text" name="username">
<input type="submit" value="登录">
</form>
</body>
</html>
LoginServlet:
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
if (username.contains("admin")) { // 管理员
req.getSession().setAttribute("admin", username);
} else { // 普通会员用户
req.getSession().setAttribute("username", username);
}
req.getRequestDispatcher("/index.jsp").forward(req, resp);
}
}
UserFilter:
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class UserFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
String name = (String) req.getSession().getAttribute("admin");
if (name != null) { // 管理员放行,可以访问user.jsp
filterChain.doFilter(req, servletResponse);
return;
}
name = (String) req.getSession().getAttribute("username");
if (name != null) { // 会员放行
filterChain.doFilter(req, servletResponse);
} else { // 游客不放行
req.setAttribute("msg", "您不是会员或者管理员,无权访问");
req.getRequestDispatcher("/login.jsp").forward(req, servletResponse);
}
}
}
AdminFilter:
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class AdminFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
String name = (String) req.getSession().getAttribute("admin");
if (name != null) { // 管理员放行,可以访问admin.jsp
filterChain.doFilter(req, servletResponse);
} else {
req.setAttribute("msg", "您不是者管理员,无权访问");
req.getRequestDispatcher("/users/user.jsp").forward(req, servletResponse);
}
}
}
配置文件:
<?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">
<jsp-config>
<taglib>
<taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/c.tld</taglib-location>
</taglib>
</jsp-config>
<!--配置Servlet-->
<servlet>
<!--配置Servlet名称-->
<servlet-name>LoginServlet</servlet-name>
<!--配置Servlet全路径-->
<servlet-class>LoginServlet</servlet-class>
</servlet>
<!--配置Servlet的一个映射-->
<servlet-mapping>
<!--配置Servlet名称-->
<servlet-name>LoginServlet</servlet-name>
<!--配置访问的路径-->
<url-pattern>/LoginServlet</url-pattern>
</servlet-mapping>
<!--过滤器配置-->
<filter>
<filter-name>UserFilter</filter-name>
<filter-class>UserFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UserFilter</filter-name>
<url-pattern>/users/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>AdminFilter</filter-name>
<filter-class>AdminFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AdminFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
</web-app>
案例:编码问题
测试页面:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="<c:url value='/EncodeServlet?username=张三GET'/>">点击这里调用GET方法</a> <br>
<form action="<c:url value='/EncodeServlet'/>" method="post">
用户名:<input type="text" name="username" value="李四POST">
<input type="submit" value="提交">
</form>
</body>
</html>
过滤器:
public class EncodeFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletResponse.setContentType("text/html;charset=utf-8");
// 处理POST请求编码问题
servletRequest.setCharacterEncoding("utf-8");
filterChain.doFilter(servletRequest, servletResponse);
}
}
EncodeServlet:
public class EncodeServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
resp.getWriter().println(username);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
resp.getWriter().println(username);
}
}
案例:页面静态化
什么是页面静态化:
页面静态化是把动态页面生成的html保存到服务器的文件上,然后再有相同请求时,不再去执行动态页面,而是直接给用户响应上次已经生成的静态页面。而且静态页面还有助于搜索引擎找到。