JavaWeb
Tomcat
1.1、官方链接https://tomcat.apache.org/download-80.cgi
1.2、启动:bin->startup
1.3、乱码解决
conf->logging.properties找到如下配置项:
java.util.logging.ConsoleHandler.encoding = UTF-8
将 UTF-8 修改为 GBK,修改后的效果为:
java.util.logging.ConsoleHandler.encoding = GBK
保存后,重启tomcat!
通过http://localhost:8080/访问服务器页面
访问页面时乱码:https://blog.youkuaiyun.com/weixin_39626745/article/details/110496357
1.4、关闭
正常关闭
bin->startup
强制关闭
点击启动窗口的×
1.5、配置
部署项目的方式
-
直接将项目放到webapps下即可
-
重新启动Tomcat服务器
-
-
分别为端口号->目录->网页名
-
简化部署:
-
war包方式
- 将项目打成一个war包,再将war包放置到webapps目录下。
- war包会自动解压缩
-
配置conf/server.xml文件
docDase:项目存放的路径 path:虚拟目录
-
在conf\Catalina\localhost创建任意名称的xml文件
- 在文件中去编写以上图片中标签的内容(注,无path,虚拟目录为xml文件名)
-
1.6、项目部署
静态项目和动态项目
- 目录结构
- java动态项目的目录结构
- 项目的根目录
- WEB-INF目录:
- web.xml:web项目的核心配置文件
- classes目录:放置字节码文件的目录
- lib目录:放置依赖的jar包
- WEB-INF目录:
- 项目的根目录
- java动态项目的目录结构
1.7、IDEA集成创建Web项目
将Tomcat集成到IDEA中,并且创建JavaEE的项目,部署项目
- 选择IDEA的Run菜单->Edit Configurations…
1.8-IDEA与tomcat的相关配置
IDEA会为一个tomcat部署的项目单独建立一份配置文件
- 查看控制台的log:
- Using CATALINA_BASE: “C:\Users\Administrator\AppData\Local\JetBrains\IntelliJIdea2021.1\tomcat\bee10957-0d37-4952-ba05-24f7c7f17d88” – 项目配置文件路径
- 工作空间项目 和 tomcat部署的web项目
- tomcat真正访问的是
tomcat部署的web项目
,它对应着工作空间项目
的web目录下的所有资源 WEB-INF
目录下的资源不能被浏览器直接访问
- tomcat真正访问的是
- 断点调试
- 在代码行左侧打断点,点击小爬虫或shift+f9使用debug模式启动tomcat
Servlet
2.1、Servlet概述
概念:运行在服务器端的小程序
- Servlet就是一个接口,,定义了Java类被浏览器访问到(tomcat识别)的规则
- 将来我们自定义一个类,实现Servlet接口,复写方法
2.2、Servlet入门
- 创建JavaEE项目
- 定义一个类,实现Servlet接口
- 实现接口中的抽象方法
- 在service(提供服务的方法)写入内容
- 配置Servlet(在WEB-INF下的web.xml文件)
实现Servlet接口,创建类
package com.example.javaWeb_Servlet;
import javax.servlet.*;
import java.io.IOException;
/**
* @author 玫瑰到了花期
* @data 2022/3/21 14:19
* @love 又偷偷看你了
* @V: CBWR-K
*/
public class Servlet01 implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
编写web.xml配置文件
<!--配置Servlet-->
<servlet>
<servlet-name>demo1</servlet-name>
<servlet-class>com.example.javaWeb.ServletDemo01</servlet-class>
</servlet>>
<!--映射Servlet-->
<servlet-mapping>
<servlet-name>demo1</servlet-name>
<url-pattern>/demo1</url-pattern>
</servlet-mapping>
通过url-pattern映射的路径来访问
2.3、Servlet执行原理
- 当服务器接收到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
- 查找web.xml文件,是否有对应的标签体内容
- 如果有,则在找到对应的全类名
- tomcat会将字节码文件加载进内存,并且创建其对象
- 调用其方法
2.4、Servlet生命周期
简述
- 被创建:执行init方法,只执行一次
- Servlet什么时候被创建
- 默认情况下,第一次被访问时,Servlet被创建
- 可以配置执行Servlet的创建时机
- 在Servlet标签下配置
- 第一次被访问时,创建
- 的值为负数
- 在服务器启动时,创建
- 的值为0或正整数
- 第一次被访问时,创建
- 在Servlet标签下配置
- Servlet的init方法只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的
- 多个用户同时访问时,可能出现线程安全问题
- 解决:尽量不要在Servlet中定义成员变量,即使定义了成员变量,也不要修改值
- 多个用户同时访问时,可能出现线程安全问题
- Servlet什么时候被创建
- 提供服务:执行service方法,执行多次
- 每次访问Servlet方法,执行多次
- 被销毁:执行destroy方法,执行一次
- Servlet被销毁时执行,服务器关闭时,Servlet被销毁
- 只有服务器正常关闭时才会执行destroy方法
- destroy方法在Servlet被销毁之前执行,一般用于释放资源
init()
/**
* 初始化方法
* 在Servlet被创建时执行,只会执行一次
* 执行在控制台
* */
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init....");
}
getServletConfig()
/**
* 获取ServletConfig对象
* ServletConfig:Servlet的配置对象
* */
@Override
public ServletConfig getServletConfig() {
return null;
}
service()
/**
* 提供服务方法
* 每一次Servlet被访问时,执行,执行多次
* 执行在控制台
* */
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("servlet....");
}
getServletInfo()
/**
* 获取Servlet的一些信息,版本,作者等等。
* */
@Override
public String getServletInfo() {
return null;
}
destroy()
/**
* 销毁方法
* 在服务器正常关闭,执行,执行一次
* */
@Override
public void destroy() {
System.out.println("destroy....");
}
load-on-startup – xml
<load-on-startup>-5</load-on-startup>
<!--指定Servlet的创建时机
1.第一次被访问时,创建
<load-on-startup>的值为负数
2.在服务器启动时,创建
<load-on-startup>的值为0或正整数
-->
2.5、Servlet注解配置
简述
- 好处
- 支持注解配置。可以不需要web.xml了
- 步骤
- 创建javaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml
- 定义一个类,实现Servlet接口
- 复写方法
- 在类上使用@WebServlet注解,进行配置
使用
@WebServlet
//uelpatterns="访问路径" -- 注解写在类前
@WebServlet(urlPatterns = "/demo")
//写法2
@WebServlet("/demo2")
//写法3,多条访问路径
@WebServlet({"/demo3","/demo4"})
2.6、Servlet体系结构
Servlet – 接口
|
GenericServlet – 抽象类
|
HttpServlet – 抽象类
- GenericServlet: 默认将除了service方法外的所有方法都给实现了,只把service方法抽象化,这样servlet类在继承GenericService时只用重写service方法即可
- ⭐HttpServlet:对http协议的一种封装,简化手动写判断请求方式的操作
-
定义类继承HttpServlet
-
复写doGet/doPost方法
-
doGet->
-
-
doPost->
-
-
2.7、快速创建Servlet类
2.8、Servlet路径配置
-
/xxx
-
资源目录,访问此路径
-
-
-
-
/xxx/xxx
-
多层路径,目录结构,需要输全路径才能访问
-
-
-
-
*.do
-
==万能路径,表示==后面的路径可以随意输入
-
.do表示必须以do结尾
-
-
-
HTTP
3.1、概念
- Hyper Text Transfer Protocol 超文本传输协议
- 传输协议
- 定义了,客户端和服务端通信时,发送数据的格式
- 特点
- 基于TCP/IP的高级协议
- 默认端口号:8080
- 基于请求/响应模型的
- 一次请求对应一次响应
- 无状态的
- 每次请求之间相互独立的,不能交互数据
- 历史版本
- 1.0
- 每次使用,都会重新建立连接
- 1.1
- 复用连接
- 1.0
3.2、请求消息与响应消息
请求消息的数据格式
3.2.1、请求行
请求方式 | 请求url | 请求协议 | 版本 |
---|---|---|---|
GET | /login.html | HTTP | 1.1 |
- HTTP协议游7种请求方式,常用的有2种
- GET:
- 请求参数在请求行中,在url后
- 请求的url长度有限制
- 不安全
- Post:
- 请求参数在请求体中、
- 请求的url长度没有限制
- 相对安全
- GET:
3.2.2、请求头
请求头名称:请求头值
客户端浏览器告诉服务器一些信息
请求头名称 | 使用 |
---|---|
Host:localhost | 端口 |
User-Agent: | 浏览器告诉服务器,访问你使用的浏览器版本信息 |
可以在服务端获取该头的信息,解决浏览器兼容问题 | |
Referer: | 告诉服务器,我(当前请求)从哪里来 |
作用: | 防盗链 |
统计 | |
Connection: | keep-alive 可以被复用 |
3.2.3、请求空行
空行,就是用于分割POST请求的请求头和请求体的
空行 |
---|
3.2.4、请求体(正文)
- 封装POST请求消息的请求参数
Request – 请求
4.1、继承体系
- request对象和response对象的原理
- request和response对象是由服务器创建的,我门来使用它
- request对象是来获取请求消息
- response对象是来设置响应消息
- request:获取请求消息
4.2、Request对象
获取请求消息数据
获取请求行数据 -F
-
Get /day1/demo1?name=傻逼胡子洋 HTTP/1.1
-
方法:
功能 方法 获取请求方式:GET String getMethod() ==*==获取虚拟目录:/day1 String getContextPath() 获取Servlet路径:/demo1 String getServletPath() 获取get方式请求参数:name=… String getQueryString() ==*==获取请求的url:/day1/demo1 String getRetURL():/day1/demo1 StringBuffer getRequestURL():http://localhost/day1/demo1 获取协议及版本:HTTP1.1 String getProtocol() 获取客户机的IP地址 String getRemoteAddr() URL: 统一资源定位符 – 中华人民共和国 URI: 统一资源标识符 – 共和国 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1、获取请求方式 String method = request.getMethod(); System.out.println("请求方式为:"+method); //2、获取虚拟目录 String contextPath = request.getContextPath(); System.out.println("虚拟目录为:"+contextPath); //3、获取Servlet路径 String servletPath = request.getServletPath(); System.out.println("Servlet路径为:"+servletPath); //4、获取get方式请求参数 String queryString = request.getQueryString(); System.out.println("get方式请求参数为:"+queryString); //5、获取请求的url StringBuffer requestURL = request.getRequestURL(); System.out.println("URL为:"+requestURL); //6、获取协议及版本 String protocol = request.getProtocol(); System.out.println("协议版本为:"+protocol); //7、获取客户机的IP地址 String remoteAddr = request.getRemoteAddr(); System.out.println("客户机的IP地址为"+remoteAddr); }
获取请求头数据 -F
功能 | 方法 |
---|---|
String contains(“”) | request对象判断字符串 |
String getHeader(String name) | ==*==通过请求头的名称获取请求头的值 |
Enumeration getHeaderNames() | 获取所有请求头的值 |
hasMoreElements() | 测试此枚举是否包含更多的元素(迭代器) |
nextElement() | 如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素 |
获取所有请求头以及值
S-user-agent
获取指定请求头的值
S-referer
获取请求体数据
-
请求体
- 只有POST请求方式才有请求体,在请求体中封装了POST请求的请求参数
-
步骤
-
获取流对象
-
从流对象中拿数据
-
方法 说明 BufferedReader getReader() 获取字符输入流,只能操作字符数据 ServletInputStream getInputStream() 获取字节输入流,可以操作所有类型数据 在文件上传后讲解 .readLine() 读取数据 以字符串形式返回这一行的数据 @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取请求消息体 -- 请求参数 //1.获取字符流 BufferedReader br = request.getReader(); //2.读取数据 String line = null; while ((line = br.readLine())!=null){ System.out.println(line); } } }
-
-
获取请求参数通用方式(s/get)-- F
方法 | 说明 |
---|---|
String getParameter(String name) | 根据参数名称获取参数值 |
password=123456 | 参数传递"password"返回123456 |
String[] getParameterValues(String name) | 根据参数名称获取参数值的数组(多个数值) |
name=“1”&name=“2” | 参数传递"name"返回所有name值 |
getParameterNames() | 获取所有请求的参数名称 |
Map<String,String[]> getParameterMap() | 获取所有参数的map集合 |
.keySet() | 输出键集合 |
getParameter
//post 获取请求参数
//根据参数名称获取参数值
String user = request.getParameter("User");
String password = request.getParameter("password");
System.out.println(user+password);
String[] getParameterValues(String name)
//post 获取请求参数
//根据参数名称获取参数数组
String[] names = request.getParameterValues("hobby");
for (String name:names) {
System.out.println(name);
}
Map<String,String[]> getParameterMap()
//post 获取请求参数
//获取所有参数的map集合
Map<String, String[]> parameterMap = request.getParameterMap();
Set<String> keySet = parameterMap.keySet();
for (String name : keySet) {
//获取键获取值
String[] values = parameterMap.get(name);
System.out.println(name);
for(String value : values){
System.out.println(value);
}
System.out.println("-------------");
}
获取请求参数中文乱码的问题
-
get方式:tomcat 8 已经将get方式乱码问题解决了
-
post方式:会乱码
-
解决:在获取参数前,设置request的编码
-
request.setCharacterEncoding("utf-8");
-
请求转发 --F
一种在服务器内部的资源跳转方式
-
方法 request 说明 getRequestDispatcher(String path) 通过request对象获取请求转发器对象 forward(ServletRequest request,ServletResponse response) 使用request对象进行转发 /*Demo6*/ System.out.println("Demo6666被访问了"); //转发到Demo7资源 RequestDispatcher requestDemo7 = request.getRequestDispatcher("requestDemo7"); requestDemo7.forward(request,response); /*Demo7*/ System.out.println("Demo7777被访问了"); /*写法2*/ request.getRequestDispatcher("requestDemo7").forward(request,response);
- 特点:
- 浏览器地址栏路径不会变
- 只能转发到当前服务器内部资源中
- 转发是一次请求
- 特点:
共享数据
-
域对象:一个有作用范围的对象,可以在范围内共享数据
-
request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
-
方法:
-
方法 说明 void setAttribute(String name,Object obj) 存储数据 Object getAttitude(String name) 通过键获取值 void removeAttribute(String name) 通过键移除键值对 /*Demo6*/ System.out.println("Demo6666被访问了"); //存储数据到request域中 request.setAttribute("msg","hello"); //转发到Demo7资源 request.getRequestDispatcher("requestDemo7").forward(request,response); /*Demo7*/ //获取request域的值 Object msg = request.getAttribute("msg"); System.out.println(msg); System.out.println("Demo7777被访问了");
-
获取ServletContext对象
方法 | 说明 |
---|---|
ServletContext getServletContext() | 获取ServletContext对象 |
//获取servletContext对象
ServletContext servletContext = request.getServletContext();
System.out.println(servletContext);
案例
需求
用户登录案例:
- 编写login.html登录页面
- username & password 两个输入框
- 使用数据库,操作mysql的数据表
- 使用jdbc连接数据库
- 登录成功跳转到SuccessServlet展示:登陆成功!用户名:欢迎您
- 登录失败跳转到FailServlet展示:登录失败,用户名或密码错误
分析
文件提取
链接:https://pan.baidu.com/s/1ApJyMdsI8sqJU6bQRXAeJw
提取码:1011
Response – 响应
5.1、HTTP协议
响应消息:服务器端发送给客户端的数据
数据格式
响应行
-
组成
-
协议/版本 响应状态码 状态码描述
-
响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态
-
状态码都是3位数字
-
分类:
-
状态码(百) 说明 1xx 服务器接收客户端消息,但没有接收完成,等待一段时间后,发送1xx多的状态码。 2xx 成功。代表:200 3xx 重定向。代表:302(重定向),304(访问缓存) 4xx 客户端错误。代表: 404(请求路径没有对应的资源) 405:请求方式没有对应的doxxx方法 5xx 服务器端错误。代表:500(服务器内部出现异常) -
-
-
-
响应头
-
格式:头名称:值
-
常见的响应头
-
响应头 说明 Content - Type: 服务器告诉客户端本次响应体数据格式以及编码格式 text/html;charset=UTF-8 Content - disposition: 服务器告诉客户端以什么格式打开响应体数据 in - line:默认值,在当前页面内打开 attachment;filename=xxx:以附件形式打开响应体。文件下载
-
响应空行
响应体
- 传输的消息
5.2、Response对象
功能-设置响应消息
设置响应行
-
格式:HTTP/1.1 200 OK
-
方法 说明 setStatus(int sc) 设置状态码
设置响应头
-
方法 说明 setHeader(String name,String value) 设置响应头
设置响应体
-
使用步骤:
-
获取输出流
-
方法 说明 PrintWriter getWriter() 字符输出流 ServletOutputStream getOutputSteam() 字节输出流
-
-
使用输出流,将数据输出到浏览器
-
5.3、完成重定向
-
资源跳转的方式
-
方法 说明 sendRedirect(String value) 简单的重定向方法 -
//index System.out.println("index"); //访问/ResponseIndex的时候自动跳转到/ResponseIndex2资源 //1.设置状态码为302 response.setStatus(302); //2.设置响应头location response.setHeader("location","ResponseIndex2"); //index2 System.out.println("index2");
//简单的重定向方法 response.sendRedirect("ResponseIndex2"); //可访问其他站点 response.sendRedirect("http://www.itcast.cn");
重定向的特点:redirct
- 地址栏发生变化
- 重定向可以访问其他站点(服务器)的资源、
- 重定向是两次请求,不能使用request对象来共享数据
- 他的对比项是"转发"
转发的特点:forward
-
转发地址栏路径不变
-
转发只能访问当前服务器下的资源
-
转发是一次请求,可以使用request对象来共享数据
-
forward 和 redirct 区别
路径写法
相对路径:通过相对路径不可以确定唯一资源
-
如:./index.html
-
不以 / 开头,以 . 开头的路径称之为相对路径
-
规则:找到访问当前资源和目标资源之间的相对位置关系
-
方法 说明 / 根目录 ./ 当前目录 …/ 上一级目录 -
绝对路径:通过绝对路径可以确定唯一资源
方法 | 说明 |
---|---|
String n = request.getContextPath() | 动态获取虚拟目录 |
response.sendRedirect(n+“ResponseIndex2”) | 重定向方法 |
- 如:http://localhost:8080/javaWeb_Response_Test_war_exploded/ResponseIndex2
- 以 / 开头的路径称之为绝对路径
- 规则:判断定义的路径是给谁用的?判断请求将来从那发出
- 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
- 虚拟目录动态获取
- 给服务器使用:不需要加虚拟目录
- 转发路径
- 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
5.4、服务器输出字符数据到浏览器
-
方法 说明 pw = getWriter() 获取字符输出流 pw.write(“ hello response
”)输出数据 -
中文乱码问题解决
-
-
//获取流对象之前,设置流的默认编码:IOS-8859-1 设置为:GBK response.setCharacterEncoding("GBK"); //告诉浏览器,服务器发送的消息体数据的编码,建议浏览器使用该编码解码 response.setHeader("content-type","text/html;charset=utf-8"); //简单的形式,设置编码 response.setContentType("text/html;charset=utf-8");
-
5.5、服务器输出字节数据到浏览器
方法 | 说明 |
---|---|
sos = response.getOutputStream() | 获取字节输出流 |
sos.write(“htllo”.getBytes(“utf-8”)) | 输出数据 |
获取字节对象之前,设置字节的默认编码:IOS-8859-1 设置为:GBK
response.setContentType("text/html;charset=utf-8");
//获取字节输出流
ServletOutputStream sos = response.getOutputStream();
//输出
sos.write("<h1>你好,baga</h1>".getBytes("utf-8"));
5.6、验证码
-
本质:图片
-
目的:防止恶意表单注册
-
方法 说明 width=100 验证码画布的宽 height=50 验证码画布的高 bImg = BufferedImage(width,height,BufferedImage.TYPE_3BYTE_BGR); 创建验证码图片对象 g = bImg.getGraphics() 画笔对象 颜色获取 g.setColor(Color.pink) 设置画笔颜色 填充背景色 g.fillRect(0,0,width,height) 填充画布颜色 画边框 g.drawRect(0,0,width-1,height-1) 设置边框颜色 验证码 g.drawString(字符,x坐标,y坐标) 写入验证码 干扰线 g.drawLine(x1,x2,x3,x4) 设置干扰线 输出 ImageIO.write(bImg,“jpg”,response.getOutputStream()) 将图片输出到页面展示 -
int width = 100; int height = 50; //1.创建一对象,在内存中图片(验证码图片对象) BufferedImage bImg = new BufferedImage(width,height,BufferedImage.TYPE_3BYTE_BGR); //2.美化图片 //2.1、填充背景色 Graphics g = bImg.getGraphics();//画笔对象 g.setColor(Color.pink); //设置画笔颜色 g.fillRect(0,0,width,height); //2.2、画边框 g.setColor(Color.BLUE); g.drawRect(0,0,width-1,height-1); Random ram = new Random(); //随机验证码 for (int i = 1; i <= 4; i++) { String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; //生成随机角标 int index = ram.nextInt(str.length()); //获取字符 char ch = str.charAt(index);//随机字符 //2.3、写入验证码 g.drawString(ch+"",width/5*i,25); } //2.4、画干扰线 g.setColor(Color.GREEN); //随机生成坐标点 for (int i = 0; i < 4; i++) { int x1 = ram.nextInt(width); int x2 = ram.nextInt(width); int y1 = ram.nextInt(height); int y2 = ram.nextInt(height); g.drawLine(x1,x2,y1,y2); } //3.将图片输出到页面展示 ImageIO.write(bImg,"jpg",response.getOutputStream());
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <img src="CheckCodeServlet" alt=""> <a href="">看不清换一张</a> </body> <script> /* * 分析: * 点击链接或者图片,需要换一张 * 1.给图片和链接绑定单击事件 * 2.重新设置图片的src属性值 * */ window.onload = function () { let img = document.getElementsByTagName("img")[0]; img.onclick = function () { let date = new Date().getTime(); //加时间戳 img.src = "CheckCodeServlet?" + date } let a = document.getElementsByTagName("a")[0]; a.onclick = function () { let date = new Date().getTime(); img.src = "CheckCodeServlet?" + date } } </script> </html>
-
5.7、ServletContext
-
概念:代表整个web应用,可以和程序的容器(服务器)来通信
-
方法 说明 request.getServletContext() 通过request对象获取 this.getServletContext() 通过HttpServlet获取 //ServletContext对象获取 //1.通过request对象获取 ServletContext servletContext = request.getServletContext(); //2.通过HttpServlet获取 ServletContext servletContext1 = this.getServletContext(); System.out.println(servletContext); System.out.println(servletContext1); System.out.println(servletContext==servletContext1);
获取MIME类型
- MIME类型:在互联网通信过程中定义的一种文件数据类型
- 格式: 大类型/小类型 text/html image/jpg
方法 | 说明 |
---|---|
String getMimeType(String file) | 获取 |
//ServletContext功能
//MIME类型:在互联网通信过程中定义的一种文件数据类型
//2.通过HttpServlet获取
ServletContext servletContext = this.getServletContext();
//3.定义文件名
String fileName = "a.jpg";
//4.获取MIME类型
String mimeType = servletContext.getMimeType(fileName);
System.out.println(mimeType);
域对象:共享数据
方法 | 说明 |
---|---|
setAttribute(String name,Object value) | 设置共享数据 |
getAttribute(String name) | 获取共享数据 |
removeAttribute(String name) | 删除共享数据 |
- ServletContext对象范围:所有用户所有请求的数据
demo3
//2.通过HttpServlet获取
ServletContext servletContext = this.getServletContext();
//设置数据
servletContext.setAttribute("msg","hello");
demo4
//2.通过HttpServlet获取
ServletContext servletContext = this.getServletContext();
//获取数据
Object msg = servletContext.getAttribute("msg");
System.out.println(msg);
分别访问后:
获取文件的真实(服务器)路径
方法 | 说明 |
---|---|
String getRealpath(String path) | 获取文件路径 |
//通过HttpServlet获取
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/b.txt");//web目录下资源访问
System.out.println(realPath);
//File file = new File(realPath);
String c = servletContext.getRealPath("/WEB-INF/c.txt");//web-inf目录下的资源访问
System.out.println(c);
String a = servletContext.getRealPath("/WEB-INF/classes/a.txt");//src路径下的资源访问
System.out.println(a);
文件下载
概念需求
- 超链接指向的资源如果能够被浏览器解析,则在浏览器中国展示,如果不能解析,则弹出下载提示框
- 任何资源都必须淡出下载提示框 – 实现
- 使用响应头设置资源的打开方式:
- 步骤:
- 定义页面,编辑超链接href属性,指向Servlet,传递资源的名称
- 定义Servlet
- 获取文件名称
- 使用字节输入流加载文件进内存
- 指定response的响应头:content-disposition:attachment;filename=xxx
- 将数据写出到response输出流
代码
//1.获取请求参数,文件名称
String filename = request.getParameter("filename");
//2.使用字节输入流加载文件进内存
//2.1、找到文件服务器路径
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/img/"+filename);
//2.3、用字节流关联
FileInputStream file = new FileInputStream(realPath);
//3.设置response响应头
//3.1设置response响应头类型:content-type
//获取文件的MIME类型
String mimeType = servletContext.getMimeType(filename);
response.setHeader("content-type",mimeType);
//3.2设置响应头打开方式:content-disposition
response.setHeader("content-disposition","attachment;filename="+filename);
//4.将输入流的数据写出到输出流中
ServletOutputStream outputStream = response.getOutputStream();
byte[] buff = new byte[1024 * 8];
int len = 0;
while ((file.read(buff)!=-1)){
outputStream.write(buff,0,len);
}
file.close();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/javaWeb_Response_Test_war_exploded/img/1.jpeg">图片1</a>
<a href="/javaWeb_Response_Test_war_exploded/video/1.mp4">视频1</a>
<hr>
<a href="/javaWeb_Response_Test_war_exploded/downLoadServlet?filename=1.jpeg">图片1</a>
<a href="/javaWeb_Response_Test_war_exploded/downLoadServlet?filename=2.webp">图片2</a>
<a href="/javaWeb_Response_Test_war_exploded/downLoadServlet?filename=1.mp4">视频</a>
</body>
</html>
中文文件名的解决
解决思路:
- 获取客户端使用的浏览器版本信息
- 根据不同的版本信息,设置filename的方式不同
//解决中文文件乱码问题
//1.获取User-agent请求头
String agent = request.getHeader("user-agent");
//2.工具类方法编码文件名即可
filename= DownLoadUtils.getFileName(agent, filename);
//1.获取请求参数,文件名称
String filename = request.getParameter("filename");
//2.使用字节输入流加载文件进内存
//2.1、找到文件服务器路径
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/img/"+filename);
System.out.println("===>>"+realPath);
//2.3、用字节流关联
FileInputStream file = new FileInputStream(realPath);
//3.设置response响应头
//3.1设置response响应头类型:content-type
//获取文件的MIME类型
String mimeType = servletContext.getMimeType(filename);
response.setHeader("content-type",mimeType);
//3.2设置响应头打开方式:content-disposition
//解决中文文件乱码问题
//1.获取User-agent请求头
String agent = request.getHeader("user-agent");
//2.工具类方法编码文件名即可
filename= DownLoadUtils.getFileName(agent, filename);
response.setHeader("content-disposition","attachment;filename="+filename);
//4.将输入流的数据写出到输出流中
ServletOutputStream outputStream = response.getOutputStream();
byte[] buff = new byte[1024 * 8];
int len = 0;
while (((len = file.read(buff))!=-1)){
outputStream.write(buff,0,len);
outputStream.flush();
}
outputStream.close();
file.close();
DownLoadServlet类
package utils;
import sun.misc.BASE64Encoder;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class DownLoadUtils {
public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}
Cookie会话 – 客户端会话技术
-
一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开位置
-
在一次会话的范围内的多次请求间,共享数据
-
概念:客户端会话技术,将数据保存到客户端
6.1、使用
方法 | 说明 |
---|---|
new Cookie(String name,String value) | 创建Cookie对象,绑定数据 |
response.addCookie(Cookie cookie) | 发送Cookie对象 |
Cookie[] request.getCookies() | 获取Cookie,拿到数据 |
/*demo1*/
//1.创建Cookie对象
Cookie cookie = new Cookie("msg","hello");
//2.发送Cookie
response.addCookie(cookie);
Cookie遍历
/*demo2*/
//3.获取Cookie
Cookie[] cookies = request.getCookies();
//获取数据,遍历cookies
if (cookies!=null){
for (Cookie c : cookies){
String name = c.getName();
String value = c.getValue();
System.out.println(name+": "+value);
}
}
实现原理
- 基于响应头set-Cookie和请求头cookie实现
6.2、发送多个Cookie
//1.创建Cookie对象
Cookie c1 = new Cookie("msg","hello");
Cookie c2 = new Cookie("name","word");
Cookie c3 = new Cookie("live","你听得到");
//2.发送Cookie
response.addCookie(c1);
response.addCookie(c2);
response.addCookie(c3);
6.3、Cookie存活的时间
-
默认情况下,当浏览器关闭后,Cookie数据被销毁
-
以此可知,Cookie存在浏览器内存里面
持久化存储
方法 说明 setMaxAge(int seconds) 持久化存储 参数 单位/s: 正数 将Cookie数据写到硬盘的文件中。持久化储存。Cookie存活时间 负数 默认值 零 删除cookie信息 //1.创建Cookie对象 Cookie c = new Cookie("live","setMaxAge"); //2.设置cookie的存活时间 c.setMaxAge(30);//将cookie持久化到硬盘,30秒后自动删除cookie文件 c.setMaxAge(-1); c.setMaxAge(0); //3.发送Cookie response.addCookie(c);
6.4、Cookie存储中文
tomcat8之后,cookie支持中文数据
tomcat8之前,cookie不支持中文数据,需要将中文数据转码:
一般采用URL编码(%E3)
//URL编码
date = URLEncoder.encode(date,"utf-8");
//URL解码
value = URLEncoder.encode(value,"utf-8");
6.5、Cookieo共享
-
默认情况下cookie不能共享
-
方法 说明 setPath(String path) 设置cookie的获取范围。默认情况下设置当前的虚拟目录 如果要共享,要将path值设置为 “/” //1.创建Cookie对象 Cookie c = new Cookie("live","你听得到"); //设置path,让当前服务器下部署的所有项目共享cookie信息 c.setPath("/"); //3.发送Cookie response.addCookie(c);
-
不同的tomcat服务器间cookie共享问题
-
方法 说明 setDomain(String path) 如果设置一级域名相同,那么多个服务器之间cookie可以共享 举例 setDomain(“.baidu.com”) 那么tieba.baidu.com和news.baidu.com中cookie可以共享
6.6、Cookie的特点和作用
- cookie存储数据在客户端浏览器
- 浏览器对于单个cookie的大小有限制(4KB),一级对同一个域名下的总cookie数量也有限制(2个)
作用:
- cookie一般用于存储少量的不太敏感的数据
- 在不登录的情况下完成服务器符客户端的身份识别
案例
记住上一次访问时间
需求:
- 访问一个Servlet,如果是第一次访问,则提示:你好欢迎首次访问网页
- 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
分析:
- 要采用Cookie来完成
- 服务器中的Servlet判断是否有一个名为lastTime的cookie
- 有:不是第一次访问
- 响应数据:欢迎回来,您上次访问时间为:lastTime时间
- 写回Cookie:lastTime=当前时间
- 没有:是第一次访问
- 响应数据:您好,欢迎您首次访问
- 写回Cookie:lastTime=当前时间
- 有:不是第一次访问
代码
package com.example.javaWeb_CookieServlet;
/**
* @author 玫瑰到了花期
* @data 2022/3/29 17:57
* @love 又偷偷看你了
* @V: CBWR-K
*/
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
@WebServlet("/ServletCookieIndex")
public class ServletCookieIndex extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
boolean isNaN = true;
//设置中文乱码问题
response.setContentType("text/html;charset=utf-8");
//获取所有的cookie
Cookie[] cookies = request.getCookies();
if (cookies!=null){
for (Cookie c : cookies){
String name = c.getName();
if ("listTime".equals(name)){
//有该cookie
isNaN = false;
//设置cookie的value
//获取当前时间,重新定义cookie的值,重新发送cookie
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss");
String str_date = sdf.format(date);
c.setValue(str_date);
//设置cookie一个月的存活时间
c.setMaxAge(60*60*24*30);
response.addCookie(c);
//响应数据
String value = c.getValue();
response.getWriter().write("欢迎回来,上次访问时间:"+value);
break;
}
}
}
if (cookies!=null|| isNaN == true){
//没有,第一次访问
//获取时间
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss");
String str_date = sdf.format(date);
//创建cookie,存储数据
Cookie cookie = new Cookie("listTime",str_date);
//设置cookie的存活时间
cookie.setMaxAge(60*60*24*30);
response.addCookie(cookie);
//响应数据
response.getWriter().write("你好,欢迎首次访问");
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
JSP
7.1、概念
-
Java Server Pages : java服务器端页面
-
可以理解为一个特殊的页面
-
其中既可以直接定义html标签
-
还可以定义java代码
-
-
用于简化书写
7.2、原理
- jsp本质上就是个servlet
7.3、JSP脚本
JSP定义JAVA代码的方式
方法 | 说明 |
---|---|
<% java代码 %> | 在%内写入java代码,也称之为jsp的脚本定义的java代码,在service方法中。 |
service方法中可以定义什么,该脚本就可以定义什么 | |
<%! java代码 %> | 第二种脚本,定义的java代码,在jsp转换后的java类的成员位置 |
<%= java代码 %> | 第三种脚本,定义的java代码,会输出到页面上 |
输出语句中可以定义什么,该脚本就可以定义什么 |
7.4、JSP内置对象
说明
- 在jsp页面中不需要获取和创建,可以直接使用的对象
关于jsp无法使用内置对象的方法
- https://blog.youkuaiyun.com/weixin_43383406/article/details/94203696
JSP一共有9个内置对象
对象 | 说明 |
---|---|
request | 请求 |
response | 响应 |
out | 字符输出流对象,可以将数据输出到页面上。 |
和response.getWriter()类似 |
out和response.getWriter()的区别
改造Cookie案例
<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %><%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2022/3/31
Time: 8:47
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>
<%
boolean isNaN = true;
//设置中文乱码问题
response.setContentType("text/html;charset=utf-8");
//获取所有的cookie
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie c : cookies) {
String name = c.getName();
if ("listTime".equals(name)) {
//有该cookie
isNaN = false;
//设置cookie的value
//获取当前时间,重新定义cookie的值,重新发送cookie
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss");
String str_date = sdf.format(date);
c.setValue(str_date);
//设置cookie一个月的存活时间
c.setMaxAge(60 * 60 * 24 * 30);
response.addCookie(c);
//响应数据
String value = c.getValue();
%>
<h1>"欢迎回来,上次访问时间:"<%=value%>
</h1>
<%
break;
}
}
}
if (cookies != null && isNaN) {
//没有,第一次访问
//获取时间
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss");
String str_date = sdf.format(date);
//创建cookie,存储数据
Cookie cookie = new Cookie("listTime", str_date);
//设置cookie的存活时间
cookie.setMaxAge(60 * 60 * 24 * 30);
response.addCookie(cookie);
//响应数据
%>
<h1>"你好,欢迎首次访问"</h1>
<%
}
%>
</body>
</html>
Session会话 – 服务器
8.1、概念
- 服务器段会话技术,再一次会话的多次请求间共享数据,将数据保存在服务器段的对象中。Httpsession
8.2、HttpSession对象
方法 | 说明 |
---|---|
request.getSession() | 获取HttpSession对象 |
使用 | |
void setAttribute(String name,Object value) | 存储数据 |
Object getAttribute(String name) | 获取session |
void removeAttribute(String name) | 删除数据 |
8.3、原理
- Session的实现是依赖于Cookie的
客户端关闭,服务器不关闭,两次获取session是同一个么?
-
默认情况下,不是
-
客户端关闭后,session也能相同
-
如果需要相同,可以创建Cookie,键位JSESSIONID,设置最大存活时间,让cookie持久化存储
-
//1.获取session HttpSession session = request.getSession(); System.out.println(session); //期望客户端关闭后,session也能相同 Cookie c = new Cookie("JSESSIONID",session.getId()); //持久化储存 c.setMaxAge(60*60); //发送cookie response.addCookie(c);
-
客户端不关闭,服务器关闭后么,两次获取的session是同一个么?
-
不是同一个
-
-
session地址不一样,但要确保数据不丢失
-
session的钝化系列化
- 在服务器正常关闭之前,将session对象系列化到硬盘上
-
session的活化反序列化
- 在服务器启动后,将session文件转化为内存中的session对象即可
-
找到本项目的out包下的文件
-
解压并修改后缀名为.war
-
将war包复制到tomcat下的webapps下
-
关闭之前的服务器
-
手动开启tomcat下的启动服务器文件
-
打开浏览器,访问session文件
session什么时候被销毁
-
服务器关闭
-
session对象调用
-
方法 说明 invalidate() 自销毁
-
-
session默认失效时间
- 30分钟,选择性配置修改
8.4、session的特点
- session用于存储一次会话的多次请求的数据
- 存在服务器端
- session可以存储任意类型,任意大小的类型
session与Cookie的区别
- session存储数据在服务器端,Cookie在客户端
- session没有数据大小限制,cookie有
- session数据安全,cookie相对于不安全
案例:验证码
案例需求:
- 访问带有验证码的登陆页面Login.jsp
- 用户输入用户名,密码以及验证码
- 如果用户名和密码输入错误,跳转登陆页面,提示:用户名或密码错误
- 如果验证码输入有误,跳转登陆页面,提示:验证码输入错误
- 如果全部输入正确,则跳转到主页success.jsp,显示:用户名:欢迎您
分析
代码
LoginServlet
package sessionServlet.Servlet;
/**
* @author 玫瑰到了花期
* @data 2022/4/1 16:17
* @love 又偷偷看你了
* @V: CBWR-K
*/
import sessionServlet.UserDao.Dao.UserDao;
import sessionServlet.UserDao.Dao.UserDaoImpl;
import sessionServlet.UserDao.User;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
UserDao userDao = new UserDaoImpl();
boolean isCo = false;
//从浏览器获取参数
String userName = request.getParameter("userName");
String password = request.getParameter("password");
String verification = request.getParameter("verification");
//获取验证码
HttpSession session = request.getSession();
String yzm = (String) session.getAttribute("yzm");
//删除验证码,防止后退后验证码被复用
session.removeAttribute("yzm");
System.out.println(yzm);
System.out.println(verification);
//判断验证码是否正确
User login = userDao.login(new User(userName, password));
if (yzm!=null&&yzm.equalsIgnoreCase(verification)){
if (login!=null){
//登陆成功
//储存信息,用户信息
session.setAttribute("userName",userName);
//重定向到success.jsp
response.sendRedirect(request.getContextPath()+"success.jsp");
}else {
//登陆失败
//储存信息到request
request.setAttribute("login_error","用户名或密码错误");
//转发到登陆页面
request.getRequestDispatcher("index.jsp").forward(request,response);
}
}else {
//验证码不一致
//储存信息到request
request.setAttribute("cc_error","验证码错误");
//转发到登陆页面
request.getRequestDispatcher("index.jsp").forward(request,response);
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
verifyServlet
package sessionServlet.Servlet;
/**
* @author 玫瑰到了花期
* @data 2022/4/1 14:22
* @love 又偷偷看你了
* @V: CBWR-K
*/
import javax.imageio.ImageIO;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
@WebServlet("/verifyServlet")
public class verifyServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//验证码制作
int width = 100;
int height=50;
BufferedImage bImg = new BufferedImage(width,height,BufferedImage.TYPE_3BYTE_BGR);
Graphics g = bImg.getGraphics();
Graphics g1 = bImg.getGraphics();
g.setColor(Color.pink);
//设置背景颜色
g.fillRect(0,0,width,height);
g.setColor(Color.black);
//设置边框线
g.drawRect(0,0,width-1,height-1);
//生成验证码
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
String str_verification = "";
for (int i = 0; i < 4; i++) {
Random r = new Random();
int index = r.nextInt(str.length());
char c = str.charAt(index);
//储存验证码
str_verification += c;
//写入验证码
g.drawString(String.valueOf(c),width/4*i,25);
//干扰线
g1.setColor(Color.GREEN);
int x1 = r.nextInt(width);
int x2 = r.nextInt(width);
int y1 = r.nextInt(height);
int y2 = r.nextInt(height);
g1.drawLine(x1,x2,y1,y2);
}
//验证码图片输出至浏览器
ImageIO.write(bImg,"jpg",response.getOutputStream());
System.out.println("验证码:"+str_verification);
HttpSession session = request.getSession();
session.setAttribute("yzm",str_verification);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
index.jsp
<%@ page import="java.awt.*" %>
<%@ page import="java.util.Random" %>
<%@ page import="javax.imageio.ImageIO" %>
<%@ page import="java.awt.image.BufferedImage" %><%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2022/4/1
Time: 14:21
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<style>
span {
color: red;
}
</style>
</head>
<body>
<script type="text/javascript">
window.onload = function () {
document.getElementById("img").src = "/verifyServlet";
document.getElementById("img").onclick = function () {
this.src = "/verifyServlet?time=" + new Date().getTime();
document.getElementsByName("verification")[0].value = "";
}
}
</script>
<form action="/LoginServlet" method="post">
用户名:<input type="text" placeholder="输入用户名" name="userName"><span><%=request.getAttribute("login_error")==null? "":request.getAttribute("login_error")%></span><br>
密码:<input type="password" placeholder="输入密码" name="password"><span><%=request.getAttribute("login_error")==null? "":request.getAttribute("login_error")%></span><br>
验证码:<input type="text" placeholder="输入验证码" name="verification"><span><%=request.getAttribute("cc_error")==null? "":request.getAttribute("cc_error")%></span><br>
<img src="" alt="" id="img" οnclick="">
<input type="submit" value="登陆">
</form>
</body>
</html>
seccexx.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2022/4/1
Time: 17:52
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>
<h1><%=request.getSession().getAttribute("userName")%>,登陆成功</h1>
</body>
</html>
JSP其余内容
9.1、指令
-
作用:用于配置JSP页面,导入资源文件
-
方法 说明 <%@指令名称 属性名1=属性值1 …%> 指令基本定义格式
page – 配置JSP页面的
方法 | 说明 |
---|---|
contentType | 等同于response.setContentType() |
1 | 设置响应体的mime类型以及字符集 |
2 | 设置当前jsp页面的编码(高级IDE才能生效如果使用低级工具需要设置pageEncoding属性设置当前页面的字符集编码) |
import | 导包 |
errorPage | 当前页面发生异常后,会自动跳转到指定的错误页面 |
isErrorPage | 标识当前页面是否是错误页面 |
true:是,可以使用内置对象exception | |
false:否,默认值,不可以使用内置对象exception |
isErrorPage
<%@ page contentType="text/html;charset=UTF-8" errorPage="500.jsp" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%
int i = 3/0;
%>
</body>
</html>
||||||||||||||||||||||||||||||||||||||||||
<%@ page contentType="text/html;charset=UTF-8" isErrorPage="true" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>服务器正忙....</h1>
<%
System.out.println(exception.getMessage());
%>
</body>
</html>
include – 页面包含的,导入页面的资源文件
方法 | 说明 |
---|---|
file | 导入页面 |
taglib – 导入资源
导入依赖
<!--jstl依赖-->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
方法 | 说明 |
---|---|
prefix | 前缀:自定义的 |
uri | 对应标签名,资源路径 |
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
9.2、注释
html注释
<!-- -->:只能注释html代码片段
jsp注释
<%-- --%>:可以注释所有
9.2、内置对象
-
在jsp页面中不需要创建,直接使用的对象
-
一共有9个‘
-
变量名 真实类型 作用 域对象 pageContext PageContext 当前页面共享数据,还可以获取其他八个内置对象 request HttpServletRequest 一次请求访问的多个资源(转发) session HttpSession 一次会话的多个请求间 application ServletContext 所有用户间共享数据 响应对象 response HttpServletResponse 响应对象 page Object 当前页面(Servlet)的对象 this out JspWriter 输出对象,数据输出到页面上 配置对象 config ServletConfig Servlet的配置对象 exception Throwable 异常对象
-
MVC开发模式
jsp演变历史
- 早期只有servlet,只能使用response输出标签数据,非常麻烦
- 后来有了jsp,简化了Servlet的开发
- 如果过度使用jsp,在jsp中即写大量的java代码,又写html标签,会造成难于维护难于分工协作
- 再后来,java的web开发,借鉴Mvc模式,使得程序的设计更加合理性
MVC
-
M:Mdel,模型 – javaBean
- 完成具体的业务操作,如查询数据库,封装对象
-
V:View,视图 – JSP
- 展示数据
-
C:Controller:控制器 – Servlet
- 获取用户的输入
- 调用模型
- 将数据交给视图进行展示
优点
- 耦合性低,方便维护,利于分工协作
- 重用性高
缺点
- 使得项目架构变得复杂,对开发人员要求高
EL表达式
概念
- Expression Language表达式语言
- 替换和简化jsp页面中java代码的编写
使用
jsp中是默认支持el表达式的
-
语法 ${表达式} 防止jsp默认解析el表达式 配置jsp中page指令:isELIgnored=“true” 忽略所有的el表达式 ${表达式} 忽略单个el表达式 替换和简化jsp页面中Java代码的编写
运算
运算符 | |
---|---|
+ - * /(div) %(mod) | 算术运算符 |
> < >= <= == != | 比较运算符 |
&&(and) ||(or) !(not) | 逻辑运算符 |
empty | 空运算符 |
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${1>3}
\${1>3}
<hr>
<h3>算术运算符</h3>
${3+4}<br>
${3/4}<br>
${3 div 4}<br>
${3%4}<br>
${3 mod 4}<br>
<hr>
<h3>比较运算符</h3>
${1==1}
${1==2}
<hr>
<h3>逻辑运算符</h3>
${1>2 && 1<2}
${1>2 and 1<2}
${1>2 || 1<2}
${1>2 or 1<2}
${!(1>2 and 1<2)}
${not(1>2 and 1<2)}
<h3>空运算符</h3>
<p>判断字符串、集合、对象、数组是否为Null并且长度为0</p>
${empty list}
</body>
</html>
获取值
- el表达式只能从域对象中获取值
语法 | |
---|---|
方式一: | |
${域名城.键名} | 从指定域中获取指定键的值 |
域名城 | pageScope – > pageContext |
requestScope --> request | |
sessionScope --> session | |
applicationScope --> application(ServletContext) | |
方式二: | |
${键名} | 表示依次从最小的域中查找是否有该键对应的值,直到找到为止 |
方式一 举例:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>el获取域中的数据</title>
</head>
<body>
<%
request.setAttribute("name","胡子洋");
session.setAttribute("age","18");
%>
${requestScope.name}
${sessionScope.age}
</body>
</html>
方式二 举例:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>el获取域中的数据</title>
</head>
<body>
<%
request.setAttribute("name","胡子洋");
session.setAttribute("name","乌鸦做胃镜");
%>
${name} <!--胡子洋-->
</body>
</html>
获取对象、LIst集合、Map集合的值
对象
语法 | |
---|---|
${域名城.键名.属性名} | 本质上会去调用对象的getter方法 |
package ytzl;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author 玫瑰到了花期
* @data 2022/4/4 13:48
* @love 又偷偷看你了
* @V: CBWR-K
*/
public class User {
private String name;
private int age;
private Date time;
/**
* 逻辑视图
* @return
* */
public String getBitStr(){
if (time!=null){
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return simpleDateFormat.format(time);
}else {
return "";
}
}
public User() {
}
public User(String name, int age, Date time) {
this.name = name;
this.age = age;
this.time = time;
}
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;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
}
<%@ page import="java.util.Date" %>
<%@ page import="ytzl.User" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>el获取对象数据</title>
</head>
<body>
<%
User user = new User();
user.setName("周杰伦");
user.setAge(18);
user.setTime(new Date());
request.setAttribute("u",user);
%>
<h3>获取对象中的值</h3>
${requestScope.u}
<%--
通过的是对象的属性来获取
*setter getter方法,去掉set或get然后再将剩余部分,首字母变小写
*setName -->Name -->name
--%>
${requestScope.u.name}<br>
${u.age}<br>
${u.time}<br>
${u.time.month+1}<br>
${u.bitStr}
</body>
</html>
集合
语法 | |
---|---|
list | |
${域名城.键名[索引]} | |
map | |
${域名城.键名.key名称} | |
${域名城.键名[“key名称”]} |
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="ytzl.User" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>el获取集合</title>
</head>
<body>
<%
User user = new User();
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(user);
user.setName("周杰伦");
request.setAttribute("list",list);
%>
<h3>获取list集合</h3>
${list}<br>
${list[0]}<br>
${list[1]}<br>
${list[2].name}
</body>
</html>
空运算符
- 用于判断字符串、集合、数据对象是否为Null或者长度是否为0
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>空运算符</title>
</head>
<body>
<%
String str = "123456";
String str1 = "";
request.setAttribute("str",str);
request.setAttribute("str1",str1);
List list = new ArrayList();
request.setAttribute("list",list);
%>
<%--${empty str} 判断字符串、集合、数组对象是否为null,或者长度为0--%>
${empty str}
<%--${not empty str1} 判断字符串、集合、数组对象是否不为null,并且长度>0--%>
${not empty str1}
${not empty list}
</body>
</html>
隐式对象
-
el表达式中有11个隐式对象
-
对象 说明 pageContext 获取jsp其他8个内置对象 ${pageContext.request.contextPath} 动态获取虚拟目录
JSTL标签
概念
-
JavaServer Pages Tag Library JSP标准标签库
- 是由Apache组织提供的开源的免费的jsp标签
-
用于简化和替换jsp页面的java代码
使用
- 导入jstl相关jar包
- 引入标签库:taglib指令:<%@ taglib%>\
- 使用标签
常用的JSTL标签
标签 | 说明 |
---|---|
if | 相当于java代码的if语句 |
test | 必须属性,接收boolean表达式,如果为true则显示标签体内容 |
<c:if test=“${not empty list}”> | |
c:if标签没有else,想要else情况,则可以再定义一个c:if标签 | |
choose | 相当于java代码的switch语句 |
when | 相当于case,必须有test属性 |
otherwise | 相当于default |
foreach | 相当于java代码的for语句 |
普通for循环 | |
begin | 开始值 |
end | 结束值 |
var | 临时变量 |
step | 自增控制 |
varStatus | 循环状态对象 |
index: 当前下标,从0开始 | |
count: 循环次数,从1开始 | |
<c:forEach begin=“0” end=“9” var=“i” step=“1” varStatus=“s”> | |
遍历容器 | |
items | 容器对象 |
var | 容器中元素的临时变量 |
varStatus | 循环状态对象 |
index: 当前下标,从0开始 | |
count: 循环次数,从1开始 | |
<c:forEach items=“${list}” var=“number” varStatus=“s”> |
if
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<html>
<head>
<title>if</title>
</head>
<body>
<%--
c:if标签
1.属性:
test 必须属性,接受boolean表达式
如果为true则显示标签体内容
如果为false则不显示标签体内容
一般情况下,test属性值会结合el表达式一起使用
2.注意:
c:if标签没有else,想要else情况,则可以再定义一个c:if标签
--%>
<%--判断一个集合是否为空,不为空的话输出--%>
<%
List list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
request.setAttribute("list",list);
request.setAttribute("number",3);
%>
<c:if test="${not empty list}">
<h1>遍历集合</h1>
</c:if>
<br>
<c:if test="${number/2!=3}">
<h1>number/2!=3</h1>
</c:if>
<br>
</body>
</html>
choose
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<html>
<head>
<title>choose</title>
</head>
<body>
<%
request.setAttribute("number",2);
%>
<c:choose>
<c:when test="${number==1}">星期一</c:when>
<c:when test="${number==2}">星期二</c:when>
<c:when test="${number==3}">星期三</c:when>
<c:otherwise>我是傻逼</c:otherwise>
</c:choose>
</body>
</html>
foreach
<%@ page import="java.util.List" %>
<%@ 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>foreach</title>
</head>
<body>
<%
List list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
request.setAttribute("list",list);
%>
<c:forEach begin="0" end="9" var="i" step="1" varStatus="s">
<h${i+1}>周杰伦</h${i+1}>
<h3>${s.index}<h3>
<h4>${s.count}<h4>
</c:forEach>
<c:forEach items="${list}" var="number" varStatus="s">
${s.index} ${s.count} ${number}
</c:forEach>
</body>
</html>
练习
- 在request与中有一个User对象的List集合。
- 需要使用jstl+el将list集合数据展示到jsp页面的表格table中。
package ytzl;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author 玫瑰到了花期
* @data 2022/4/4 13:48
* @love 又偷偷看你了
* @V: CBWR-K
*/
public class User {
private String name;
private int age;
private Date time;
/**
* 逻辑视图
* @return
* */
public String getBitStr(){
if (time!=null){
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return simpleDateFormat.format(time);
}else {
return "";
}
}
public User() {
}
public User(String name, int age, Date time) {
this.name = name;
this.age = age;
this.time = time;
}
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;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
}
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.Date" %>
<%@ page import="ytzl.User" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<html>
<head>
<title>table表格</title>
</head>
<body>
<%
List list = new ArrayList();
list.add(new User("周杰伦",18,new Date()));
list.add(new User("胡子洋",19,new Date()));
list.add(new User("葛霄",99,new Date()));
request.setAttribute("list",list);
%>
<table width="500px" height="500px" cellpadding="0px" cellspacing="0px" border="1px solid black">
<tr>
<td>编号</td>
<td>姓名</td>
<td>年龄</td>
<td>创建时间</td>
</tr>
<c:forEach items="${list}" var="user" varStatus="s">
<tr>
<td>${s.count}</td>
<td>${user.name}</td>
<td>${user.age}</td>
<td>${user.bitStr}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
三层架构
- 软件设计架构
- 界面层(表示层)
- 用户看的界面,用户可以通过界面上的组件和服务器进行交互
- 业务逻辑层
- 处理业务逻辑的。
- 数据访问层
- 操作数据存储文件。
案例
需求
- 用户信息的增删改查操作
设计
-
技术选型
- Servlet+Jsp+Mysql+JDBC+BeanUtils+tomcat
-
数据库设计
-
开发
- 环境搭建
- 创建数据库环境
- 创建项目,导入需要的jar包或xml依赖
- 编码
- 环境搭建
-
测试
-
部署运维
任务视图
查询
添加
修改
Filter过滤器
方法
方法 | 说明 |
---|---|
chain.doFilter(request, response); | 过滤器放行 |
阐述
- 生活中的过滤器
- 净水器
- 空气净化器
- 土匪
- web中的过滤器.
- 当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能
- 过滤器的作用
- 一般用于玩完成通过的操作
- 如:登录验证、统一编码处理、敏感字符过滤…
使用
-
定义一个类,实现接口Filter
-
复写方法
-
配置拦截路径
web.xml配置
<filter>
<filter-name>demo1</filter-name>
<filter-class>com.ytzl.filter.FilterDemo1</filter-class>
</filter>
<filter-mapping>
<filter-name>demo1</filter-name>
/*拦截路径*/
<url-pattern>/*</url-pattern>
</filter-mapping>
注解 @WebFilter(“/*”)
-
package com.ytzl.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; /** * @author 玫瑰到了花期 * @data 2022/4/14 11:28 * @love 又偷偷看你了 * @V: CBWR-K */ @WebFilter("/*") public class FilterDemo1 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("doFilter......"); //是否放行 //放行 chain.doFilter(request,response); } @Override public void destroy() { } }
过滤器执行流程
过滤器生命周期
过滤器配置详解
拦截路径配置
路径 | 作用 | |
---|---|---|
具体资源路径 | /index.jsp | 只有访问index.jsp资源时,过滤器会被执行 |
拦截目录 | /user/* | 访问/user下的所有资源时,过滤器会被执行 |
后缀名拦截 | *.jsp | 访问所有后缀名为jsp资源时,过滤器会被执行 |
拦截所有资源 | /* | 访问所有资源时,过滤器会被执行 |
拦截方式配置:资源被访问的方式
注解配置 | 说明 |
---|---|
设置dispatcherTypes属性 | |
REQUEST(request) | 默认值。浏览器直接请求资源 |
FORWARD(forward) | 转发访问资源 |
INCLUDE(include) | 包含访问资源 |
ERROR(error) | 错误跳转资源 |
ASYNC(async) | 异步访问资源 |
package com.ytzl.filter;
/**
* @author 玫瑰到了花期
* @data 2022/4/16 17:51
* @love 又偷偷看你了
* @V: CBWR-K
*/
import javax.servlet.*;
import javax.servlet.annotation.*;
import java.io.IOException;
/**浏览器直接请求资源时,该过滤器会被执行转发不会被执行*/
//@WebFilter(value = "/index.jsp",dispatcherTypes = DispatcherType.REQUEST)
/**只有转发时才会被执行*/
//@WebFilter(value = "/index.jsp",dispatcherTypes = DispatcherType.FORWARD)
/**既可以转发访问,也可以直接请求*/
@WebFilter(value = "/index.jsp",dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST})
public class FilterDemo5 implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//放行
chain.doFilter(request, response);
System.out.println("FilterDemo5....");
}
@Override
public void init(FilterConfig config) throws ServletException {
}
@Override
public void destroy() {
}
}
WEB.XML配置
配置 | 说明 |
---|---|
设置标签即可 | |
REQUEST(request) | 默认值。浏览器直接请求资源 |
FORWARD(forward) | 转发访问资源 |
INCLUDE(include) | 包含访问资源 |
ERROR(error) | 错误跳转资源 |
ASYNC(async) | 异步访问资源 |
过滤器链(配置多个过滤器)
- 执行顺序:如果有两个过滤器:过滤器1、过滤器2
- 过滤器1
- 过滤器2
- 资源执行
- 过滤器2
- 过滤器1
- 过滤器先后顺序问题
- 注解配置:按照类名的字符串比较规则比较,值小的先执行
- 如:AFilter BFilter,AFilter小、先执行
- web.xml配置
- 谁定义在上边,谁先执行
- 注解配置:按照类名的字符串比较规则比较,值小的先执行
案例–登陆验证
需求
- 访问day17_case案例的资源,验证其是否登录
- 如果登录了,则直接放行
- 如果没登录,则跳转登陆页面,提示“您尚未登陆,请先登录”
代码
package itcast.Service;
/**
* @author 玫瑰到了花期
* @data 2022/4/18 17:19
* @love 又偷偷看你了
* @V: CBWR-K
*/
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter("/*")
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//0.强制转换
HttpServletRequest request1 = (HttpServletRequest) request;
//1.获取资源请求的路径
String uri = request1.getRequestURI();
//2.判断是否包含登陆相关路径,要注,排除掉 css/js/图片/验证码等资源
if (uri.contains("/login.jsp")||uri.contains("/LoginServlet")||uri.contains("/css/")||uri.contains("/js/")||uri.contains("/fonts/")||uri.contains("/VerificationCodeServlet")){
//包含,用户就是想登陆。放行
chain.doFilter(request, response);
}else {
//不包含,需要验证用户是否登陆
//3.从session中获取user
Object user = request1.getSession().getAttribute("user");
if (user!=null){
//登陆了,放行
chain.doFilter(request, response);
}else {
//没有登陆,跳转登陆页面
request1.setAttribute("login_msg","您尚未登录,请登录");
request1.getRequestDispatcher("/login.jsp").forward(request1,response);
}
}
}
@Override
public void init(FilterConfig config) throws ServletException {
}
@Override
public void destroy() {
}
}
案例–敏感词汇过滤
需求
- 对day17_case案例录入的数据进行敏感词汇过滤
- 敏感词汇:笨蛋,傻瓜
- 如果是敏感词汇,替换为“***”
分析
- 对request对象进行增强。增强获取参数相关方法
- 放行。传递代理对象
增强对象的功能
- 设计模式:一些通用的解决固定问题的方式
- 装饰模式:
- 代理模式:
- 概念
- 真实对象:被代理的对象
- 代理对象
- 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的
- 动态代理
- 静态代理:在一个类文件描述代理模式
- 动态代理: 在内存中形成代理类
- 实现步骤:
- 代理对象和真实对象实现相同的接口
- 代理对象 = Proxy.newProxyInstance()
- 使用代理对象调用方法
- 增强方法
- 增强方式
- 增强参数列表
- 增强返回值类型
- 增强方法体执行逻辑
- 实现步骤:
- 概念
package itcast.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author 玫瑰到了花期
* @data 2022/4/18 17:58
* @love 又偷偷看你了
* @V: CBWR-K
*/
public class ProxyTest {
public static void main(String[] args) {
//1.创建真实对象
Lenovo lenovo = new Lenovo();
//2.动态代理,增强lenovo对象
/**
* 三个参数
* 1.类加载器 lenovo.getClass().getClassLoader()
* 2.接口数组 lenovo.getClass().getInterfaces()
* 3.处理器 new InvocationHandler()
* */
SaleComputer proxy_Lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
/**
* 代理逻辑编写的方法,代理对象调用的所有方法都会触发该方法执行
* 参数:
* 1、proxy:代理对象
* 2、method:代理对象调用的方法,被封装为的对象
* 3、args:代理对象调用方法时,传递的实际参数
* */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/* System.out.println("该方法执行了....");
System.out.println(method.getName());
System.out.println(args[0]);*/
//判断是否是sale方法
if (method.getName().equals("sale")){
//1.增强参数
double money = (double) args[0];
money = money * 0.85;
System.out.println("专车接你...");
Object obj = method.invoke(lenovo, money);
System.out.println("免费送货...");
//2.增强返回值
return obj+"_鼠标垫";
}else {
Object obj = method.invoke(lenovo, args);
return obj;
}
}
});
//2.调用方法
String computer = proxy_Lenovo.sale(8000);
System.out.println(computer);
proxy_Lenovo.show();
}
}
代码
package itcast.Service;
/**
* @author 玫瑰到了花期
* @data 2022/4/18 18:22
* @love 又偷偷看你了
* @V: CBWR-K
*/
import javax.servlet.*;
import javax.servlet.annotation.*;
import java.io.*;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
@WebFilter("/*")
public class SensitiveWordsFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=UTF-8");
//1.创建代理对象,增强getParameter方法
ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(request.getClass().getClassLoader(), request.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//增强getParameter方法
//判断是否是getParameter方法
if (method.getName().equals("getParameter")) {
//增强返回值
//获取返回值
String value = (String) method.invoke(request, args);
if (value != null) {
for (String str : list) {
if (value.contains(str)) {
System.out.println("str==>" + str);
value = value.replaceAll(str, "笨蛋");
}
}
}
request.getAttribute("");
return value;
}
return method.invoke(request, args);
}
});
//2放行
chain.doFilter(proxy_req, response);
}
private List<String> list = new ArrayList<String>();//敏感词汇集合
@Override
public void init(FilterConfig config) throws ServletException {
try {
//1.获取文件的真实路径
ServletContext servletContext = config.getServletContext();
String realPath = servletContext.getRealPath("/WEB-INF/敏感词汇.txt");
System.out.println("realPath==>" + realPath);
//2.读取文件
BufferedReader br = new BufferedReader(new InputStreamReader(servletContext.getResourceAsStream("/WEB-INF/敏感词汇.txt"), "utf-8"));
//BufferedReader br = new BufferedReader(new FileReader(realPath));
//3.将文件的每一行数据设置添加到list中
String line = null;
while ((line = br.readLine()) != null) {
list.add(line);
}
System.out.println("list.toString()==>" + list.toString());
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void destroy() {
}
}
Listener监听器
事件监听机制
事件监听机制 | 说明 |
---|---|
事件 | 一件事情 |
事件源 | 事件发生的地方 |
监听器 | 一个对象 |
注册监听 | 将事件、事件源、监听器绑定在一起。 |
当事件源上发生某个事件后,执行监听器代码 |
ServletContextListenter | 监听ServletContext对象的创建和销毁 |
---|---|
void contextDestroyed(ServletContextEvent sce) | ServletContext对象被销毁之前会调用该方法 |
void contextInitialized(ServletContextEvent sce) | ServletContext对象创建后会调用该方法 |
使用
-
定义一个类,实现ServletContextListener接口
-
复写方法
-
配置
-
web.xml
-
<!-- 配置监听器--> <listener> <listener-class>com.ytzl.Listener.ListenerDemo1</listener-class> </listener>
-
-
注解
-
@WebFilter
-
-
依赖导入
<dependencies>
<!-- jsp -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- jsp -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>