1.web开发项目结构
src
------java代码核心的配置文件
(例如spring配置文件等) servlet
web
----静态资源
或者jsp
html/js/css/img等静态资源外部都可以直接访问
web-inf
-外界无法访问
web.xml
—servlet相关配置
2.servlet
- 定义:servlet是基于java技术的
web组件
,由容器管理并产生动态的内容。servlet与客户端通过servlet容器实现请求/相应模型进行交互。(springmvc底层就是基于servlet)
2.1servlet环境搭建
- 在项目中创建
libs
目录存放第三方依赖包 - 导入
servlet-api.jar
到libs目录中(在tomcat安装的目录lib目录中) - 创建servlet包专门存放servlet
- 创建Servlet子类实现Servlet接口
- 在Servlet子类加上
@WebServlet("path")
注解定义URL访问路径 - 重写Servlet类中的
service
,在service中编写动态资源
package com.zhxd.test;
/*
* author zhxd
* ClassName indexServlet
*/
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
import java.io.PrintWriter;
//利用注解定义客户端访问路径
@WebServlet("/zhxd")
public class indexServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
/*
* tomcat 启动完成
* 127.0.0.1:8080/项目名称/zhxd 执行service
* 通过service方法获取ServletRequest ServletResponse对象
* */
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("zhxd???");
//通过servletRequest对象获取客户端传递给服务器的参数
String username = servletRequest.getParameter("username");
//设置响应的格式和字符集
servletResponse.setContentType("text/html;charset=gbk");
//获取响应客户端的流传输管道
PrintWriter writer = servletResponse.getWriter();
if(username.equals("zhxd")) {
writer.println("登录成功");
}else {
writer.println("登录失败");
}
writer.close();
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
2.2servlet执行流程
- servlet由
tomcatweb服务器
创建,service也是由tomcatweb服务器
调用 - 创建一个Servlet子类必须实现servlet接口
重写service
方法 - tomcat服务器执行servlet中的service方法是因为创建的Servlet实现了
httpservlet
接口,实现了service
方法
2.3servlet生命周期(重点)
- 创建servlet实例被服务器(tomcat)加载servlet —
无参构造方法
- servlet创建的模式有两种:第一,第一次访问servlet才会创建servlet对象;第二,提前创建好servlet对象。
- 单例模式:servlet对象创建好之后,在jvm内存中只会
存一份
@WebServlet(urlPatterns="path",loadOnstartup=1)
urlPattern:访问的url
loadOnStartup:当值为负数的时候:第一次访问的创建Servlet对象
;当值为0和正数时:服务器启动就会创建Servlet对象
,数字越小优先级越高,zhxd01Servlet loadOnstartup = 1,zhxd02Servlet loadOnstartup=2,底层会根据loadOnstartup的值排序,越小越优先加载- 共享
同一个Servlet
对象,存在线程安全问题
- init()初始化方法
- 当servlet类被创建时,执行init方法,该方法只
执行一次
,可以在该方法中写一些初始化的代码
- service(),执行每次请求
- 每次客户端发送请求到服务器都会执行service方法,
每次请求都执行一次
- destroy():销毁
- 当tomcat容器停止的时候卸载servlet
2.4Servlet其他方法
getServletConfig()
:该方法返回调用init()方法时传递给Servlet对象的ServletConfig对象,ServletConfig对象包含Servlet的初始化参数getServletInfo()
:返回一个字符串,返回的是一个纯文本字符串,而不是任何类型的标记
getServletConfig的用法:
- 在
@WebServlet()
注解中定义初始化参数,例:@WebServlet(urlPattern="/zhxd",initParams={@WebInitParam(name="",value="")})
- 定义成员属性
ServletConfig servletConfig
- 在生命周期
init(ServletConfig servletConfig)
中给servletConfig赋值,this.servletConfig = servletConfig;
- 重写getServletConfig()方法
例:
package com.zhxd.test;
/*
* author zhxd
* ClassName indexServlet
*/
import javax.servlet.*;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
import java.io.PrintWriter;
//在@WebServlet注解中的initParams定义初始参数
@WebServlet(urlPatterns = "/zhxd", loadOnStartup = -1, initParams = {
@WebInitParam(name = "param1", value = "teacher"),
@WebInitParam(name = "param2", value = "student")
})
public class indexServlet implements Servlet {
//定义私有的servletConfig
private ServletConfig servletConfig;
public indexServlet() {
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
//在初始化给servletConfig赋值
this.servletConfig = servletConfig;
}
//重写getServletConfig
@Override
public ServletConfig getServletConfig() {
return servletConfig;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//通过ServletConfig对象.getInitParameter获取初始化参数
String param1 = getServletConfig().getInitParameter("param1");
String param2 = getServletConfig().getInitParameter("param2");
servletResponse.setContentType("text/html;charset=gbk");
PrintWriter writer = servletResponse.getWriter();
writer.println("param1:" + param1);
writer.println("param2:" + param2);
writer.close();
}
@Override
public String getServletInfo() {
return "I'm ServletInfo";
}
@Override
public void destroy() {
}
}
2.5HttpServlet
HttpServlet模板设计模式:
HttpServlet对的servlet接口包装,提供get/post/put/head
等方法
httpServletDemo.java
package com.zhxd.test;
/*
* author zhxd
* ClassName httpServletDemo
*/
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;
import java.io.PrintWriter;
@WebServlet("/zhxd01")
public class httpServletDemo extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.println("Http的post请求");
writer.close();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.println("Http的get请求");
writer.close();
}
}
html/userinfo.html(post请求)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>userinfo</title>
</head>
<body>
<form action="http://127.0.0.1:8080/zhxd01" method="post">
<label for="">姓名:</label><input type="text" name="username" value=""/><br>
<label for="">年龄:</label><input type="number" name="age" value=""/><br>
<input type="submit" name="submit" value="提交" />
</form>
</body>
</html>
2.6request与response对象
- request:获取客户端发送给服务端的数据
- response:返回数据给客户端
- http协议基于
请求(request)
和响应(response)
模型
2.6.1request对象
- 获取请求方式:
String getMethod()
- 获取项目访问路径:
String getContextPath()
- 获取URL统一资源定位符:
StringBuffer getRequestURL()
- 获取URI统一资源标识:
String getRequestURI()
- 获取get请求的参数:
String getQueryString()
- 根据请求头名称获取值:
String getHeader(String name)
- 获取当前上下文(获取tomcat配置的项目路径):
String contextPath()
- 通过流读取来获取Post参数:
ServletInputStream getInputStream()
BufferReader getReader()
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 通过流获取Post参数
BufferedReader reader = req.getReader();
String str = reader.readLine();
System.out.println(str);
reader.close();
}
- request通用获取请求参数
- Request对象里面封装好了一个Map集合,Map集合里面放的是所有的参数
- 返回Map集合,
Map<String,String[]> getParameterMap()
- 根据键名获取值:
String[] getParameterValues(String name)
- 根据键名获取值:
String getParameter(String name)
package com.zhxd.test;
/*
* author zhxd
* ClassName httpServletTest
*/
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;
import java.util.Map;
@WebServlet("/zhxd02")
public class httpServletTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//请求URL:http://127.0.0.1:8080/zhxd02?name=zhxd&&name=zxd
//获取到参数的Map集合
Map<String, String[]> map = req.getParameterMap();
//遍历map集合
for (String key : map.keySet()) {
System.out.print(key + ":");
String[] values = map.get(key);
for (String value : values) {
System.out.print(value+" "); // name:zhxd zxd
}
System.out.println();
}
//根据 键名 获取值
String value = req.getParameter("name");
System.out.println(value);//zhxd
String[] values = req.getParameterValues("name");
for (String v : values) {
System.out.println(v);
/*
* zhxd
* zxd
* */
}
}
}
2.6.2response对象
- 客户端在发出每个请求的时候都会创建一个response对象,并作为参数传入Servlet.service()中,用于对客户端的请求进行响应
- 设置服务端的编码:
response.setCharacterEncoding("gbk")
- 设置响应头:
response.setHeader("Content-type", "text/html;gbk")
- 同时设置客户端和服务端(调用setCharacterEncoding()方法):
response.setContentType("text/html;charset=gbk")
- 相应格式由三部分组成:
响应行、响应头、响应体
- 向客户端响应正文(响应体),可以使用response响应流:
response.getWriter()/response.getOutputStream()
:如果响应的是字符,就用writer,如果响应的是字节,比如下载的时候,则用outputstream
- 设置错误的响应码:
response.setError(404, "未找到请求的资源")
- 设置正确的响应码:
response.setStatus(200)
2.6.3request请求转发和response重定向
2.6.3.1request请求转发
- 请求转发是在服务器
内部
资源跳转的一种方式,只能转发到服务器内部资源中。
- 获取转发器:
request.getRequestDispatcher(String path)
- 使用RequestDispatcher进行请求转发:
forward(ServletRequest servletRequest,ServletResponse servletResponse)
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/httpServlet02");
requestDispatcher.forward(request,response);
- 数据共享:
request.setAttribute(String name,value)
httpServlet01.java
package com.zhxd.test;
/*
* author zhxd
* ClassName httpServlet01
*/
import javax.servlet.RequestDispatcher;
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("/httpServlet01")
public class httpServlet01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取重请求对象
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/httpServlet02");
//共享数据
req.setAttribute("name","zhxd");
//请求转发
requestDispatcher.forward(req, resp);
}
}
httpServlet02.java
package com.zhxd.test;
/*
* author zhxd
* ClassName httpServlet01
*/
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;
import java.io.PrintWriter;
@WebServlet("/httpServlet02")
public class httpServlet02 extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取共享数据
String name = (String)req.getAttribute("name");
System.out.println(name);
resp.setContentType("text/html;charset=gbk");
PrintWriter writer = resp.getWriter();
writer.println("这是httpServlet02返回的数据");
writer.close();
}
}
2.6.3.2response重定向
- 客户端往服务器发送一个请求,服务端返回http状态码是
302
,同时返回一个新的URL,客户端会按照新的URL重新去发送请求 - 相关API
- 首先设置http状态码为302:
response.setStatus(302)
- 设置响应头location的值:
reponse.setHeader("Location","www.baidu.com")
- 合并上面两个API:
response.sendRedirect(String location)
package com.zhxd.test;
/*
* author zhxd
* ClassName httpServlet01
*/
import javax.servlet.RequestDispatcher;
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("/httpServlet01")
public class httpServlet01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setStatus(302);
resp.setHeader("Location", "http://www.baidu.com");
/*
*resp.sendRedirect("http://www.baidu.com");
*/
}
}
浏览器尚未跳转,按下F9,进入下一步,页面进入百度页面
- 重转发与重定向的区别
- 转发只能把请求转发给同
一个web应用的其他组件
;重定向可以转发到任意
的地址。 - 重转发访问结束后,浏览器的地址栏URL并
不会发生变化
,客户端只发送一次
请求;重定向访问结束后,浏览器地址栏URL会发生变化
,客户端会发送两次
请求。 - 请求转发调用者和被调用者之间共享请求对象,属于同一个请求和响应过程;重定向则是不同的请求和响应过程
3.JSP
JSP是Java Server Page的缩写,是java服务端页面,底层是基于Servlet封装,最终JSP文件会编译为Servlet的java文件。由于Servlet做界面的时候极其不方便,所以产生了JSP技术,页面的书写和一般的html相似。
- 在JSP中定义Java代码
- <%…%>:内容会放到_jspService()方法之中
- <%=…%>:内容会放在out.print(),作为out.print()的参数(responsse.getWriter())
- <%!..%>:内容会放在_jspService()方法之外,被类直接包含
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%
System.out.println("%%是定义在_jspservice之中的...");
int j = 20;
test();
%>
<%="%=%这个也是定义在_jspservlet之中的,可以直接输出字符串给客户端" + j%>
<%!
void test() {
System.out.println("%!%是定义在_jspservice之外的");
}
%>
</body>
</html>
查看转换成Servlet对象之后的代码:CATALINA_BASE: C:\Users\zhxd.IntelliJIdea2017.3\system\tomcat\Unnamed_test\work
3.1JSP内置对象
- JSP内置对象有九个,不需要用户(程序员)创建,在JSP页面中就可以直接使用的对象
对象名 | 真实类型 | 作用 |
---|---|---|
pageContext | PageContext | 当前页面共享数据,还可以获取其他八个内置对象 |
request | HttpServletRequest | 请求对象 |
response | HttpServletResponse | 响应对象 |
out | JspWriter | 输出对象,数据输出到页面上 |
session | HttpSession | 一次会话的多个请求间共享数据 |
application | ServletContext | 用户间共享数据 |
page | Object | 前页面(Servlet)的对象 this |
config | ServletConfig | Servlet的配置对象 |
exception | Throwable | 异常对象 |
- out对象
int getRemaining()
:获取剩余缓冲区大小int getBufferSize()
:获取缓冲区大小void isAutoFlush()
:自动刷新缓冲区
- page对象
page对象包含当前Servlet接口引用的变量,可以看做this关键字的别名
- getClass():返回当前Object的类
- hashCode():返回该Object的哈希代码
- toString():把该Object类转换成字符串
- equals(Object o()):比较该对象和指定对象是否相等
- pageContext对象
在JSP页面中,使用pageContext对象可以获取JSP的其他8个内置对象。它代表当前JSP页面的运行环境,并提供了一系列用于获取其他内置对象的方法。
JspWriter getOut()
:用于获取out内置对象Object getPage()
:用于获取page内置对象ServletRequest getRequest()
:用于获取request内置对象ServleResponse getResponse()
:用于获取response内置对象HttpSession getSession()
:用于获取session内置对象Exception getException()
:用于获取exception内置对象ServletConfig getServletConfig()
:用于获取appliction内置对象setAttribute(String name,Object value, int scope)
:用于设置pageContext对象的属性
pageContext对象可以设置。scope参数:PageContext.PAGE_SCOPE(1),PageContext.REQUEST_SCOPE(2),PageContext.SESSION_SCOPE(3),PageContext.APPLICATION_SCOPE(4)
getAttribute(String name,Object value, int scope)
:用于获取pageContext对象的属性removeAttribute(String name,int scope)
:删除指定范围内名称为name的属性removeAttribute(String name)
:删除所有范围内名称为name的属性findAttribute(String name)
:从4个域对象中查找名称为name的属性
- session对象
session中保存的数据是一次会话有效,保存用户状态,直到
浏览器关闭
为止(和服务器断开连接)。
session.setAttribute(String name, Object obj)
:将属性设置在session范围内session.getAttribute(String name)
:从session对象中获取属性session.removeAttribute(String name)
:从session对象中移除属性
- application对象
application对象用于保存所有应用程序中的公有数据。它在服务器启动时自动创建,在
服务器停止时
销毁。
getAttributeNames()
:获得所有application对象使用的属性名。getAttribute(String name)
:从application对象中获取指定对象名。setAttribute(String key, Object obj)
:使用指定名称和指定对象在application对象中进行关联。removeAttribute(String name)
:从application对象中去掉指定名称的属性。
3.2el表达式
el(Expression Language)表达式语言,用于简化JSP页面内的代码
,主要功能是获取数据
。语法:${expression},会从page、request、session、application域中取值
httpServletTest.java
package com.zhxd.test;
/*
* author zhxd
* ClassName httpServletTest
*/
import javax.servlet.RequestDispatcher;
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("/httpServletTest")
public class httpServletTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String name = "张三";
int age = 20;
String gender = "male";
//定义request域的数据
req.setAttribute("name", name);
req.setAttribute("age", age);
req.setAttribute("gender", gender);
//请求转发
req.getRequestDispatcher("test.jsp").forward(req, resp);
}
}
test.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>test</title>
</head>
<body>
<%--使用el表达式--%>
${name} - ${age} -${gender}
</body>
</html>
3.3jstl标签
jstl是标签语言,是apache对el表达式的扩展,但是并非JSP内置的标签,需要自己导包并指定标签库。
- 环境步骤
- 导入jstl依赖包
- 导入JSTL的core标签库<%@ taglib prefix=“c” uri=“http://java.sun.com/jstl/core_rt” %>
- prefix=“c”:指定标签库的前缀,这个前缀可以随意给值,但是按照习惯标签前缀通常都是c
- uri=“http://java.sun.com/jstl/core”:指定标签库的uri
下载地址:jstl依赖包
JSP学习会重点学到2个标签,<c:if>和<c:forEach>
3.3.1<c:if>条件判断
相当于java的if条件判断语句,它只有if语句,没有else语句
语法<c:if test=“条件”></c:if>
- 条件:必须是一个布尔值,一般结合el表达式
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<html>
<head>
<title>test</title>
</head>
<body>
<%request.setAttribute("number", 4);%>
<c:if test="${number % 2 == 0}">
<h1>偶数</h1>
</c:if>
<c:if test="${number % 2 != 0}">
<h1>奇数</h1>
</c:if>
</body>
</html>
3.3.2<c:forEach>循环语句
相当于java的循环语句
- forEach标签的属性
- 数值操作
- begin:开始值
- end:结束值
- var:临时值
- step:步长
- varStatus:循环状态对象
- index:容器中元素的索引,从0开始
- count:循环次数,从1开始
2.遍历容器
- items:容器对象
- var:容器单个元素的临时值
- varStatus:循环状态对象
- index:容器中元素的索引,从0开始
- count:循环次数,从1开始
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<html>
<head>
<title>test</title>
</head>
<body>
<%
ArrayList<String> nameList = new ArrayList<String>();
nameList.add("beijing");
nameList.add("guangzhou");
nameList.add("zhuhai");
request.setAttribute("nameList", nameList);
%>
<%--遍历容器--%>
<c:forEach items="${nameList}" var="name" varStatus="vs">
第${vs.count}次循环<br />
name${vs.index}:${name}<br />
<hr />
</c:forEach>
<%--遍历数值--%>
<c:forEach begin="0" end="10" step="2" var="i" varStatus="vs">
第${vs.count}次循环,索引值为${vs.index},数值为${i}
<hr />
</c:forEach>
</body>
</html>
4.会话技术
http协议是无状态的,没有任何的记忆功能,每次服务器接收到的请求都是认为是新的请求。会话可以理解为一次通话,从开始直到挂断为一次会话,一次会话可以包含多次请求和响应。会话技术实现方式有:
- 客户端会话跟踪技术:
Cookie
- 服务端会话跟踪技术:
Session
token/jwt
4.1Cookie
Cookie是客户端的会话技术,将数据保存在客户端中,之后每一次请求都携带Cookie数据进行访问,基本原理:Cookie实现是基于HTTP协议的,客户端通过发送请求到达服务端,服务器会创建cookie,通过执行Set-Cookie
将数据返回给客户端,当时用同一个浏览器发送一个请求时,在请求头
中设置cookie数据发送给服务端。
- 创建Cookie对象:
Cookie cookie = new Cookie(String key, String value)
- 使用response响应Cookie给客户端:
response.addCookie(Cookie cookie)
- 获取客户端携带的所有Cookie:
Cookie[] cookies = request.getCookies()
- 获取Cookie对象的名字:
String getName()
- 获取Cookie对象的值:
String getValue()
- 设置Cookie的过期时间:
cookie.setMaxAge(int seconds)
- 正数:将Cookie写入浏览器所在的电脑硬盘中,持久化存储,到期自动删除
- 负数:默认值,当浏览器关闭时,Cookie失效
- 零:删除对应Cookie
setCookie
@WebServlet("/setCookie")
public class testServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie cookie1 = new Cookie("name", "zhangsan");
Cookie cookie2 = new Cookie("age", "18");
//设置cookie
resp.addCookie(cookie1);
resp.addCookie(cookie2);
}
}
getCookie
@WebServlet("/getCookie")
public class testServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取所有Cookie
Cookie[] cookies = req.getCookies();
for(Cookie cookie:cookies) {
//获取cookie对象的名字和值
System.out.println(cookie.getName());
System.out.println(cookie.getValue());
}
}
}
4.2Session
session的底层是基于cookie封装的,数据保存在服务端。session实现的原理:
- 客户端发送请求达到服务器创建session,服务器会返回一个sessionid在响应头
- 客户端接收到sessionid之后保存在Cookie中
- 当同一个浏览器发送请求时会把sessionid通过Cookie形式发送给服务端,服务端接受到sessionid之后再根据id寻找对应的session
- 常用API:
void setAttribute(k,v)
:设置session的键值对Object getAttribute(k)
:根据键获取值void removeAttribute(k)
:根据键删除sessionvoid invalidate
:销毁session对象
getSessionA
@WebServlet("/getSessionA")
public class testServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();//获取session对象
//设置session
session.setAttribute("name", "zhangsan");
session.setAttribute("age", 18);
}
}
getSessionB
@WebServlet("/getSessionB")
public class testServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
//获取session
String name = (String)session.getAttribute("name");
Integer age = (Integer) session.getAttribute("age");
System.out.println("姓名为:"+ name + " " + "年龄:" + age);
}
}
- Sesssion和Cookie的区别
- session用于存储一次会话多次请求的数据,存在服务端端,Cookie存在客户端
- session可以存储任意类型和大小的数据,Cookie存储的数据有大小限制
- session数据较为安全用户不可见,cookie相对不安全
5.过滤器
过滤器是存在客户端与服务器之间的一道过滤网,在访问资源时,对请求进行修改判断,把不符合规则的请求拦截或者修改。应用场景:判断用户是否登录、过滤请求记录日志、身份校验,权限控制等。同时过滤器也可以减少代码冗余的问题。
5.1使用步骤
- 定义一个类实现
Filter接口
- 重写
doFilter()/init()/destory()
方法filterChain.doFilter(servletRequest, servletResponse)
:放行
- 配置拦截路径
package com.zhxd.filter;
/*
* author zhxd
* ClassName FilterTest01
*/
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*")
public class FilterTest01 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器正在运行~");
filterChain.doFilter(servletRequest, servletResponse);//放行请求
}
@Override
public void destroy() {
}
}
5.2过滤器的声明周期
- init():在服务器启动时创建Filter对象,然后调用init初始化方法,只执行一次。
- doFilter():在每次请求被拦截时会执行,会执行多次
- destory():在服务器关闭后,Filter对象被销毁,只执行一次
5.3配置过滤器的拦截
- 拦截路径配置(四种):
- 具体资源路径配置:/index.jsp,只有访问index.jsp时,过滤器才会执行
- 拦截目录:/zhxd/*,访问zhxd目录下的所有资源,都会执行过滤器
- 后缀名拦截:*.jsp,访问jsp资源时,都会执行过滤器
- 拦截所有资源:/*,所有请求都会执行过滤器
- 拦截方式配置:
- REQUEST:默认值,直接访问时拦截
- FORWARD:转发资源时拦截
- INCLUDE:包含资源访问时拦截
- ERROR:错误跳转资源时拦截
- ASYNC:异步访问资源时拦截
//直接访问时
@WebFilter(value = "/index.jsp", dispatcherTypes = DispatcherType.REQUEST)
//转发访问时
@WebFilter(value = "/index.jsp", dispatcherTypes = DispatcherType.FORWARD)
5.4过滤器链
执行完过滤器1,再执行过滤器2…形成了一个链式调用,优先级按照过滤器类名的自然排序
6.监听器
web监听器是Servlet中特殊的一种类,能帮助开发者监听web中的特定事件,比如ServletContext、HttpSession、ServletRequest的创建和销毁;变量的创建、销毁和修改等。可以在某些动作前后增加处理,实现监控。
监听器有三类6种:
- 监听生命周期:
- ServletRequestListener
- HttpSessionListener
- ServletContextListener
- 监听值的变化
- ServletRequestAttributeListener
- HttpSessionAttributeListener
- ServletContextAttributeListener
案例:统计在线人数
onlineSessionListener.java
package com.zhxd.listener;
/*
* author zhxd
* ClassName SessionListenerTest
*/
import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/*
* 监听的实现
* 1. 实现需要的接口
* 2. 加上监听类的注解
*
* 监听Session的声明周期
* 1. sessionCreated session对象创建
* 2. sessionDestoryed session对象销毁
* */
@WebListener
public class onlineSessionListener implements HttpSessionListener {
//在线人数
private Integer onlineNumber = 0;
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
System.out.println("执行Session监听器");
onlineNumber++;
ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
servletContext.setAttribute("onlineNumber", onlineNumber);
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
System.out.println("销毁Session监听器");
onlineNumber--;
ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
servletContext.setAttribute("onlineNumber", onlineNumber);
}
}
onlinServlet.java
package com.zhxd.servlet;
/*
* author zhxd
* ClassName onlineServlet
*/
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;
import java.io.PrintWriter;
@WebServlet("/online")
public class onlineServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置响应类型
resp.setContentType("text/html;charset=utf-8");
//从Application作用域中取出在线人数
//输出
PrintWriter writer = resp.getWriter();
//已登录情况下
String key = req.getParameter("key");
if(key == null || !(key.equals("logout"))) {
Integer onlineNumber =
//不能直接使用req.getServletContext(),要通过session去获取上下文(application作用域)
(Integer) req.getSession().getServletContext().getAttribute("onlineNumber");
writer.write("<h1>在线人数:" + onlineNumber + "</h1><br />");
writer.write("<a href='online?key=logout'>退出登录</a>");
writer.close();
return;
}
//退出
req.getSession().invalidate();
writer.write("<h1>您已退出,再见</h1>");
writer.close();
}
}