Javaweb后端技术(上)

Tomcat

一、 Web知识概述
Web(互联网总称)
Java Web:是用Java技术来解决相关web互联网领域的技术总和,通俗的说:将编写好的代码,发布到互
联网,可以让所有用户都访问到
1.1 软件架构
网络中有很多的计算机,它们直接的信息交流,我们称之为:交互
在互联网交互的过程的有两个非常典型的交互方式——B/S 交互模型(架构)和 C/S 交互模型
(架构)
C/S架构
Client/Server 客户端/服务器
访问服务器资源必须安装客户端软件
例如: QQ,绝地求生,LOL
在这里插入图片描述

B/S架构
Browser/Server 浏览器/服务器
访问服务器资源不需要专门安装客户端软件,而是直接通过浏览器访问服务器资源.
例如: 天猫、京东、知乎网站
在这里插入图片描述
1.2 Web服务器作用
开发者通过web服务器可以把本地资源发布到互联网
用户就可以通过浏览器访问这些资源
1.3 资源的分类
资源:计算机中数据文件
静态资源
对于同一个页面,不同用户看到的内容是一样的。
例如:体育新闻、网站门户等,常见后缀: .html、.js、.css
动态资源
用对于同一个页面,不同用户看到的内容可能不一样。
例如:购物车、我的订单等,常见后缀: .jsp、.aspx、
.php
1.4 URL 请求路径
URL (Uniform Resource Locator) ,统一资源定位符是对互联网上资源位置的一种表示,互联网上
的每个文件都有一个唯一的URL。
完整格式如下
协议://域名:端口号/资源位置?参数=值

  • 协议,http、https、ftp等
  • 域名,域名或IP地址,都可以访问WEB资源
  • 端口号,程序必须使用端口号,才可以让另一个计算机访问。http协议的默认端:80
  • 资源位置,用于描述WEB资源在服务器上的位置。
  • 参数=值,浏览器和服务器交互传递的数据
    例如:
    常见路径(访问 京东-笔记本电脑)
    https://list.jd.com/list.html?cat=670,671,672
    常见路径(访问 京东秒杀-电脑办公)
    https://miaosha.jd.com/category.html?cate_id=29
    常见路径(访问 拉勾-JavaEE)
    http://www.lagou.com
    1.5 常见的Web服务器

在这里插入图片描述

  • Jetty:Apache组织开源免费的小型web服务器,支持JavaEE规范.
  • Tomcat: Apache组织开源免费的web服务器,支持JavaEE规范(Servlet/Jsp).
  • JBoss: RedHat红帽公司的开源免费的web服务器,支持JavaEE规范.
  • Glass Fish:Sun公司开源免费的web服务器,支持JavaEE规范.
  • WebLogic: Oracle公司收费的web服务器,支持JavaEE规范.
  • WebSphere:IBM公司收费的web服务器,支持JavaEE规范.
    JavaEE规范
    在Java中所有的服务器厂商都要实现一组Oracle公司规定的接口,这些接口是称为JavaEE规范。不同厂商的JavaWeb服务器都实现了这些接口,在JavaEE中一共有13种规范。实现的规范越多,功能越强。

2.1 Tomcat使用
2.1.1 下载
Tomcat 官网下载地址:
https://tomcat.apache.org/download-80.cgi
在这里插入图片描述

2.1.2 安装
绿色免安装版,解压即用(注意:不要有中文路径)
在这里插入图片描述

2.1.3 目录结构
在这里插入图片描述
2.1.4 启动和关闭
在这里插入图片描述

== 在tomcat黑窗口内部crtl + c二次,表示正常关闭
2.1.5 启动报错问题【经验值】
① Java环境变量
现象: 黑窗口一闪而过(不到半秒)
解决:
配置好Java环境变量
JAVA_HOME
Path
在这里插入图片描述
② 8080端口被占用
现象:启动时报错(黑框口等了一会就关闭)
在这里插入图片描述
暴力:找到占用的端口号的对应进程,杀死进程
cmd命令: netstat -ano | findstr “8080”
在这里插入图片描述

进入到任务管理器,找到它,干掉它
在这里插入图片描述
温柔:修改Tomcat端口号
进入Tomcat安装目录/conf/server.xml 文件修改
注意:如果是其他软件占用了8080,你可以直接修改这一个就行…

在这里插入图片描述
注意:如果你想启动多个tomcat的话,需要修改二个端口号
在这里插入图片描述

端口号:个人指定范围:1024~65535之间,只要不与其他软件冲入即可
③ 访问测试
注:如果是80端口,可以省略不写
中文乱码问题
修改 apachehome/apache-tomcat-8.5.56/conf/logging.properties文件
把UTF-8,修改为GBK
在这里插入图片描述

2.1.6 发布项目三种方式
① webapps 部署(最简单)
直接放置在 webapps 目录下
在这里插入图片描述
这种方案(支持热更新),一般在开发完毕后,来使用的》。。。。
② server.xml部署(了解)
在tomcat/conf/server.xml中找到标签,添加标签
在这里插入图片描述

缺点
1.配置文件修改完毕后,需要重启后生效…
2.server.xml是tomcat的核心配置文件,如果稍有不慎操作失误,整个tomcat启动失败
3.这种方案作为了解即可
③ 独立xml部署(开发时使用)
在tomcat/conf/Catalina/localhost 目录下创建一个xml文件,添加标签
在这里插入图片描述
2.2 Idea中使用Tomcat【重中之重…】
2.2.1 配置Tomcat
在这里插入图片描述
在这里插入图片描述
再次点击,确定是否配置成功…
在这里插入图片描述

2.2.2 创建Web项目
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2.2.2 发布Web项目
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2.2.4 页面资源热更新
在这里插入图片描述

2.2.5 经验值分享
安全目录下的内容,浏览器是无法访问的
在这里插入图片描述

HTTP协议

1 Http简介
什么是Http协议
HTTP协议:超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网
络协议。用于定义WEB浏览器与WEB服务器之间交换数据的过程。
传输协议:在客户端和服务器端通信时,规范了传输数据的格式
在这里插入图片描述

必须先有请求,才会有响应
HTTP协议的作用
HTTP协议是学习JavaWEB开发的基石,不深入了解HTTP协议,就不能说掌握了WEB开发,更无
法管理和维护一些复杂的WEB站点。
HTTP协议的特点
基于请求/响应模型的协议。
请求和响应必须成对;
先有请求后有响应。
简单快捷
因为发送请求的时候只需要发送请求方式和请求路径即可
HTTP协议默认的端口:80
例如: http://www.lagou.com:80
无状态协议
多次请求之间相互独立,不能交互数据
Http协议的版本
HTTP/1.0,发送请求,创建一次连接,获得一个web资源,连接断开。
HTTP/1.1,发送请求,创建一次连接,获得多个web资源,连接断开。
HTTP协议有两种报文格式:
请求报文:由客户端向服务器端发出的报文。
响应报文:从服务端到客户端的报文。
2 Http协议详解

2.1 Http请求报文详解
HTTP请求报文:由客户端向服务器端发出的报文。
HTTP请求报文格式:包含请求行、请求头、空行、请求体 四个部分
在这里插入图片描述

请求行

请求行格式:请求方式 资源路径 协议/版本
例如:POST /web01/login.html HTTP/1.1
请求行必须在HTTP请求格式的第一行。
请求方式:协议规定7种,常用两种:GET和POST
GET请求:
将请求参数追加在URL后面,不安全。例如:login.html?username=tom&password=1234
URL长度限制GET请求方式的数据大小。
没有请求体
POST请求
请求参数显示请求体处,较安全。
请求数据大小没有限制。
只有表单设置为method=”post”才是post请求.其他的都是get请求。
常见GET请求:地址栏直接访问、<a href=””><img src=””>

请求头
请求头: 描述了客户端向服务器发送请求时使用的http协议类型,所使用的编码,以及发送内容的长度,referer,等等。
请求头也是用的键值对key:value
在这里插入图片描述
请求体

通常情况下,只有post请求方式才会使用到请求体,请求体中都是用户表单提交的数据,每一项数据都使用键值对key=value,多组值使用&相连。
例如;username=tom&password=1234

Http请求报文演示
创建页面,编写“login.html”,并提供表单,分别设置表单的提交方式为:get和post。将表单提交位置设置成#,表示提交到当前表单。
在这里插入图片描述

观看下图,我们采用GET请求方式、POST请求方式的抓包结果:(Chrome浏览器)
GET请求抓包数据:
在这里插入图片描述

POST请求抓包数据:
在这里插入图片描述

2.2 Http响应报文详解
响应报文:从服务端到客户端的报文。
HTTP响应报文格式:响应行、响应头、空行、响应体 四个部分
在这里插入图片描述

响应行
例如:HTTP/1.1 200 OK
格式:协议/版本 状态码 状态码描述
状态码:服务器与浏览器用于确定状态的固定数字号码
200 :请求成功。
302 :请求重定向。
304 :请求资源没有改变,访问本地缓存。
404 :请求资源不存在。通常是用户路径编写错误,也可能是服务器资源已删除。
500 :服务器内部错误。通常程序抛异常。

响应头
响应头: 用来描述服务器回给客户端浏览器的content的一些描述,例如: 我是什么服务器,我返回的是
啥编码,我返回的内容有多长等等
响应头也是用的键值对 key:value
在这里插入图片描述

响应体
响应体,就是服务器发送给浏览器的正文。

<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="#" method="post">
用户名:<input type="text" name="username" value=""/> <br/>
密 码:<input type="text" name="password" value=""/> <br/>
<input type="submit"/>
</form>
</body>
</html>

Http响应报文演示
如下图,我们提供的响应的抓包结果(Chrome浏览器)
在这里插入图片描述

Servlet

一、 Servlet概述
servlet= server+applet :运行在服务器端的java程序。
Servlet是一个接口,一个类要想通过浏览器被访问到,那么这个类就必须直接或间接的实现Servlet接口
作用
接收请求,处理逻辑,响应结果
在这里插入图片描述

二 、Servlet快速入门
案例需求:
编写一个普通的java类,通过浏览器可以访问
步骤分析:
① 创建web项目
② 编写普通java类,实现servlet接口
③ 在web.xml配置url-pattern
④ 部署web项目
⑤ 启动测试
2.1 代码编写
① 创建web项目
在这里插入图片描述

② 编写普通java类,实现servlet接口
编写抽象方法(service方法)

public class QuickServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
// 对外提供服务
/*
request:代表请求
response:代表响应
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse
servletResponse) throws ServletException, IOException {
// 向浏览器响应一句话
servletResponse.getWriter().write("QuickServlet");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}

③ 配置web.xml
配置servlet网络访问路径

<?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_3_1.xsd"
version="3.1">
<!--
把QuickServlet交给tomcat管理
servlet-name:当前servlet的别名(使用类名即可)
servlet-class:全限定类名
-->
<servlet>
<servlet-name>QuickServlet</servlet-name>
<servlet-class>cn.itcast.a_quick.QuickServlet</servlet-class>
</servlet>
<!--
给servlet设置一个网络的访问地址(路径)
servlet-name:给指定别名的servlet配置映射
url-pattern:网络访问地址(注意:必须以/开头)
-->
<servlet-mapping>
<servlet-name>QuickServlet</servlet-name>
<url-pattern>/quickServlet</url-pattern>
</servlet-mapping>
</web-app>

④ 部署web项目
在这里插入图片描述
⑤ 启动测试
在这里插入图片描述
2.2 servlet执行原理
在这里插入图片描述
三 、Servlet生命周期
3.1 生命周期相关
3.1.1 思想介绍
生命周期:指的是 一个对象从生(创建)到死(销毁)的一个过程

// 1. servlet对象创建时,调用此方法
public void init(ServletConfig servletConfig);
// 2. 用户访问servlet时,调用此方法
public void service(ServletRequest servletRequest, ServletResponse
servletResponse);
// 3. servlet对象销毁时,调用此方法
public void destroy();

3.1.2 代码演示
① LifeServlet

public class LifeServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("LifeServlet创建了....");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse
servletResponse) throws ServletException, IOException {
System.out.println("LifeServlet的service方法执行了");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("LifeServlet销毁了...");
}
}

② 配置web.xml

<!--servlet的生命周期-->
<servlet>
<servlet-name>LifeServlet</servlet-name>
<servlet-class>cn.itcast.b_api.LifeServlet</servlet-class>
<!--tomcat启动时,创建servlet对象,执行init方法 -->
<load-on-startup>4</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>LifeServlet</servlet-name>
<url-pattern>/lifeServlet</url-pattern>
</servlet-mapping>

在这里插入图片描述

  • 创建
    1)默认情况下
    用户第一次访问时,创建servlet,执行init方法
    2)修改创建时机
<load-on-startup></load-onstartup>

正数:4-N 【服务器启动时,创建】
补充:Tomcat的web.xml里有1,3 所以推荐4-n
负数(默认值):-1 【用户第一次访问时,创建】

  • 运行(提供服务)
    用户每次访问时,都执行service方法
  • 销毁
    服务器正常关闭时,销毁servlet,执行destroy方法
笔试题:请描述下servlet的生命周期:
答案:servlet是一个单实例多线程的,默认情况下,第一次请求来的时候,才会对该servlet进行实
例化,并执行初始化init方法,随后再执行service方法完成业务处理,当每一次请求发送过来,都会从新
开启一个线程,来执行servlet中的service方法,当服务器关闭或者servlet被移除的时候,会执行
destory方法

四 Servlet体系结构
在这里插入图片描述
在这里插入图片描述
4.1 GenericServlet
① 编写普通java类,继承GenericServlet抽象类

public class ServletDemo1 extends GenericServlet {
@Override
public void init() throws ServletException {
System.out.println("ServletDemo1 创建了...");
}
@Override
public void service(ServletRequest servletRequest, ServletResponse
servletResponse) throws ServletException, IOException {
servletResponse.getWriter().write("ServletDemo1 extends
GenericServlet");
}
@Override
public void destroy() {
System.out.println("ServletDemo1 销毁了..");
}
}

② 配置web.xml

<!--servlet继承genericServlet-->
<servlet>
<servlet-name>ServletDemo1</servlet-name>
<servlet-class>cn.itcast.c_inherit.ServletDemo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo1</servlet-name>
<url-pattern>/servletDemo1</url-pattern>
</servlet-mapping>

4.2 HttpServlet
在这里插入图片描述

① 编写前端html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<h3>用户登录</h3>
<form action="http://localhost:8080/servlet_demo/servletDemo2" method="get">
<input type="submit" value="提交表单..">
</form>
</body>
</html>

② 编写普通java类,继承HttpServlet抽象类

public class ServletDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.getWriter().write("get....");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.getWriter().write("post...");
}
}

③ 配置web.xml

<!--servlet继承httpServlet-->
<servlet>
<servlet-name>ServletDemo2</servlet-name>
<servlet-class>cn.itcast.c_inherit.ServletDemo2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo2</servlet-name>
<url-pattern>/servletDemo2</url-pattern>
</servlet-mapping>

五 url-pattern的配置方式
在这里插入图片描述

5.1 Servlet映射多个url
在这里插入图片描述

5.2 url映射模式
配置 url地址取值可以是:

  1. 精确匹配(掌握)
    /servletDemo3 localhost:8080/项目路径/servletDemo3
  2. 目录匹配
    /aa/*
  3. 后缀匹配
    .xxx 例如:.do
<!--
只要浏览器符合目录匹配规则,都可以访问到这个servlet:
/aa/abc
/aa/asadfasdf
-->
<servlet>
<servlet-name>ServletDemo4</servlet-name>
<servlet-class>com.lagou.servlet.QuickServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo4</servlet-name>
<url-pattern>/aa/*</url-pattern>
</servlet-mapping>
<!--
只要浏览器符合后缀匹配规则,都可以访问到这个servlet
aa.do
bb.do
xx.do
-->
<servlet>
<servlet-name>ServletDemo5</servlet-name>
<servlet-class>com.lagou.servlet.QuickServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo5</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

六 Request对象
6.1 request对象概述
用户通过浏览器访问服务器时,Tomcat将HTTP请求中所有的信息都封装在Request对象中
作用:开发人员可以通过request对象方法,来获取浏览器发送的所有信息.
在这里插入图片描述
6.2 获取请求行信息

  • 例如:
    GET /servlet_demo/requestDemo1 HTTP/1.1
  • 相关API:
  1. 获取请求方式 GET【掌握】
    String getMethod()
  2. 获取项目虚拟路径(项目名)/servlet_demo【掌握】
    String getContextPath()
  3. 获取URL http://localhost:8080/servlet_demo/requestDemo1
    统一资源定位符(确定某一个地址) 中华人民共和国
    StringBuffer getRequestURL()
  4. 获取协议和版本号 HTTP/1.1
    String getProtocol()
  5. 获取客户端ip
    String getRemoteAddr()
public class RequestDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// System.out.println(req);
System.out.println("请求方式:" + req.getMethod());
System.out.println("虚拟路径:" + req.getContextPath());
System.out.println("URL:" + req.getRequestURL());
System.out.println("协议和版本:" + req.getProtocol());
System.out.println("客户端ip:" + req.getRemoteAddr());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
}

6.3 获取请求头信息

  • 例如:
    Host: 127.0.0.1:8080
  • 相关API:
  1. 获取知道请求头名称对应的值,注:名称不区分大小写
    String getHeader(String name)
  2. 获取所有请求头的名称
    Enumeration getHeaderNames()
    注:是Iterator前身
public class RequestDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 获取所有的请求头名称
Enumeration<String> enumeration = req.getHeaderNames();
// 遍历
while(enumeration.hasMoreElements()){
// 取出元素名(请求头名称)
String name = enumeration.nextElement();
// 根据名称获取值
String value = req.getHeader(name);
System.out.println(name +" : "+ value);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
}

6.4 获取请求体信息(请求参数)【重点…】
不论get还是post请求方式,都可以使用下列方法来获取请求参数

  • 参数
    username=jack&password=123&hobby=drink&hobby=perm
  • API
  1. 获取指定参数名的值 username=jack
    String getParameter(String name)
  2. 获取指定参数名的值数组 hobby=drink&hobby=perm
    String[] getParameterValues(String name)
  3. 获取所有参数名和对应值数组,参数名 name(key),值数组 value,封装map集合
    Map<String,String[]> getParameterMap()
  • 中文乱码【重点】
    get:在tomcat8及以上版本,内部URL编码(UTF-8)
    post:编码解码不一致,造成乱码现象
    客户端(浏览器)编码:UTF-8
    服务器默认 解码:ISO-8859-1 拉丁文
    指定解码:void setCharacterEncoding(String env)
    注:这哥们必须在方法内,行首
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>form</title>
</head>
<body>
<h3>get方式:</h3>
<form action="/day09_request/requestDemo3" method="get">
用户:<input type="text" name="username"> <br>
密码:<input type="password" name="password"> <br>
爱好:
<input type="checkbox" name="hobby" value="smoking"/>抽烟
<input type="checkbox" name="hobby" value="drink"/>喝酒
<input type="checkbox" name="hobby" value="perm"/>烫头
<input type="submit" value="get提交...">
</form>
<h3>post方式:</h3>
<form action="/day09_request/requestDemo3" method="post">
用户:<input type="text" name="username"> <br>
密码:<input type="password" name="password"> <br>
爱好:
<input type="checkbox" name="hobby" value="smoking"/>抽烟
<input type="checkbox" name="hobby" value="drink"/>喝酒
<input type="checkbox" name="hobby" value="perm"/>烫头
<input type="submit" value="post提交...">
</form>
</body>
</html>
@WebServlet("/requestDemo3")
public class RequestDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("手动获取---------");
String username = req.getParameter("username");
System.out.println("用户:" + username);
String password = req.getParameter("password");
System.out.println("密码:" + password);
String[] hobby = req.getParameterValues("hobby");
System.out.println("爱好:" + Arrays.toString(hobby));
System.out.println("自动获取---------");
Map<String, String[]> parameterMap = req.getParameterMap();
parameterMap.forEach((k, v) -> {
System.out.println(k + " = " + Arrays.toString(v));
});
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 指定post的解码方式....
req.setCharacterEncoding("UTF-8");
System.out.println("post提交方法,再去调用get....");
this.doGet(req, resp); // 让get小老弟干活...
	}
}

6.5 请求转发
一种在服务器内部的资源跳转方式

  • API
  1. 通过reqeust对象,获得转发器对象
    RequestDispatcher getRequestDispatcher(String path) //要跳转到的z
  2. 通过转发器对象,实现转发功能
    void forward(ServletRequest request, ServletResponse response)
  • 请求转发特点
    浏览器:发了一次请求
    地址栏:没有发生改变
    只能转发到服务器内部资源…

  • 链式编程
    request.getRequestDispatcher("/bServlet").forward(reqeust,response)
    在这里插入图片描述

  • API

  1. 设置数据
    void setAttribute(String name, Object o)
  2. 获取数据
    Object getAttribute(String name)
  3. 删除数据
    void removeAttribute(String name)
  • 生命周期
  1. 何时创建?
    用户发送请求时,创建request
  2. 何时销毁
    服务器返回响应是,销毁request
  3. 作用范围?
    一次请求,包含多次转发
@WebServlet("/aServlet")
public class AServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
System.out.println("aServlet处理功能上....");
// 转发到BServlet
/* // 1.获得转发器对象 path = @WebServlet("/bServlet")
RequestDispatcher requestDispatcher =
request.getRequestDispatcher("/bServlet");
// 2.实现转发功能
requestDispatcher.forward(request, response);*/
// 存一个数据
request.setAttribute("hanbao", "香辣鸡腿堡");
// 链式编程横
request.getRequestDispatcher("bServlet").forward(request, response);
}
}
@WebServlet("/bServlet")
public class BServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
System.out.println("bServlet处理功能下....");
// 获取数据
String hanbao = (String) request.getAttribute("hanbao");
System.out.println("hanbao:" + hanbao);
}
}

七 Response对象
7.1 概述
response对象表示web服务器给浏览器返回的响应信息
作用:开发人员可以使用response对象的方法,设置要返回给浏览器的响应信息
在这里插入图片描述

Response体系结构

ServletResponse 接口
|
HttpServletResponse 接口
|
org.apache.catalina.connector.ResponseFacade 实现类(由tomcat提供的)

7.2 设置Http响应消息
响应行

  • 格式
    协议/版本号 状态码
  • 例如
    HTTP/1.1 200
  • API
  1. 设置状态码
    void setStatus(int sc) 200 302 304 404 500

响应头

  • 格式
    响应头名称:响应头的值
  • 例如
    Location:http://www.lagou.com
  • API
  1. 设置指定头名称和对应的值
    void setHeader(String name, String value)

响应体【重点】

  • API(输出流对象)
  1. 字符输出流
    PrintWriter getWriter()
  2. 字节输出流
    ServletOutputStream getOutputStream()
    注意:在同一个servlet中,二种类型的输出流不能同时存在,互斥

7.3 响应重定向
在这里插入图片描述

需求:用户访问AServlet后,服务器告诉浏览器重定向到BServlet
步骤分析

  • 方式一
    // 1.设置状态码
    response.setStatus(302);
    // 2.设置响应头 Location
    response.setHeader(“Location”,“重定向网络地址”);
  • 方式二
    // 1.response这哥们封装专门处理重定向的方法
    response.sendRedirect(“重定向网络地址”);

重定向特点

  1. 地址栏会发生改变
  2. 重定向是二次请求
  3. 重定向是客户端(浏览器)行为,可以跳转到服务器外部资源…
  4. 不能使用request域共享数据
@WebServlet("/AServlet")
public class AServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
System.out.println("AServlet执行了....");
/* // 1.设置状态码
response.setStatus(302);
// 2.设置响应头 Location
response.setHeader("Location","/day10_response/BServlet");*/
// 1.response这哥们封装专门处理重定向的方法
response.sendRedirect("http://www.itcast.cn");
}
}
@WebServlet("/BServlet")
public class BServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
System.out.println("BServlet执行了....");
}
}

请求转发与重定向的区别

  1. 哪个对象
    转发(request对象的方法)
    request.getRequestDispatcher("/bServlet").forward(request,response);
    重定向(response对象的方法)
    response.sendRedirect("/day10_response/bServlet");
  2. 几次请求
    转发
    地址栏: 没有改变
    浏览器: 发了一次请求
    服务器: 只有一对请求和响应对象
    发生的位置: 服务器
    重定向
    地址栏: 发生了改变
    浏览器: 发了两次请求
    服务器: 有两对请求和响应对象
    发生的位置: 浏览器
  3. 小结
    写法
    转发("/servlet资源路径") 服务器内部行为
    重定向 ("/虚拟路径(项目名)/servlet资源路径") 浏览器外部行为
    使用场景(重点掌握)
    如果需要传递数据(request域),使用转发
    如果不需要传递数据(request域),使用重定向

7.4 响应中文
需求
向页面输出中文数据没有乱码
步骤分析

  1. 通过response获取字符输出流
    PrintWriter pw = response.getWriter();
  2. 通过字符输出输出文本
    pw.write(“中文…”);
    在这里插入图片描述

解决中文乱码

  1. 指定服务器响应编码方式
    response.setCharacterEncoding(“GBK”);
  2. 统一浏览器和服务器编码
    response.setContentType(“text/html;charset=utf-8”);
@WebServlet("/EncodeServlet")
public class EncodeServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// 指定服务器响应编码方式
// response.setCharacterEncoding("UTF-8");
// 统一浏览器和服务器编码
response.setContentType("text/html;charset=utf-8");
// 1. 通过response获取字符输出流
PrintWriter pw = response.getWriter();
// 2. 通过字符输出输出文本
pw.write("中文....");
}
}

八 、ServletContext
8.1 概述
web容器(tomcat)在启动时,它会为每个web项目承建一个对应的ServletContext对象
它代表:当前web项目
在这里插入图片描述

主要作用

  1. 域对象(共享数据)
  2. 获取资源在服务器的真实地址
  3. 获取全局的配置参数
  4. 获取文件MIME类型

获取ServletContext对象

  1. 通过request对象获得
    ServletContext sc = request.getServletContext();
  2. 继承HttpServlet后,可以直接调用
    ServletContext sc = this.getServletContext();

8.2 域对象(共享数据)
在当前项目范围内,共享数据(多个servlet都可以获取)
在这里插入图片描述

  1. 存储数据
    void setAttribute(String name,Object value)
  2. 获取数据
    Object getAttribute(String name)
  3. 删除数据
    void removeAttribute(String name)
@WebServlet("/OneServlet")
public class OneServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// 向servletContext域存数据....
ServletContext sc1 = request.getServletContext();
ServletContext sc2 = getServletContext();
sc1.setAttribute("user", "jack");
System.out.println("OneServlet存了数据。。。");
}
}
@WebServlet("/TwoServlet")
public class TwoServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// 从servletContext域获取数据
String user = (String) request.getServletContext().getAttribute("user");
System.out.println("TwoServlet获取数据:"+user);
}
}

生命周期

  1. 何时创建?
    项目加载时,创建
  2. 何时销毁?
    项目卸载时,销毁
  3. 作用范围?
    与项目共存亡(多个servlet都可以操作它)

8.3 获取资源在服务器的真实地址
可以实现web项目的移植性…动态获取文件真实路径
在这里插入图片描述

  • API
    String getRealPath(String path);
@WebServlet("/RealpathServlet")
public class RealpathServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// 获取car.jpg 文件真实路径
String carPath =
request.getServletContext().getRealPath("/img/car.jpg");
System.out.println(carPath);
// 获取web.xml 文件真实路径
String webPath = request.getServletContext().getRealPath("/WEBINF/
web.xml");
System.out.println(webPath);
}
}

8.4 获取全局的配置参数
读取web.xml配置文件中标签信息,实现参数和代码的解耦(多个servlet都可以获取)

<?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_3_1.xsd"
version="3.1">
<!--全局配置参数:所有的servlet都可以读取...-->
<context-param>
<param-name>encode</param-name>
<param-value>UTF-8</param-value>
</context-param>
</web-app>
@WebServlet("/ContextPathServlet")
public class ContextPathServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// 获取全局参数
String value = request.getServletContext().getInitParameter("encode");
System.out.println("全局配置参数:"+value);
}
}

8.5 获取文件MIME类型
在互联网通信过程中定义的一种文件数据类型格式
格式: 大类型/小类型 例如: text/html image/jpeg
在这里插入图片描述

<a href="/day10_servletContext/MimeServlet?filename=luola.avi">获取文件的mime类型
</a><br>
@WebServlet("/MimeServlet")
public class MimeServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// 获取指定文件的mime类型
// 获取请求参数
String filename = request.getParameter("filename");
// 获取文件的mime类型
String mimeType = request.getServletContext().getMimeType(filename);
response.getWriter().write(filename + "---" + mimeType);
}
}

8.6 案例:统计网站的访问次数
需求
一般个人博客的首页,都会显示你是第几位访问此网站…
在这里插入图片描述

@WebServlet(value = "/CountServlet", loadOnStartup = 4) // 服务器启动时,创建此
servlet对象
public class CountServlet extends HttpServlet {
@Override
public void init() throws ServletException {
getServletContext().setAttribute("count", 0);
}
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// 设置response响应编码
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("<h1>拉勾网站</h1>");
// 用户每次访问,从域中取出,加1,再存进去
ServletContext servletContext = request.getServletContext();
// 从域中取出
Integer count = (Integer) servletContext.getAttribute("count");
// 加1
count++;
// 再存进去
servletContext.setAttribute("count", count);
response.getWriter().write("<div>你是,第" + count + "位访问此网站...
</div>");
}
}

Cookie & Session

一 会话概述

1.1 什么是会话?

日常生活中:从拨通电话到挂断电话之间的一连串你问我答的过程就是一个会话。
B/S架构中:从浏览器第一次给服务器发送请求时,建立会话;直到有一方断开,会话结束。
一次会话:包含多次请求响应。
在这里插入图片描述

1.2 会话技术
问题:Http是一个无状态协议,同一个会话的连续两个请求相互独立,彼此并不了解
作用:用于存储浏览器与服务器在请求和响应过程中产生的数据 客户端会话技术:cookie
服务器端会话技术:session

在这里插入图片描述

二 Cookie【重点】

2.1 概述

Cookie作用:在一次会话的多次请求之间共享数据,将数据保存到客户端(浏览器) jd购物车
在这里插入图片描述
2.2 快速入门

  1. 设置数据到cookie中
    // 1.创建cookie对象,设置数据 *value只能存字符串
    Cookie cookie = new Cookie(String name,String value);
    // 2.通过response,响应(返回)cookie
    response.addCookie(cookie);
  2. 从cookie中获取数据
    // 1.通过request对象,接收cookie数组
    Cookie[] cookies = request.getCookies();
    // 2.遍历数组
@WebServlet("/SetServlet")
public class SetServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// 1.创建cookie对象,设置数据
Cookie cookie = new Cookie("name","jack");
// 2.通过response,响应(返回)cookie
response.addCookie(cookie);
}
}
@WebServlet("/GetServlet")
public class GetServlet extends HttpServlet {
		protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
			this.doPost(request, response);
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.通过request对象,接收cookie数组
		Cookie[] cookies = request.getCookies();
// 2.遍历数组
		if(cookies!=null){
			for (Cookie c : cookies) {
				String name = c.getName();
				String value = c.getValue();
				System.out.println(name + " : " + value);
			}
		}
	}
}

2.3 工作原理

基于HTTP协议:请求头cookie 和 响应头 set-cookie
在这里插入图片描述
2.4 Cookie细节
2.4.1 服务器发送多个Cookie?

  • 答案是可以的
    // 1. 创建多个cookie对象
    Cookie cookie1 = new Cookie(“name”,“lucy”);
    Cookie cookie2 = new Cookie(“age”,“18”);
    // 2. 通过response响应多个
    response.addCookie(cookie1);
    response.addCookie(cookie2);
@WebServlet("/MultipleCookie")
public class MultipleCookie extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// 1. 创建多个cookie对象
Cookie cookie1 = new Cookie("name","lucy");
Cookie cookie2 = new Cookie("age","18");
// 2. 通过response响应多个
response.addCookie(cookie1);
response.addCookie(cookie2);
}
}

2.4.2 Cookie在浏览器保存时间?

  • 默认情况下
    浏览器关闭(会话结束),cookie销毁(内存)
  • 设置cookie的存活时间
    cookie.setMaxAge(int second); – 单位是秒
    正数:指定存活时间,持久化浏览器的磁盘中,到期后自动销毁
    负数:默认浏览器关闭,cookie销毁
    零:立即销毁(自杀)
@WebServlet("/MaxAgeCookie")
public class MaxAgeCookie extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// 1.创建cookie对象
Cookie cookie = new Cookie("product", "xiaomi10");
// 2.设置cookie存活时间
// cookie.setMaxAge(-1); // 默认值,浏览器关闭自动销毁
// cookie.setMaxAge(60);// 存活30秒,到期自动销毁
cookie.setMaxAge(0); // 立即销毁...
//3. response响应cookie
response.addCookie(cookie);
}
}

2.4.3 Cookie是否可以存储中文?

  • tomcat8之前的版本,不支持中文
    URLEncoder 编码
    URLDecoder 解码
  • tomcat8以后的版本,支持中文…
    Rfc6265Cookie规范,不允许使用 分号、空格等一些特殊符号…
@WebServlet("/EncodeCookie")
public class EncodeCookie extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
String product = "华为荣耀 30X,";
product= URLEncoder.encode(product, "UTF-8");
// 1.创建cookie对象
Cookie cookie = new Cookie("product", product);
// 2.response响应cookie
response.addCookie(cookie);
}
}
@WebServlet("/GetServlet")
public class GetServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// 1.通过request对象,接收cookie数组
Cookie[] cookies = request.getCookies();
// 2.遍历数组
if(cookies!=null){
for (Cookie c : cookies) {
String name = c.getName();
String value = c.getValue();
// 解码
value = URLDecoder.decode(value, "UTF-8");
System.out.println(name + " : " + value);
			}
		}
	}
}

2.5 Cookie特点

  1. cookie存储数据都在客户端(浏览器)
  2. cookie的存储数据只能是字符串
  3. cookie单个大小不能超过4KB
  4. cookie存储的数据不太安全

三 Session【重点】

3.1 概述

使用Cookie问题

  1. 最多存储4K字符串
  2. 存储数据不太安全

session作用:在一次会话的多次请求之间共享数据,将数据保存到服务器端
在这里插入图片描述

3.2 快速入门

HttpSession也是一个域对象

  • API
  1. 存储数据
    void setAttribute(String name,Object value)
  2. 获取数据
    Object getAttribute(String name)
  3. 删除数据
    void removeAttribute(String name)

步骤分析

  1. 将数据存储到session中
    // 1.通过rquest对象,获取session对象
    HttpSession session = request.getSession();
    // 2.操作session的API,存储数据
    session.setAttribute(“username”,“哈哈,呵呵”);
  2. 从session中获取数据
    // 1.通过rquest对象,获取session对象
    HttpSession session = request.getSession();
    // 2.操作session的API,获取数据
    session.getAttribute(“username”);
@WebServlet("/SetSession")
public class SetSession extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// 1.通过rquest对象,获取session对象
HttpSession session = request.getSession();
// 2.操作session的API,存储数据
session.setAttribute("username", "哈哈,呵呵");
}
}
@WebServlet("/GetSession")
public class GetSession extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// 1.通过rquest对象,获取session对象
HttpSession session = request.getSession();
// 2.操作session的API,获取数据
String username = (String) session.getAttribute("username");
System.out.println("GetSession获取:" + username);
}
}

3.3 工作原理

Session基于Cookie技术实现
在这里插入图片描述

3.4 生命周期

  • 何时创建
    用户第一次调用request.getSession()方法时,创建
  • 何时销毁
    服务器非正常关闭
    非活跃状态30分钟后
    tomcat进行配置 /tocmat安装目录/conf/web.xml
    session.invalidate(); 自杀
  • 作用范围
    一次会话中,多次请求之间
    注意:每一个浏览器跟服务器都是独立的会话…

四 三大域对象总结

request、session、ServletContext
4.1 API

  1. 设置数据
    void setAttribute(String name, Object o)
  2. 获取数据
    Object getAttribute(String name)
  3. 删除数据
    void removeAttribute(String name)

4.2 生命周期

4.2.1 ServletContext域对象

  • 何时创建
    服务器正常启动,项目加载时,创建
  • 何时销毁
    服务器关闭或项目卸载时,销毁
  • 作用范围
    整个web项目(共享数据)

4.2.2 HttpSession域对象

  • 何时创建
    用户第一次调用request.getSession()方法时,创建
  • 何时销毁
    服务器非正常关闭
    未活跃状态30分钟
    自杀
  • 作用范围
    一次会话中,多次请求间(共享数据)

4.2.3 HttpServletRequest域对象

  • 何时创建
    用户发送请求时,创建
  • 何时销毁
    服务器做出响应后,销毁
  • 作用范围
    一次请求中,多次转发间(共享数据)

4.3 小结
能用小的不用大的:request<session<servletContext
常用的场景:
request:一次查询的结果(servlet转发jsp)
session:存放当前会话的私有数据
用户登录状态
验证码
购物车
servletContext:若需要所有的servlet都能访问到,才使用这个域对象.

Filter & Listener

Filter
一 概述
生活中的过滤器
净水器、空气净化器、地铁安检、山大王
web中的过滤器
当用户访问服务器资源时,过滤器将请求拦截下来,完成一些通用的操作
应用场景
如:登录验证、统一编码处理、敏感字符过滤
二 快速入门
需求:编写filter对目标资源servlet进行拦截
① 编写java类,实现filter接口

public class QuickFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/**
* 此方法拦截用户请求
* @param servletRequest :请求对象
* @param servletResponse :响应对象
* @param filterChain :过滤器链(是否放行)
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse
servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("QuickFilter拦截了请求...");
// 放行
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}

② 配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--快速入门-->
<!--注册filter-->
<filter>
<filter-name>QuickFilter</filter-name>
<filter-class>com.lagou.a_quick.QuickFilter</filter-class>
</filter>
<!--配置filter拦截路径-->
<filter-mapping>
<filter-name>QuickFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

三 工作原理
在这里插入图片描述
四 使用细节
4.1 生命周期
生命周期:指的是一个对象从生(创建)到死(销毁)的一个过程
// 初始化方法
public void init(FilterConfig config);

// 执行拦截方法
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain);

// 销毁方法
public void destroy();

  • 创建
    服务器启动项目加载,创建filter对象,执行init方法(只执行一次)
  • 运行(过滤拦截)
    用户访问被拦截目标资源时,执行doFilter方法
  • 销毁
    服务器关闭项目卸载时,销毁filter对象,执行destroy方法(只执行一次)
  • 补充:
    过滤器一定是优先于servlet创建的
// @WebFilter(value = "/show.jsp"})
public class LifecycleFilter implements Filter {
/*
filterConfig 它是filter的配置对象
注意作用:获取filter的初始化参数
*/
private String encode;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("LifecycleFilter创建了...执行init方法");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse
servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("LifecycleFilter拦截了请求...执行deFilter方法");
// 放行
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
System.out.println("LifecycleFilter销毁了...执行destroy方法");
}
}

4.2 拦截路径
在开发时,我们可以指定过滤器的拦截路径来定义拦截目标资源的范围

  • 精准匹配
    用户访问指定目标资源(/targetServlet)时,过滤器进行拦截
  • 目录匹配
    用户访问指定目录下(/user/*)所有资源时,过滤器进行拦截
  • 后缀匹配
    用户访问指定后缀名(*.html)的资源时,过滤器进行拦截
  • 匹配所有
    用户访问该网站所有资源(/*)时,过滤器进行拦截

/*

  • 精准匹配
    用户访问指定目标资源(/show.jsp)时,过滤器进行拦截
  • 目录匹配
    用户访问指定目录下(/user/*)所有资源时,过滤器进行拦截
  • 后缀匹配
    用户访问指定后缀名(*.html)的资源时,过滤器进行拦截
  • 匹配所有
    用户访问该网站所有资源(/*)时,过滤器进行拦截
    */
// @WebFilter("/show.jsp") 精准匹配
// @WebFilter("/user/*") // 目录匹配
// @WebFilter("*.html") // 后缀匹配
@WebFilter("/*") // 匹配所有
public class UrlPatternFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse
servletResponse, FilterChain chain) throws ServletException, IOException {
System.out.println("UrlPatternFilter拦截了请求...");
// 放行
chain.doFilter(servletRequest, servletResponse);
}
public void destroy() {
}
}

4.3 过滤器链
在一次请求中,若我们请求匹配到了多个filter,通过请求就相当于把这些filter串起来了,形成了过滤器链

  • 需求
    用户访问目标资源 /targetServlet时,经过 FilterA FilterB
  • 过滤器链执行顺序 (先进后出)
    1.用户发送请求
    2.FilterA拦截,放行
    3.FilterB拦截,放行
    4.执行目标资源 show.jsp
    5.FilterB增强响应
    6.FilterA增强响应
    7.封装响应消息格式,返回到浏览器
  • 过滤器链中执行的先后问题…
    配置文件
    谁先声明,谁先执行
<filter-mapping>

在这里插入图片描述
五 综合案例
5.1 用户评论留言
需求
用户访问某论坛网站,可以写评论的方式对比赛内容进行留言
5.1.1 需求分析
5.1.2 代码实现
① bbs.html

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>bbs</title>
</head>
<body>
<h3>LPL季后赛观看留言板</h3>
<hr>
<form action="${pageContext.request.contextPath}/WordsServlet" method="post">
<textarea name="content" id="" cols="30" rows="10"></textarea>
<input type="submit" value="请留言">
</form>
</body>
</html>

② WordsServlet

@WebServlet("/WordsServlet")
public class WordsServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// 1.接收请求参数 content
String content = request.getParameter("content");
// 2.将结果响应到 浏览器
response.getWriter().write(content);
}
}

5.2 统一网站编码
需求
tomcat8.5版本中已经将get请求的中文乱码解决了,但是post请求还存在中文乱码
浏览器发出的任何请求,通过过滤器统一处理中文乱码
5.2.1 需求分析

在这里插入图片描述

5.2.2 代码实现
真实场景中,过滤器不会统一响应mime类型

// @WebFilter("/*")
public class EncodeFilter implements Filter {
private String encode="UTF-8";
public void doFilter(ServletRequest servletRequest, ServletResponse
servletResponse, FilterChain chain) throws ServletException, IOException {
// 类型向下转型
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// 判断用户是否为post请求,才设置编码
if (request.getMethod().equalsIgnoreCase("post")) {
request.setCharacterEncoding(encode);
}
response.setContentType("text/html;charset="+encode);
// 放行
chain.doFilter(servletRequest, servletResponse);
}
public void destroy() {
}
}
<!--统一网站编码-->
<filter>
<filter-name>EncodeFilter</filter-name>
<filter-class>com.lagou.d_case.EncodeFilter</filter-class>
<init-param>
<param-name>encode</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Listener【了解】
1.1 概述
生活中的监听器
我们很多商场有摄像头,监听着客户的一举一动。如果客户有违法行为,商场可以采取相应的措施。
javaweb中的监听器
在我们的java程序中,有时也需要监视某些事情,一旦被监听的对象发生相应的变化,我们应该采取相
应的操作。
监听web三大域对象:HttpServletRequest、HttpSession、ServletContext 通过监听器监听三大域对象它们的创建和销毁
场景
历史访问次数、统计在线人数、系统启动时初始化配置信息
1.2 快速入门
监听器在web开发中使用的比较少,见的机会就更少了,所以我们就使用ServletContextListenner来带领大家学习下监听器,因为这个监听器是监听器中使用率最高的一个,且监听器的使用方式都差不多。我们使用这个监听器可以在项目启动和销毁的时候做一些事情,例如,在项目启动的时候加载配置文件。

ServletContextListener接口的API介绍--重要
void contextDestroyed(ServletContextEvent sce) 监听servletcontext销毁
void contextInitialized(ServletContextEvent sce) 监听servletcontext创建

使用步骤
1.创建一个类实现ServletContextListenner接口
2.实现ServletContextListenner的contextInitialized和contextDestroyed方法。
3.给这个类在xml中配置

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class MyServletContextListenner1 implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("服务器启动,servletContext被创建了");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("服务器停止,servletContext被销毁了");
}
}

web.xml配置如下

<listener>
<listener-class>com.itheima.listenner.MyServletContextListenner1</listenerclass>
</listener>

同理:使用如下接口以相同的方式也可以监听到session对象和request对象的创建和销毁
HttpSessionListener:监听Httpsession域的创建于销毁的监听器
ServletRequestListener:监听ServletRequest域的创建于销毁的监听器

MVC模式&三层架构【思想】

一 MVC模式

1.1 JSP发展史
早期只有servlet,只能使用response输出html标签,非常麻烦。
在这里插入图片描述

后来有了JSP,简化了servlet开发;如果过度使用JSP,在JSP页面中写了大量的java代码和html标
签,造成难于维护,难于分工协作的场景。
在这里插入图片描述

再后来为了弥补过度使用jsp的问题,我们使用servlet+jsp这套组合拳,利于分工协作。
在这里插入图片描述
1.2 MVC介绍
MVC设计模式: Model-View-Controller简写。
MVC是软件工程中的一种软件架构模式,它是一种分离业务逻辑与显示界面的设计方法。
简单来说:前辈们总结的一套设计经验,适合在各种软件开发领域,目的:高内聚,低耦合

  • M:model(模型) JavaBean(1.处理业务逻辑、2.封装实体)
  • V:view(视图) Jsp(展示数据)
  • C:controller(控制器)Servlet(1.接收请求、2.调用模型、3.转发视图) MVC:笔试题
  • 优缺点
    优点
    降低耦合性,方便维护和拓展,利于分工协作
    缺点
    使得项目架构变得复杂,对开发人员要求高

在这里插入图片描述
二 三层架构(MVC升级版)
改造了MVC以后的架构,就称为三层架构
在这里插入图片描述

2.1 概念
通常意义上的三层架构就是将整个业务应用划分为:表示(现)层、业务逻辑层、数据访问层。
区分层次的目的 为了高内聚低耦合的思想
表示(现)层:又称为web层,与浏览器进行数据交互(控制器和视图)
业务逻辑层:又称为service层,处理业务数据(if判断,for循环)
数据访问(持久)层:又称为dao层,与数据库进行交互的(每一条(行)记录与javaBean实体对应)
包目录结构

  • com.lagou 基本包(公司域名倒写)
  • com.lagou.dao 持久层
  • com.lagou.service 业务层
  • com.lagou.web 表示层
  • com.lagou.domain 实体(JavaBean)
  • com.lagou.util 工具
    在这里插入图片描述
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值