EL&JSTL&Filter&Listener day24-EL&JSTL&Filter&Listener 第一章 EL表达式 第二章 JSTL的核心标签库使用 第三章 过滤器Filter 第四章 监听器Listener(了解)
第一章 EL表达式
1.概述
EL(Express Lanuage) 表达式可以嵌入在jsp页面内部,减少jsp脚本的编写,EL出现的目的主要是代替jsp页面中输出脚本<%= 数据%>的编写
2.格式和作用
EL表达式的格式
${EL表达式内容}
EL表达式的作用:
- 从域对象中查找制定的数据
- ServletContext 作用域整个web程序
- session 一次会话
- request 一次请求
- pageContext 当前JSP页面
- EL内置对象的使用
- 执行运算符
3.表达式的基本使用(从域中取数据)
1.EL表达式取数据
格式XXXXScope.key
- ${applicationScope.键名} ServletContext 域对象存储键值对
- ${sessionScope.键名} session 域对象存储键值对
- ${requestScope.键名} request.域对象存储键值对
- ${pageScope.键名} pageContext域对象存储键值对
2.简化方式
EL 表达式去处域对象的数据,简化方式,推荐使用
${键名} 将会从最小的域对象开始查找,一旦找到,就不会再继续查找
友好型:客户端的友好型
<%=%> 取出域对象数据,没有此键,页面中显示null
${} 取出域对象中的数据 没有此键,页面中显示" "
3.通过EL表达式,获得普通数据
格式:
${key}
代码演示:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>获取域容器中的数据</title>
</head>
<body>
<%
// 1 将数据保存到域容器中
pageContext.setAttribute("city", "北京1"); // page
pageContext.setAttribute("city", "北京2", PageContext.REQUEST_SCOPE); // request
pageContext.setAttribute("city", "北京3", PageContext.SESSION_SCOPE); // session
pageContext.setAttribute("city", "北京4", PageContext.APPLICATION_SCOPE); // servletContext
// 2 删除指定域数据
/*
pageContext.removeAttribute("city", PageContext.PAGE_SCOPE); // page
pageContext.removeAttribute("city", PageContext.REQUEST_SCOPE); // request
pageContext.removeAttribute("city", PageContext.SESSION_SCOPE); // session
pageContext.removeAttribute("city", PageContext.APPLICATION_SCOPE); // servletContext
*/
pageContext.removeAttribute("city"); // 删除所有域中的数据
%>
<h1>java</h1>
<h3>获取数据</h3>
<%
out.print(pageContext.getAttribute("city")!=null?pageContext.getAttribute("city"):""); // page
out.print(pageContext.getAttribute("city", PageContext.REQUEST_SCOPE)); // request
out.print(pageContext.getAttribute("city", PageContext.SESSION_SCOPE)); // session
out.print(pageContext.getAttribute("city", PageContext.APPLICATION_SCOPE)); // servletContext
%>
<h3>智能获取数据</h3>
<%
/*
pageContext.findAttribute(key) 根据key从四个域容器中依次获取数据, 如果获取到了,取值结束; 如果都没有获取到, 返回null
*/
out.print(pageContext.findAttribute("city"));
%>
<h1>EL</h1>
<h3>获取数据</h3>
${pageScope.city}
${requestScope.city}
${sessionScope.city}
${applicationScope.city}
<h3>智能获取数据</h3>
${city}
</body>
</html>
4. EL获得javaBean对象的值
格式:
${对象.成员变量}
代码演示
<%@ page import="cn.itcast.pojo.User" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
// EL获得javaBean对象的值
User user = new User();
user.setUsername("zhangsan");
user.setPassword("abc");
request.setAttribute("user", user);
%>
<h1>java</h1>
username = <%=((User)pageContext.findAttribute("user")).getUsername()%> <br/>
password = <%=((User)pageContext.findAttribute("user")).getPassword()%> <br/>
nickname = <%=((User)pageContext.findAttribute("user")).getNickname()%>
<hr/>
<h1>EL</h1>
username === ${user.username} <br/>
password === ${user.password} <br/>
nickname === ${user.nickname} <br/>
</body>
</html>
public class User {
private String username;
private String password;
private String nickname;
//省略构造方法、get、set方法
}
5. EL获得List<String>
的值
格式:
${List集合对象[索引]}
代码演示
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %><%--
EL表达式作用一(从域中取出数据): EL获得 List<String> 的值
格式: ${ List集合对象[索引] }
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--1.创建 List<String>集合, 存到Request域中 --%>
<%
List<String> list = new ArrayList<String>();
list.add("迪丽热巴");
list.add("古力娜扎");
request.setAttribute("list",list);
%>
<%--2.通过EL表达式, 获取List<String>集合中的数据--%>
<%--jsp方式获取--%>
<%
List<String> names = (List<String>) request.getAttribute("list");
out.print( names.get(0) +" === "+ names.get(1) );
%>
<%--EL方式获取--%>
${list[0]} == ${list[1]}
</body>
</html>
6.EL获得List<User>
的值
格式:
${List集合对象[索引].成员变量}
代码演示
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="com.itheima.pojo.User" %><%--
EL表达式作用一(从域中取出数据): EL获得 List<User> 的值
格式: ${ List集合对象[索引].成员变量 }
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--1.创建 List<User>集合, 存到Request域中 --%>
<%
List<User> list = new ArrayList<User>();
list.add(new User("迪丽热巴","123456"));
list.add(new User("古力娜扎","abcdef"));
request.setAttribute("list",list);
%>
<%--2.通过EL表达式, 获取 List<User>集合中的数据--%>
<%--jsp方式获取--%>
<%
List<User> users = (List<User>) request.getAttribute("list");
out.print( users.get(0).getUsername() +"=="+ users.get(0).getPassword() );
out.print( users.get(1).getUsername() +"=="+ users.get(1).getPassword() );
%>
<br/>
<%--EL方式获取--%>
${list[0].username} == ${list[0].password}
${list[1].username} == ${list[1].password}
</body>
</html>
7.EL获得Map<String,User>的值
格式:
${Map集合对象.key.成员变量}
或
${Map集合对象['key'].成员变量}
代码演示
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="com.itheima.pojo.User" %>
<%@ page import="java.util.Map" %><%--
EL表达式作用一(从域中取出数据): EL获得 Map<String, User> 的值
格式:
${Map集合对象.key.成员变量 }
或
${Map集合对象['key'].成员变量}
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--1.创建 Map<String, User>集合, 存到Request域中 --%>
<%
Map<String, User> userMap = new HashMap<String, User>();
userMap.put("user1", new User("迪丽热巴","123456"));
userMap.put("user2", new User("古力娜扎","abcdef"));
request.setAttribute("userMap",userMap);
%>
<%--2.通过EL表达式, 获取 Map<String, User>集合中的数据--%>
<%--jsp方式获取--%>
<%
Map<String, User> map = (Map<String, User>) request.getAttribute("userMap");
out.print( map.get("user1").getUsername() +"=="+ map.get("user1").getPassword());
out.print( map.get("user2").getUsername() +"=="+ map.get("user2").getPassword());
%>
<br/>
<%--EL方式获取--%>
${userMap.user1.username} == ${userMap.user1.password}
${userMap.user2.username} == ${userMap.user2.password}
<br/>
${userMap['user1'].username} == ${userMap['user1'].password}
${userMap['user2'].username} == ${userMap['user2'].password}
</body>
</html>
4.EL的内置对象pageContext
EL的四大内置对象
- applicationScope ServletContext域
- sessionScope session域
- requestScope request域
- pageScope pageContext域
注意
<%pageContext%>指的是pageContext域对象
${pageContext}指的是EL中的一个内置对象
JSP中一共预先定义了9个这样的对象,分别为:request、response、session、application、out、pagecontext、config、page、exception
pageContext : WEB开发中的页面的上下文对象.
作用:可以用来获取JSP中四个域中的数据(pageScope, requestScope, sessionScope, applicationScope)
- 例如,在Servlet中,想获得web应用的名称:
request.getContextPath();
- 那么,在jsp页面上,想获得web应用的名称:
${pageContext.request.contextPath}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>获取WEB应用项目名称</title>
</head>
<body>
<h3>获取WEB应用项目名称</h3>
<%--JSP方式获取--%>
<%= request.getContextPath()%>
<%--EL方式获取--%>
${pageContext.request.contextPath}
</body>
</html>
5.EL执行运算符
-
算数运算符 + , - , * , / , %
-
逻辑运算符 && , || , !
-
比较运算符 > , < , >= , <= , == , !=
-
Null运算符 empty 判空运算
如果判断的对象是空,结果为true
注意:
- 容器判断,判断的是长度 ==0 就是空
- 基本类型数组,不是判断长度,判断数组容器是否存在
- 基本类型数组,判断是空的话只能令他 = null 结果才为true
-
三元运算符
- (布尔表达式)?结果1:结果2
示例代码
<body>
${(6>9)?"漂亮":"酷"}
<br>
<%
User user = new User();
pageContext.setAttribute("user",user);
String[] str = new String[0];
request.setAttribute("str",str);
List<String> list = new ArrayList<String>();
request.setAttribute("list",list);
int[] arr = {};
request.setAttribute("arr",arr);
Integer[] ar = {};
request.setAttribute("ar",ar);
%>
user对象为空吗:${empty user}<br><%--false--%>
str数组为空吗:${empty str}<br><%--true--%>
list集合为空吗:${empty list}<br><%--true--%>
arr数组为空吗:${empty arr}<br><%--false--%>
ar包装类数组为空吗:${empty ar}<br><%--true--%>
</body>
6.案例
记录上一次登录所使用的用户名
步骤
- 获取提交的用户名密码
- 获取是否“记住用户名”
- 判断和tom,123 匹配
- 如果匹配 重定向到首页
- 不匹配 转发回到登录首页;获取cookie中的username值。显示在页面上
示例代码
login首页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/login" method="post">
<%-- 从Cookie中取出 user = tom--%>
用户名:<input type="text" name="username" value="${cookie.user.value}"><br>
密的码:<input type="password" name="password"><br>
<input type="checkbox" name="rem" value="remUsername">记住用户名<br>
<input type="submit" value="登录">
</form>
</body>
</html>
处理记住用户名的操作
- 用户名密码的验证
- 记录用户名
@WebServlet(urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
if ("tom".equals(username) && "123".equals(password)){
response.getWriter().write("login ok");
}else{
response.getWriter().write("login no");
}
// 2.记住用户名
// 判断是否勾复选框的value值
String rem = request.getParameter("rem");// remUsername
System.out.println(rem);
if(rem != null){
// 勾选记住用户名
Cookie cookie = new Cookie("user", username);
cookie.setMaxAge(60*10);
cookie.setPath(request.getContextPath());
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
第二章 JSTL的核心标签库使用
1.概述
JSTL(JSP Standard Tag Library),jsp标准标签库,可以嵌入在jsp页面中使用标签的形式完成业务逻辑等功能。jstl出现的目的和EL相同,也是要放在jsp页面中的脚本代码。
JSTL标准标签库有5个子库,但随着发展,目前最常用的是核心库Core
标签库 | 标签库的URI | 前缀 |
---|---|---|
Core | http://java.sun.com/jsp/jstl/core | c |
I18N | http://java.sun.com/jsp/jstl/fmt | fmt |
SQL | http://java.sun.com/jsp/jstl/sql | sql |
XML | http://java.sun.com/jsp/jstl/xml | x |
Functions | http://java.sun.com/jsp/jstl/functions | fn |
2 jstl标签的安装
导入jar包
javax.servlet.jsp.jstl.jar
standard.jar
使用tagelib指令在jsp页面导入要是用的jstl标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
3.常用的jstl标签
jstl目前常用的标签只有if、foreach标签
3.1 if标签
if标签作用:起到java代码判断的作用
if标签的属性介绍:
- test:判断是否执行标签内的内容(true--执行标签中的内容,false,不执行)。
- var:用来保存test属性结果(使用var属性给他取个名字),这个结果可以保存到制定的web域中,默认保存在pageContext域
- scope:指定保存数据到哪个web域
示例代码
<%-- if标签的使用--%>
<%@ taglib prefix = "c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page contentType="text/html;charset=utf-8" language="java"%>
<html>
<head>
<title>if标签</title>
</head>
<body>
<%
int num = 10;
pageContext.setAttribute("num",num);
%>
<c:if test="${num>5}"> num大于5</c:if>
<c:if test="${num<=5}">num 小于等于5</c:if>
<%--将判断结果 保存到var属性中,并存到指定的域对象--%>
<c:if test="${num == 100}" var = "result" scope="request"></c:if>
<h3>
取出域对象中的值
</h3>
${result}
</body>
</html>
3.2 forEach标签 重点
forEach标签作用:起到java代码的for循环作用
forEach标签属性介绍
- var:在不循环对象的时候,保存的是控制循环的变量;在循环对象的时候,保存的是被循环对象中的元素
- items:指定要循环的对象
- varStatus:保存了当前循环过程中的信息(循环的开始、结束、步长、次数等)
- begin:设置循环的开始
- end:设置循环的结束
- step:设置步长
小结:
foreach标签:循环,包括传统for和增强for
传统for for(int a = 0;a<10;a++){}
属性:
begin="" 相当于 a=0
end="" 相当于 a<10(包含10)
step="" (步长)相当于 a++
step="2" 相当于 1,3,5...
var = "a" 属性var,定义属性值
含义:将循环次数变量,存储到最小域对象 pageContext中
键名就是a
EL 表达式取出
<c:foreach>
循环体
<c:foreach>
遍历数组,遍历集合
属性:
items:遍历容器
var:遍历的容器中的每个元素,存储在pageContext域对象中
var属性值,就是与对象的键名
varStatus(变量状态属性):
varStatus="vs":会将对象,存在pageContext域中
域对象的键名就是vs
对象,是定义了循环状态的对象
对象中有个属性count,循环的次数
输出循环的次数
int count = 0;
for(String s:str){
count++;
System.out.println(s);
}
示例代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<body>
<%--forEach标准循环--%>
<c:forEach begin="1" end="10" step="1" var="a">
<div style="color:red;font-size:28px">
div区域 ${pageScope.a}
</div>
</c:forEach>
<%--遍历集合--%>
<%
String[] strs = {"I","Love","Java"};
pageContext.setAttribute("strs",strs);
%>
<c:forEach items="${strs}" var="s" varStatus="vs">
<%--EL 在pageContext域中取出键值对,键是s,值是数组元素--%>
${s} ${vs.count}<br>
</c:forEach>
<%--集合,存储User对象--%>
<%
List<User> list = new ArrayList<User>();
User u1 = new User();
u1.setUsername("张三");
u1.setPassword("123");
User u2 = new User();
u2.setUsername("李四");
u2.setPassword("456");
list.add(u1);
list.add(u2);
pageContext.setAttribute("list",list);
%>
<c:forEach items="${list}" var="s">
${s.username} ${s.password}
</c:forEach>
</body>
第三章 过滤器Filter
1.Filter概念
过滤器:过筛子,符合条件的才能过去,不符合条件的过不去
生活比喻:安检,检查安全的人与物才可以通过放行
程序:客户端需要访问服务器的目标资源,在客户端和服务器资源之间设置过滤器,符合要求放行
2.入门
需求:
- 浏览器要访问HelloServlet
- 途径过滤期MyFilter, 若MyFilter放行,可执行访问到HelloServlet; 若不放行,无法访问HelloServlet
执行图解:
实现步骤
- 编写Servlet, 在web.xml配置Servlet访问路径
- 编写Filter,定义类, 实现接口Filter, 实现接口中抽象方法, 在web.xml配置Filter的访问过滤路径
代码:Servlet
@WebServlet(urlPatterns = "/servlet1")
public class Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("servlet");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
代码: MyFilter
import javax.servlet.*;
import java.io.IOException;
/**
* 过滤器的快速入门
* 1.定义类实现接口 Fileter
* 2.重写接口中的抽象方法
* 3.web.xml配置
* */
public class MyFilter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
代码: web.xml
<!-- 配置过滤器 配置方式和servlet 90%一致-->
<filter>
<filter-name>myFilter1</filter-name>
<filter-class>com.zhuxu.fitle.MyFilter1</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter1</filter-name>
<!--
Servlet配置 <url-pattern></url-pattern> 浏览器的访问地址
Fileter配置 <url-pattern></url-pattern> 过滤器要拦截的资源
-->
<url-pattern>/*</url-pattern>
</filter-mapping>
执行流程
Tomcat服务器启动的时候,读取配置文件web.xml(过滤器的配置)
Tomcat引擎读取完配置文件后,创建对象 FilterChain对象,过滤器链,维护着过滤器和资源之间的顺序
request,response对象在Tomcat引擎创建对象,调用过滤器,层层传递参数,传递到servlet
3.Filter的生命周期
1.创建
对象初始化创建,调用方法init(初始化)
方法参数 FilterConfig
Tomcat引擎创建过滤器对象,并调用init传递参数
Tomcat启动的时候,创建过滤器对象
方法参数 FilterConfig,过滤器配置对象
可以获取到过滤器的 名字等等
方法 getServletContext() 获取到最大对象
2.拦截方法
拦截方法doFilter
每次访问要拦截的对象,就运行
访问了,非拦截对象,不运行
3.销毁
对象的销毁方法 destroy()
关闭服务器的时候,过滤器对象销毁
4.Filter的url-pattern配置
1.完全匹配
要过滤的资源
只拦截servlet1,其他资源不拦截 几乎不用
没有必要为一个资源,创建过滤器
<!--
过滤资源,只有hello
绝对匹配 <url-pattern>/hello</url-pattern>
只能过滤指定的资源
-->
<url-pattern>/hello</url-pattern>
2.目录匹配
过滤器最常见的配置
一次过滤一大片
拦截下 jstl目录下的所有资源
<!--
目录匹配,过滤器中最常见
/abc/* 过滤abc目录下的所有资源
一次过滤一片资源
过滤后台资源 /admin/*
-->
<url-pattern>/admin/*</url-pattern>
3.后缀名匹配
<!--
后缀名匹配,一般不使用
*.jsp 访问所有jsp文件
-->
<url-pattern>*.jsp</url-pattern>
4.四种拦截形式
- 请求拦截:默认配置,拦截客户端发来的请求
- 转发拦截:FORWARD Servlet1转发到Servlet2,就会拦截
- 包含拦截:INCLUDE 当一个jsp页面包含另一个jsp页面,拦截
- 错误拦截:ERROR 程序出现500错误,跳转到一个页面去 拦截
5.注解配置Filter
@WebFilter(urlPatterns="/过滤资源")
@WebFilter("/*")
public class ChinaFilter implements Filter {
//代码省略...
}
package cn.itcast.web.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
// 方式一
//@WebFilter(urlPatterns = {"/hello.jsp", "/helloServlet"})
// 方式二
// @WebFilter(urlPatterns = {"/hello.jsp"})
// 方式三
// @WebFilter(urlPatterns = "/hello.jsp")
// 方式四
@WebFilter("/hello.jsp")
public class Filter3 implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
// 因为父类不能调用子类的方法,所以向下转型
HttpServletRequest httpServletRequest = (HttpServletRequest) req;
String uri = httpServletRequest.getRequestURI();
System.out.println("执行过滤器3 ... ... 访问的路径: " + uri);
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
6 Filter 处理中文乱码
新建一个拦截器
每次拦截都执行doFilter方法
方法的参数 servletRequest,servletResponse传递到Servlet的doGet方法
过滤器中,设置request对象使用的编码表
所有的Servlet都受益
客户端中文显示设置
servletRequest.setCharacterEncoding("utf-8");
服务器端中文显示设置
servletResponse.setContentType("text/html;charset=utf-8");
代码: ChinaServlet
@WebServlet("/china")
public class ChinaServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println("ChinaServlet , 获取请求参数 username = " + username);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
代码: ChinaFilter
@WebFilter("/*")
public class ChinaFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//在过滤器中,设置request对象的编码表
req.setCharacterEncoding("utf-8");
//设置response缓冲区的编码表,通知浏览器的解码
resp.setContentType("text/html;charset=utf-8");
System.out.println("ChinaFilter执行了, 过滤中文,设置编码utf-8");
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
}
7 过滤器链 FilterChain的执行过程
Filter中的过滤器链 FilterChain: 由Tomcat引擎创建对象
作用: 维护过滤器执行顺序
小结: Servlet中doGet方法参数 request, response对象, 由Tomcat引擎创建, 经过多个过滤器一层层传递
8 多个过滤器的先后执行顺序
web.xml配置
和配置文件的编写顺序决定运行的顺序,准确的说法是,根据mapping的顺序决定 (由上到下执行)
注解开发
注解开发没有配置文件的
按照类名的自然顺序决定: A-B-C(不区分大小写) 1 2 3
如果存在配置文件,配置文件优先
9.过滤器案例:登录验证(权限校验)
1.需求
- 访问项目的资源。验证是否登录
- 如果登陆了,则直接放行
- 如果没有登录,则跳转到登录页面,提示“尚未登录,请先登录”
2.实现
1.登录页面 login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<!--登录失败的提示信息-->
${message}
<form action="${pageContext.request.contextPath}/login" method="post">
用户名:<input type="text" name="username"><br>
密 码:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
2.登录成功界面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>成功界面</title>
</head>
<body>
<h1>欢迎访问</h1>
</body>
</html>
3.过滤器
@WebFilter(urlPatterns = "/resource/*")
public class LoginFilter implements Filter {
/**
* 登录的过滤,如果登录,直接放行
* 没有登录,退到登录页面上
* 客户端是否登录取决于session域对象
* */
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 取出session域对象的值
// ServletRequest转成子接口
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
String username = (String) request.getSession().getAttribute("username");
if (username == null){
// 没有登录,退到登录页面
request.setAttribute("message","请先登录,再访问");
request.getRequestDispatcher("/login.jsp").forward(request,response);
}else{
// 登录状态直接放行
filterChain.doFilter(request,response);
}
}
@Override
public void destroy() {
}
}
4.Servlet
/**
* 处理客户端登录的请求
* 用户名 密码 tom 123
* 登录验证
* 登录成功,页面跳转到 resource/welcome.jsp
* 登录信息存储到session域中
*
* 登录失败,回到登录页面去
* */
@WebServlet(urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
if ("tom".equals(username) && "123".equals(password)){
// 登陆成功,用户名存储在session
request.getSession().setAttribute("username",username);
// 页面跳转到 resource/welcome.jsp
// 重定向,需要写web应用名称
response.sendRedirect(request.getContextPath()+"/resource/welcome.jsp");
}else{
// 登录失败
// 回到登录页面,告知用户登录失败,request域存储登录失败的信息
request.setAttribute("message","登录失败,用户名或者密码输入错误");
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
第四章 监听器Listener(了解)
1 Listener概述
监听器Listener 是 监听某个组件变化的对象.
-
事件源是固定的,主要是request, session, servletcontext域对象
-
监听的是域对象变化
- 对象的创建和销毁, 域对象中存储的数据变化
-
第一个维度划分:
-
监听的域对象request, session, servletcontext
域对象 监听器 request ServletRequestListener session HttpSessionListener servletcontext ServletContextListener
-
-
第二个维度划分:
- 监听的域对象的状态
2 ServletContext监听器入门
用于监听 servletcontext域对象, 对象的创建和销毁, 域对象中存储的数据变化
实现步骤
- 创建类实现监听器接口 ServletContextListener
- 重写抽象方法
- 注解方式 配置 Listener
@WebListener
public class MyServletContextListener implements ServletContextListener {
@Override
/**
* ServletContext对象,被创建,调用
*/
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext域对象创建");
}
@Override
/**
* ServletContext对象,被销毁前调用
*/
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext域对象销毁");
}
}
- web.xml配置方式 Listener
<listener>
<listener-class>com.itheima.listener.MyServletContextListener</listener-class>
</listener>
3 监听器事件对象 ServletContextEvent
ServletContextEvent: 是ServletContext域对象的事件对象, 此对象由tomcat引擎创建ServletContext
- 方法:
-
Object getSource()
获取到被监听的事件源 -
ServletContext getServletContext()
获取到被监听的事件源
-
- 小结:
- 两个方法 除了返回值外,功能实现是一致的, 设计目的为了通用性
- 其他的监听器事件对象(HttpSessionEvent, ServletRequestEvent), 都有共同的方法 getSource()
@WebListener
public class MyServletContextListener implements ServletContextListener {
@Override
/**
* ServletContext对象,被创建,调用
*/
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext域对象创建");
ServletContext context = (ServletContext) servletContextEvent.getSource();
System.out.println(context);
ServletContext servletContext = servletContextEvent.getServletContext();
System.out.println(servletContext);
}
@Override
/**
* ServletContext对象,被销毁前调用
*/
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext域对象销毁");
}
}
4 注解版
package cn.itcast.listener;
import javax.servlet.*;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.*;
// 每次请求都会创建一个新的request对象; 当响应结束后,立刻销毁request对象
@WebListener
public class MyRequestListener implements ServletRequestListener {
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
ServletRequest servletRequest = servletRequestEvent.getServletRequest();
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
System.out.println("新的request对象创建了 .... ... 路径: " + httpServletRequest.getRequestURI());
}
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
System.out.println("request对象销毁了 .... ...");
}
}
重点 Servlet抽取源
如 登录 注册 ....
首页
<html>
<head>
<title>Title</title>
<style>
body{
font-size: 20px;
}
</style>
</head>
<body>
<%--
每个超链接上添加参数,告知服务器,我要做什么
--%>
<a href="${pageContext.request.contextPath}/user?operator=login">登录</a> <br>
<a href="${pageContext.request.contextPath}/user?operator=register">注册</a> <br>
<a href="${pageContext.request.contextPath}/user?operator=updatePassword">改密</a> <br>
<a href="${pageContext.request.contextPath}/user?operator=findPassword">找回密码</a> <br>
</body>
</html>
处理请求操作
/**
* 所有的客户端的用户操作请求
* 我来实现
* */
@WebServlet(urlPatterns = "/user")
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取客户端超链接的参数
/* String operator = request.getParameter("operator");
if ("login".equals("operator")){
login();
}else if ("register".equals(operator)){
register();
}else if ("updatePassword".equals(operator)){
updatePassword();
}*/
// 优化
String operator = request.getParameter("operator");
// 反射,获取客户端参数 opreator 是方法名
try {
Class cla = this.getClass();
// 获取方法
Method method = cla.getMethod(operator,HttpServletResponse.class,HttpServletResponse.class);
method.invoke(this,request,response);
}catch (Exception exception){
exception.printStackTrace();
}
}
// 方法处理登录
public void login(HttpServletRequest request, HttpServletResponse response){
System.out.println("处理登录的方法");
}
// 方法处理注册
public void register(HttpServletRequest request, HttpServletResponse response){
System.out.println("处理注册的方法");
}
// 方法处理改密
public void updatePassword(HttpServletRequest request, HttpServletResponse response){
System.out.println("处理修改密码的方法");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}