1 重定向和EL表达式
1.1 RequestDispatcher 请求转发
-
RequestDispatcher 请求转发
- 客户端发起请求,servlet处理业务逻辑;
- servlet调用forward方法,把请求转发到指定资源(jsp、servlet、html);
- 因为是内部转发所以地址栏的地址不会有变化;
-
RequestDispatcher 可以访问WEB-INF的数据(有限制一般不能访问)
-
示例:
跳转的jsp代码
<%--
Created by IntelliJ IDEA.
User: 14408
Date: 2022/12/7
Time: 10:44
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
我是跳转的dispatcher
</body>
</html>
java代码
package net.lizheng.web;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name="dispatcher",value = "/dispatcherforward")
public class Dispatcher extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("WEB-INF/dispatcher.jsp").forward(req,resp);
}
}
了解即可,
1.2 EL表达式
- 全称Expression language 灵感来与ECMAscript和xpath ,提供了简写jsp的表达式,使jsp更加的简洁明了;
- 语法:
${变量名} 或者${对象.属性}
- 取值是从小到大寻找page->request->session->application
- 指定某个作用域寻找:
- pageScope
- requestScope
- sessionScope
- applicationScope
javabean
- 指定某个作用域寻找:
package net.lizheng.web;
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
jsp
<%--
Created by IntelliJ IDEA.
User: 14408
Date: 2022/12/7
Time: 10:44
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
name1=${name1}
<br>
name2=${name3.name}
<br>
age=${name3.age}
<br>
<%--指定在session作用域寻找没有返回为空--%>
name3=${seessionScope.name2}
</body>
</html>
请求
package net.lizheng.web;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name="dispatcher",value = "/dispatcherforward")
public class Dispatcher extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("name1","小曾");
req.setAttribute("name2","小政");
User user=new User();
user.setName("小小");
user.setAge(12);
req.setAttribute("name3",user);
req.getRequestDispatcher("WEB-INF/dispatcher.jsp").forward(req,resp);
}
}
1.3 sendRedirect 重定向
- 重定向:客户端发送了请求,sevlet处理业务逻辑,servlet会调用sendRediect()方法会把目前资源(servlet,jsp,html,外部站点)作为响应信息返回给客户端,客户端会根据重定向的地址再次向服务器发送请求;
- 不能访问web-inf目录,浏览器地址的地址会变化;
- 原地址响应码为302 响应头location为跳转的新地址;
- 外部站点必须加上http或者https才能访问;
- 和requestdispatcher相比 sendredirect的性能效率不如requestdispatcher
代码:
package net.lizheng.web;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "sendRedirect",value = "/SendRedirecr")
public class SendRedirecr extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("https://mp.csdn.net/");
}
}
2 Session和Cookie
2.1 基础知识
- 无状态协议:http是无状态协议,客户端和服务端交换数据结束,客户端和服务端就会断开连接,再次请求需要重新建立连接,这就意味着http不能记录http的状态。
- 会话跟踪:会话是用户登录网站后的一系列的操作,例如登录视频网站查看视频,会话跟踪是web程序的一项技术,用来跟踪一个会话,常用的会话跟踪技术是session和cookie;
- cookie是客户端记录信息验证身份,session是通过服务器记录信息验证身份;
2.2 Cookie
- Cookie的工作原理:Cookie实际上是一小段文本信息,当服务器需要记录客户端请求状态的时候,服务端就会生成一个cookie发送给客户端,客户端会保存并在下一次请求附带这个cookie,服务端会校验cookie从而跟踪整个会话;
- cookie的分类
- 会话cookie 不设置有效期 生命周期是打开浏览器到关闭浏览器,储存在内存中;
- 持久cookie 设置有效期 会把cookie存储在磁盘中;
- cooke的常用的值
- name 名字;
- value 值 ;
- domain 存储cookie的父域或者子域;
- expired/max-age cookie的有效期;
- size cookie的大小;
- path cookie的路径;
- http-only 客户端的cookie不能被客户端的js读取
- secure 服务端只支持https的请求;
- cookie的缺陷
- 会增加请求的流量;
- cookie以明文的方式不安全;
- Cookie一般4000多k 不能存储大的数据;
- 浏览器最多能支持50多个cookie 至少能支持20个;
增加token代码
package net.lizheng.web.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/AddCookie")
public class AddCookie extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie cookie = new Cookie("token", "sdjlksjdlfjlsdjlfasjdkfjskldf");
cookie.setMaxAge(200);
cookie.setHttpOnly(true);
resp.addCookie(cookie);
}
}
获取token代码
package net.lizheng.web.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/GetCookie")
public class GetCookie extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie[] cookies = req.getCookies();
for (Cookie cookie:cookies){
System.out.println( "Name是"+cookie.getName());
System.out.println( "Value是"+cookie.getValue());
System.out.println( "Secure是"+cookie.getSecure());
System.out.println("-----------------------");
}
}
}
2.3 Session
- Session的工作原理:Session是记录客户状态的一种机制,Session是保存在服务端的,Session依赖Cookie,用户请求服务器会建立一个map结构的key-value的键值对(SessionId和Session),并把Sessionid(cookie)响应给客户端并保存,下次请求就会把SessionI携带过去,服务器收到SessionID就会检索从而达到记录客户状态;
- Session有时效性,可以随着请求更改session的状态;
- 登录举例
登录JAVA代码
package net.lizheng.web.seession;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/Login")
public class Login extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username =req.getParameter("username");
String password =req.getParameter("password");
if (username.equals("xiaozeng")&&password.equals("123456")){
Userdemo userdemo=new Userdemo();
userdemo.setName(username);
userdemo.setAge(23);
userdemo.setMsg("今天不学习明天变垃圾");
HttpSession session = req.getSession();
session.setAttribute("loginInfo",userdemo);
req.getRequestDispatcher("WEB-INF//userinfo.jsp").forward(req,resp);
}else {
HttpSession session = req.getSession();
session.setAttribute("errmsg","账号密码错误");
req.getRequestDispatcher("/login.jsp").forward(req,resp);
}
//seeion的常用方法
HttpSession session = req.getSession();
System.out.println(session.getId());
System.out.println(session.getCreationTime());
System.out.println(session.isNew());
}
}
退出JAVA代码
package net.lizheng.web.seession;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/Logout")
public class Logout extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//session失效
req.getSession().invalidate();
req.getRequestDispatcher("login.jsp").forward(req,resp);
}
}
javabean代码
package net.lizheng.web.seession;
public class Userdemo {
private String name;
private int age;
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
登录页面信息
<%--
Created by IntelliJ IDEA.
User: 14408
Date: 2022/12/8
Time: 10:06
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/testdemo/Login" method="post">
<input type="text" name="username">
<br>
<input type="password" name="password">
<br>
<input type="submit" value="登录">
</form>
<br>
${errmsg}
</body>
</html>
用户信息
<%--
Created by IntelliJ IDEA.
User: 14408
Date: 2022/12/8
Time: 10:30
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
name=${loginInfo.name}
<br>
age=${loginInfo.age}
<br>
msg=${loginInfo.msg}
<br>
<a href="/testdemo/Logout"> 退出 </a>
</body>
</html>
3 Filter和Listener
3.1Filter
- Filter是过滤器,会过滤servlet容器传给web资源的request对象和repone对象,进行检索和修改
- Filter的作用:
- 动态的拦截请求和响应,进行修改和使用请求和响应的信息;
- 拦截请求是在进入web资源之前拦截;
- 拦截响应会在响应客户端之前拦截;
- Filter的生命周期(有三个方法):
- init()方法,只会启动一次,用于初始化;
- doFilter(HttpServletRuquest ruq,HttpServletRpone req ,FilterChain chain) 只要满足条件就会触发,只要根据条件决定是否放行(doChain()方法);
- destroy 容器销毁的时候执行一次
- @WebFilter注解:
方法 | 描述 |
---|---|
servletName | 以servletname为条件进行筛选 servletName等价于webServlet的Name |
urlPatterns | 路径为筛选条件 等价于webServlet的urlPatterns |
value | 和urlPatterns一样 两者不可一起使用,urlPatterns定义多个路径,value只能定义一个路径 |
filterName | 定义过滤器的名字 |
displayName | 过滤器的显示名字 |
dispatcherType | 过滤器筛选的范围 |
initparam | 初始化的参数 |
asyncSupported | 是否支持异步 |
decription | Filter的描述信息 |
- dispatcherType的筛选范围
- REQUEST 默认值 监控所有的请求;
- FORWARD 筛选forward方法的请求;
- INCLUDE 筛选include方法的请求;
- ERROR 错误资源的请求;
- ASNYC 筛选异步请求;
- FilterConfig的三个方法
public interface FilterConfig {
//Filter的姓名
String getFilterName();
//获取ServletContext 对象
ServletContext getServletContext();
获取注解中初始化的参数
String getInitParameter(String var1);
Enumeration<String> getInitParameterNames();
}
3.2 Listener
- 监听器是实现了特定接口的特殊类,用于监听对象创建和销毁以及对象的属性和对象方法的执行。
- 作用监听域对象request/session/application:
- ServletRquestListener
- HttpSessionListener
- ServletContextListener
- 实现方法:
- 创建一个普通类并实现接口;
- 重写监听接口的方法 ;
- 旧版Listener配置是在web.xml文件,新版是使用元注解;
3.2.1 SevletContextListener
- 监听 ServletContext 对象的生命周期,实际上就是监听 Web 应用的生命周期。
- 例如:监听SevletContext的初始化参数:
1.配置初始化参数
<?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">
<context-param>
<param-name>namelistener</param-name>
<param-value>我是全局监听</param-value>
</context-param>
<context-param>
<param-name>age</param-name>
<param-value>web项目关闭自动销毁</param-value>
</context-param>
</web-app>
配置类
<?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">
<context-param>
<param-name>namelistener</param-name>
<param-value>我是全局监听</param-value>
</context-param>
<context-param>
<param-name>age</param-name>
<param-value>web项目关闭自动销毁</param-value>
</context-param>
</web-app>
建立监听类
package net.lizheng.web.Listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class ServetAll implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("contextInitialized");
ServletContext servletContext = sce.getServletContext();
Config config=new Config();
String name=servletContext.getInitParameter("namelistener");
String age =servletContext.getInitParameter(("age"));
config.setNamelistener(name);
config.setAge(age);
System.out.println(config.getNamelistener());
System.out.println(config.getAge());
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("contextDestroyed");
}
}
启动web项目
3.2.2 HttpSession
- 监控整个session域对象。
- 例如:统计用户在线人数量
初始化全局变量
//设置session初始值
servletContext.setAttribute("onlineCount",0);
配置监听类
package net.lizheng.web.Listener.HttpSession;
import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class SessionCount implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
HttpSession session = se.getSession();
ServletContext servletContext = session.getServletContext();
Integer onlineCount = (Integer)servletContext.getAttribute("onlineCount");
servletContext.setAttribute("onlineCount",++onlineCount);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();
ServletContext servletContext = session.getServletContext();
Integer onlineCount = (Integer)servletContext.getAttribute("onlineCount");
servletContext.setAttribute("onlineCount",--onlineCount);
}
}
查看人数的jsp
<%--
Created by IntelliJ IDEA.
User: 14408
Date: 2023/2/17
Time: 10:42
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>在线人数通知</title>
</head>
<body>
目前在线人数是${applicationScope.onlineCount}
</body>
</html>
退出的jsp
<%--
Created by IntelliJ IDEA.
User: 14408
Date: 2023/2/17
Time: 10:44
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
request.getSession().invalidate();
%>
目前人数是${applicationScope.onlineCount}
</body>
</html>
3.2.3 ServletRquestListener
- 监听域对象request。
- 例如:监听接口的访问量:
设置全局变量
servletContext.setAttribute("requestCount",0);
监听类
package net.lizheng.web.Listener.Ruquest;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class RequestCount implements ServletRequestListener {
@Override
public void requestInitialized(ServletRequestEvent sre) {
ServletContext servletContext = sre.getServletContext();
Integer requestCount = (Integer)servletContext.getAttribute("requestCount");
servletContext.setAttribute("requestCount",++requestCount);
}
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("requestDestroyed");
}
}
查看通知量的jsp
<%--
Created by IntelliJ IDEA.
User: 14408
Date: 2023/2/17
Time: 11:35
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>请求量</title>
</head>
<body>
接口请求量统计${applicationScope.requestCount}
</body>
</html>