JavaWeb笔记
JavaWeb基础
JavaWeb技术体系

前端知识学习目录
| 技术 | 简介 |
|---|---|
| HTML | 结构,页面骨架,静态页面 |
| CSS | 表现,负责页面画面美化渲染 |
| JavaScript | 行为,负责页面行为,使网页可以交互,如验证之类的 |
| jQuery | JavaScript 库,方便操作BOM与DOM的功能 |
| JSON | 一种文件格式,字符串 |
| Ajax | 异步请求 |
| Node.js | 不是一门编程语言,是一个执行 JavaScript 代码的工具,提供了前端程序的运行环境 可以把Node.js理解成是运行前端程序的服务器,等同于Java中的Tomcat |
| webpack | 前端模块打包机,基于 Node.js 开发出来的打包工具,是目前前端项目工程化的具体解决方案,类似Java中的Maven |
| Vue | 前端MVVM框架,免除原生JavaScript中的DOM操作,简化书写 |
B/S架构与C/S架构
B/S架构(Browser/Server)
B/S架构(Browser/Server Architecture)是指浏览器/服务器架构,也被称为Web架构。在B/S架构中,应用程序的前端界面(通常是浏览器)与后端服务器进行交互。
交互流程:在B/S架构中,前端界面是通过浏览器上的Web页面来呈现给用户,通常使用HTML、CSS和JavaScript等技术来实现。用户通过浏览器发送请求(如点击链接、填写表单等),请求会被发送到服务器端进行处理。服务器端进行相应的业务逻辑处理,并返回数据或页面给浏览器,浏览器再将这些数据或页面展示给用户。
适应场景:B/S架构适用于跨平台和分布式环境,因为它只需要一个浏览器作为客户端界面,不需要安装额外的客户端软件
示例应用:常见的网站和在线应用一般采用B/S架构,如电子商务网站、新闻网站等
C/S架构(Client/Server)
C/S架构(Client/Server Architecture)是指客户端/服务器架构。在C/S架构中,应用程序被分为客户端和服务器两个部分。
- 交互流程:在C/S架构中,客户端是安装在用户本地的软件,负责用户界面的显示和用户交互,用户可以在客户端上进行各种操作,客户端会将这些操作转换为请求,发送给服务器。服务器则负责接收客户端的请求,进行相应的处理,并返回结果给客户端。
- 适应场景:客户端软件需要在各个平台上进行开发和维护,适用于对性能和用户体验要求较高的应用场景。
- 示例应用: 桌面应用程序和移动应用程序采用C/S架构,如QQ、迅雷等APP。
在浏览器输入网址后请求的过程
在浏览器输入一个网址后,以下是请求的一般过程:
- DNS解析:浏览器首先会解析输入的网址中的域名部分,将域名解析为对应的IP地址。浏览器会向本地DNS服务器发送查询请求,如果本地DNS服务器没有缓存该域名对应的IP地址,则会向根DNS服务器逐级查询,最终获取到目标服务器的IP地址。
- 建立TCP连接:浏览器使用HTTP协议与目标服务器建立TCP连接。TCP连接的建立需要进行”三次握手”,即客户端向服务器发送连接请求,服务器回复确认连接请求,最后客户端再次回复确认。
- 向服务器发起HTTP请求:建立TCP连接后,浏览器会构建HTTP请求报文,包括请求行、请求头和请求体等信息。请求行中包含了请求方法(GET、POST等)、请求URL和协议版本等。请求头中包含了一些附加的信息,如Cookie、Referer、User-Agent等。请求体中通常包含了一些表单数据或上传的文件等内容。
- 服务器处理请求:目标服务器接收到浏览器发送的HTTP请求后,会进行请求的处理。服务器根据请求的URL找到对应的资源(如静态文件或动态程序),执行相应的操作。这可能涉及到数据库查询、业务逻辑处理等。
- 服务器发送HTTP响应:服务器处理完请求后,会生成HTTP响应报文,包括响应行、响应头和响应体等信息。响应行中包含了响应状态码(如200表示成功、404表示资源未找到等)和协议版本等。响应头中包含了一些附加的信息,如响应的内容类型、长度、缓存策略等。响应体中包含了服务器返回给浏览器的数据或页面内容。
- 接收响应并渲染页面:浏览器接收到服务器发送的HTTP响应后,会根据响应的内容进行页面渲染。如果响应是一个HTML页面,浏览器会解析HTML代码,并加载其中引用的其他资源(如CSS、JavaScript文件等)。最终,浏览器将页面展示给用户。
- 关闭TCP连接:当页面全部加载完成后,浏览器会关闭与服务器的TCP连接,释放资源。在后续的操作中,如果需要再次请求同一服务器的资源,浏览器会重新建立TCP连接。

Tomcat
常用的 Web 服 务 器
| web服务器 | 简介 |
|---|---|
| Tomcat | Apache组织提供的一种web服务器,提供对jsp和servlet的支持。轻量级的javaweb容器(服务器),当前应用最广的javaweb服务器(免费) |
| Jboss | 遵从javaEE规范的、开放源码的、纯java的ELB服务器,支持所有的javaEE规范(免费) |
| GlassFish | Oracle公司开发的一款Javaweb服务器,是一款强健的商业服务器,达到产品级质量(应用很少) |
Tomcat简介
Tomcat(全名为Apache Tomcat)是一个开源的、轻量级的Web应用服务器,由Apache软件基金会开发和维护。Tomcat可以作为Servlet容器、JSP容器和WebSocket容器
Tomcat特点
Tomcat具有以下几个主要特点:
- 轻量级:Tomcat是一个相对轻量级的Servlet容器,它具有较小的内存占用和快速启动的特点。由于其设计简单,它在资源消耗方面比一些其他大型JavaEE服务器(如WebLogic、WebSphere)更加节省。
- 独立性:Tomcat是一个独立的服务,可以独立于其他Web服务器(如Apache HTTP Server)运行。它可以作为独立的Servlet容器使用,也可以与其他Web服务器配合使用,通过反向代理或负载均衡实现更复杂的部署架构。
- 开源性:Tomcat是一个开源项目,代码完全公开,并且遵循Apache许可证。这意味着任何人都可以查看、使用和修改Tomcat的源代码,可以根据自己的需求进行定制和扩展,使得它具有较好的灵活性和可定制性。
- 可扩展性:Tomcat提供了可插拔的架构,允许用户通过添加或配置插件(例如Valve、Realm、Servlet等)来扩展其功能。这使得开发人员可以根据需要增加新的功能组件,或者替换默认的组件实现,以满足特定的需求。
- 易用性:Tomcat提供了一个简单易用的管理界面(Tomcat Manager),可以通过该界面对Web应用程序进行部署、启停和监控。它还支持热部署特性,在不重启服务器的情况下更新Web应用程序,方便开发和调试。无论是小型的个人网站还是大型的企业级应用,都可以选择Tomcat作为其运行环境。同时,许多Java Web框架都默认支持Tomcat,使得开发人员更容易上手和开发应用程序。
- 多协议支持:Tomcat不仅支持HTTP协议,还支持其他常用的网络协议,如HTTPS、AJP(Apache JServ Protocol)等。这使得Tomcat可以与其他应用程序和Web服务器进行协同工作,提供更灵活的部署方式。
- 多线程支持:Tomcat使用多线程技术来处理并发请求,提高系统的并发性能。它为每个请求创建一个独立的线程,这样可以同时处理多个请求,提升Web应用程序的吞吐量。
- 安全性支持:Tomcat提供了多种安全措施,例如基于角色的访问控制、SSL/TLS加密等。它通过配置文件和管理界面来管理用户认证、授权和安全设置,以确保Web应用程序的安全性。
- JSP支持:Tomcat还支持JavaServer Pages(JSP)技术。JSP是用于创建动态Web页面的Java标准,可以在其中嵌入Java代码和HTML标记。Tomcat可以编译和执行JSP页面,将其转化为Servlet并进行处理,从而生成最终的HTML响应。
- Java WebSocket支持:Tomcat对Java WebSocket API提供了支持,可以加载和执行WebSocket相关的类和方法,从而实现WebSocket通信功能。开发人员可以使用Tomcat来构建实时的双向通信应用程序。
- Servlet容器:Tomcat作为一个Servlet容器,它能够加载、实例化和管理Servlet组件。它接收来自客户端的HTTP请求,并将请求转发给相应的Servlet进行处理,然后将处理结果返回给客户端。Tomcat负责管理Servlet的生命周期、线程处理和请求-响应的过程。
Tomcat作用
Tomcat作为一个Servlet容器,在Java Web开发中具有以下主要作用:
- 提供Servlet容器环境:Tomcat是一个Servlet容器,遵循Java Servlet规范,能够运行Java编写的Servlet代码。
- 提供Servlet管理:Tomcat可以管理和处理Servlet的生命周期,包括初始化、加载、调用和销毁。
- 提供连接池管理:Tomcat可以管理数据库连接池,提供了一组API和配置选项,用于管理数据库连接的创建、复用和回收,从而提高数据库访问的效率和性能。
- URL映射:Tomcat接收来自客户端的HTTP请求,URL映射将客户端请求转发给相应的Servlet进行处理。这样,开发人员可以根据URL的不同将请求分发到不同的Servlet,实现灵活的请求处理机制。
- 运行JSP页面:Tomcat内置了JSP引擎,可以将JSP页面编译成Servlet,并在运行时动态地生成HTML响应。开发人员可以使用JSP编写动态的Web页面,通过Tomcat来解析和执行这些JSP页面。
- 处理静态资源:除了动态生成的Servlet和JSP页面,Web应用程序还可能包含静态资源,如HTML、CSS、JavaScript、图片等。Tomcat可以直接处理这些静态资源的访问,并将其发送给客户端,无需额外的配置或处理。
- Web应用部署:Tomcat提供了一个简单易用的管理界面(Tomcat Manager),允许用户对Web应用程序进行部署、启停和监控。开发人员可以通过Tomcat Manager来管理多个Web应用程序,进行版本管理和灰度发布等操作。
Tomcat目录介绍
1 | Tomcat |
IDEA添加Tomcat
准备工作
(1)使用maven骨架创建web项目,选中Create from archetype,搜索webapp

(2)生成的目录并不是完整的,可以自己添java目录、resources目录、test目录

(3)在pom.xml文件添加打包方法
1 | <!--<packaging>:打包方式标签(war表示是web项目,默认值是jar)--> |
打成war包后目录结构变化
1 | 1、编译后的java字节码文件和resources的资源文件,会放到WEB-INF下的classes目录下 |
方式一:集成本地Tomcat
(1)安装tomcat省略
(2)集成本地Tomcat到IDEA

其中级别update classes and resources最低,restart最高
| 模式 | 简介 |
|---|---|
| Update resources | 修改html、css、js后,执行更新 |
| Redeploy | 修改后台Java代码后,在不重新启动服务器的情况下,重建和重新部署应用程序构件,一般在更改java文件时使用。 |
| Update classes and resources | 重新编译所有更改的Java类(仅在debugging时)+更新所有更改过的资源,一般在更改.jsp文件时使用 |
| Restart server | 修改服务器配置(即配置文件)后,执行更新 |
(3)点击deployment,点右边的+的artifacts,选择war exploded,将开发项目部署项目到Tomcat中
| 模式 | 简介 |
|---|---|
| xxx.war | 发布模式,将项目打成war包,把war包发布到Tomcat服务器上, war模式部署成功后,Tomcat的webapps目录下会有部署的项目内容,这个一般是成品项目,也就是整个项目完成后才去做的 |
| xxx.war exploded | 展开部署,将WEB工程以当前文件夹的位置关系发布到Tomcat服务器上 war exploded模式部署成功后,Tomcat的webapps目录下没有,而使用的是项目的target目录下的内容进行部署 这个更适合我们测试的时候使用,所以虚拟目录应该用这个选项 |

方式二:Maven添加Tomcat插件
(1)在pom.xml中添加Tomcat插件
1 | <build> |
(2)使用Maven Helper插件快速启动项目

添加Tomcat报错解决
在右下角提示Error:Duplicate context path ‘/‘报错,原因是Tomcat下加入两个maven项目,同一个项目的war和exploded两个版本,因为不可能存在几个项目都发布到同一个地址下这里是’/‘,所以需要修改其他项目的 Application context即可

JavaWeb三大组件
JavaWeb 的三大组件分别是Servlet 程序、Filter过滤器、Listener 监听器
Servlet程序
Servlet简介
Servlet在Java Web开发中扮演着重要的角色,是一种用于在Web服务器上运行的Java程序组件
- 狭义Servlet:指Java语言中的javax.servlet.Servlet接口,这个接口定义了处理客户端请求和生成响应的方法
- 广义Servlet:指任何实现了javax.servlet.Servlet接口的类,包括通过实现该接口或继承已有实现的类来创建的Servlet类。
Servlet运行在服务器端,主要作用是使用Java语言与Servlet容器(如Tomcat)进行交互,处理Web请求和生成Web响应。
- 处理Web请求:Servlet可以接收来自客户端的HTTP请求,并根据请求的内容进行相应的处理。它可以读取请求参数、处理表单数据、解析请求头等。通过编写Servlet类,开发者可以定义自己的业务逻辑来处理不同类型的请求。
- 生成Web响应:Servlet可以根据业务逻辑和请求内容动态生成HTTP响应。它可以生成HTML页面、JSON数据、XML文档等各种形式的响应内容。开发者可以通过设置响应状态码、头信息和内容体等来构建合适的响应,以满足客户端的需求。
Servlet容器简介
- Servlet是一种用于在Web服务器上基于Java语言编写的服务器端程序,本身不能独立运行,需要在支持Servlet规范的容器中才能被加载和执行
- Servlet容器,也称为Web容器或Servlet引擎,提供了运行和管理Servlet的环境,可以加载和执行Java编写的Servlet代码
- 常见的Servlet容器有Apache Tomcat、Jetty、IBM WebSphere和Oracle WebLogic等。这些容器实现了Servlet规范,可以加载和执行Java编写的Servlet代码
Servlet与Tomcat关系
Tomcat 作为Servlet容器,负责处理客户请求,把请求传送给Servlet,并将Servlet的响应传送回给客户,而Servlet运行在服务器端,主要作用是使用Java语言与Servlet容器(如Tomcat)进行交互,处理Web请求和生成Web响应。Servlet需要依赖Tomcat才能运行,Tomcat 服务器和Servlet 版本的对应关系
| Tomcat版本 | Servlet/jsp版本 | javaEE版本 | 运行环境 |
|---|---|---|---|
| 4.1 | 2.3/1.2 | 1.3 | Jdk1.3 |
| 5.0 | 2.4/2.0 | 1.4 | Jdk1.4 |
| 5.5/6.0 | 2.5/2.1 | 5.0 | Jdk5.0 |
| 7.0 | 3.0/2.2 | 6.0 | Jdk6.0 |
| 8.0 | 3.1/2.3 | 7.0 | Jdk7.0 |
Servlet继承关系

| 关系 | 简介 |
|---|---|
| javax.servlet.Servlet接口 | Servlet体系根接口,有5个方法 |
| javax.servlet.Generic抽象类 | Servlet抽象实现类,对不常用的方法进行了空实现,未对service方法进行实现 |
| javax.servlet.http.HttpServlet抽象子类 | 继承Generic抽象实现类,对serivice方法重写,主要针对表单提交方式的重写 |
Servlet接口的五个方法
核心方法是init()、service()、destroy(),另外两个方法getServletInfo()和getServletConfig()使用的不是很多,了解即可
| 方法 | 简介 |
|---|---|
init() | 初始化方法,在Servlet被创建时执行,只执行一次 |
| getServletConfig() | 获取ServletConfig对象 |
service() | 服务方法,每次客户端发送请求,Servlet被访问都会调用该方法 |
| getServletInfo() | 该方法用来返回Servlet的相关信息,没有什么太大的用处,一般返回一个空字符串即可 |
destroy() | 销毁方法,当Servlet被销毁时,调用该方法。在内存释放或服务器关闭时销毁Servlet,只调用一次 |
Servlet生命周期
生命周期:指一个对象从被创建到被销毁的整个过程,对应Servlet中的三个方法:init()、service()、destroy()
| 生命周期 | 简介 |
|---|---|
| 加载和实例化(实例化) | 默认情况下,当Servlet第一次被访问时,Servlet调用构造方法(构造器)进行实例化 |
| 初始化(初始化) | 在Servlet实例化之后,容器将调用Servlet的init()方法初始化这个对象init()方法仅调用一次,用来加载配置文件、创建连接等初始化的工作 |
| 请求处理(服务) | 每次请求Servlet时,Servlet容器都会调用Servlet的service()方法对请求进行处理service()方法访问一次就会调用一次 |
| 服务终止(销毁) | 当需要释放内存或者容器关闭时,容器就会调用Servlet实例的destroy()方法完成资源的释放destroy()方法仅调用一次 |
Servlet的初始化时机
(1)Servlet的初始化时机默认是第一次接收请求时实例化、初始化,之后每次请求都会调用服务,直到销毁,如果创建Servlet比较耗时的话,那么第一个访问的人等待的时间就比较长,用户的体验就比较差
(2)可以设置初始化时机,解决这个问题
在web.xml中,设置初始化时机(xml方式)
1 | <!-- 指定servlet被创建的时机,设为负数则在第一次访问时创建、0或正数则在servlet加载进servlet容器时创建,且越小先被创建 --> |
使用@WebServlet注解中的loadOnstartup属性设置初始化时机(注解方式)
1 | // 指定servlet被创建的时机,设为负数则在第一次访问时创建、0或正数则在servlet加载进servlet容器时创建,且越小先被创建 |
Servlet注解开发
Servlet的配置是从3.0版本后开始支持注解配置(@WebServlet),3.0版本前只支持XML配置文件的配置方法,XML配置方式和注解比起来,麻烦很多,了解即可,建议使用注解来开发
| @WebServlet注解中的属性 | 描述 |
|---|---|
| name | 指定Servlet 的 name 属性,等价于 <servlet-name>。如果没有显式指定,则该 Servlet 的取值即为类的全限定名 |
| value | 该属性等价于 urlPatterns 属性。两个属性不能同时使用。 |
| urlPatterns | 指定一组 Servlet 的 URL 匹配模式。等价于<url-pattern>标签。 |
| loadOnStartup | 指定 Servlet 的加载顺序,等价于 <load-on-startup>标签。设为负数则在第一次访问时创建、0或正数则在servlet加载进servlet容器时创建,且越小先被创建 |
| initParams | 指定一组 Servlet 初始化参数,等价于<init-param>标签。 |
| asyncSupported | 声明 Servlet 是否支持异步操作模式,等价于<async-supported> 标签。 |
| description | 该 Servlet 的描述信息,等价于 <description>标签。 |
| displayName | 该 Servlet 的显示名,通常配合工具使用,等价于 <display-name>标签。 |
(1)使用Maven创建Web项目,pom文件导入Servlet依赖坐标
1 | <dependencies> |
(2)定义一个类,实现Servlet接口,并重写接口中所有方法
1 | //添加loadOnStartup属性并修改为0或者正整数,则会在服务器启动的时候调用init()方法 |
(3)启动Tomcat,浏览器中输入URL地址访问该Servlet
1 | http://localhost:8080//项目名称/@WebServlet注解路径 |
过滤器(Filter)
过滤器简介
过滤器(Filter)用于对请求和响应进行预处理和后处理。当客户端发送请求时,过滤器会先执行,然后再将请求传递给目标Servlet进行处理。同样,在目标Servlet处理完请求后,过滤器还可以对响应进行处理,最后将响应返回给客户端。
过滤器三要素
| 三要素 | 简介 |
|---|---|
| 拦截 | 过滤器之所以能够对请求进行预处理,关键是对请求进行拦截,把请求拦截下来才能够做后续的操作。 而且对于一个具体的过滤器,它必须明确它要拦截的请求,而不是所有请求都拦截。 |
| 过滤 | 根据业务功能实际的需求,看看在把请求拦截到之后,需要做什么检查或什么操作,写对应的代码即可。 |
| 放行 | 过滤器完成自己的任务或者是检测到当前请求符合过滤规则,那么可以将请求放行。 所谓放行,就是让请求继续去访问它原本要访问的资源。 |
过滤器链
(1)多个Filter的拦截范围如果存在重合部分,那么这些Filter会形成Filter链。

(2)过滤器链执行顺序
1 | 1、浏览器请求重合部分对应的目标资源时,会依次经过Filter链中的每一个Filter。 |
过滤器生命周期
| 生命周期阶段 | 执行时机 | 执行次数 |
|---|---|---|
| 创建对象 | Web应用启动时 | 一次 |
| 初始化 | 创建对象后 | 一次 |
| 拦截请求 | 接收到匹配的请求 | 多次 |
| 销毁 | Web应用卸载前 | 一次 |
过滤器开发步骤
(1)定义类,实现javax.servlet.Filter接口,实现其中的三个方法:init、doFilter、destroy
(2)配置Filter,可以通过xml文件或注解配置,推荐注解
(3)在doFilter()方法中执行过滤,满足过滤条件使用 chain.doFilter(request, response);放行,如果不满足过滤条件转发或重定向请求
过滤器匹配规则
| 规则 | 简介 |
|---|---|
| /index.html | 拦截具体的资源,只有访问index.html时才会被拦截 |
| /test/* | 目录拦截,访问/test下的所有资源,都会被拦截 |
| *.png | 后缀名拦截,访问后缀名为png的资源,都会被拦截 如果前杠后缀,星号在中间,/.png配置启动Web应用时会抛出异常 java.lang.IllegalArgumentException: Invalid /.png in filter mapping |
| /* | 拦截所有,访问所有资源,都会被拦截 |
过滤器使用案例
需求:请求参数message是否等于monster,等于则使用 chain.doFilter(request, response);放行,不等于则将请求跳转到另外一个页面
1 | /** |
监听器(Listener)
监听器简介
Listener监听器用于监听Web应用中的事件,并在事件发生时执行相应的操作。它实现了一种观察者模式,用于观察和响应特定的事件。
监听器分类
(1)Servlet规范中定义了9个监听器接口,可以用来监听ServletContext、HttpSession 和 ServletRequest 对象的生命周期和属性变化事件
| 监听器 | 简介 |
|---|---|
| ServletContext监听器 | 监听ServletContext对象的创建与销毁、以及属性的变化 |
| HttpSession监听器 | 监听HttpSession对象的创建与销毁、以及属性的变化 |
| HttpServeltRequest监听器 | 监听HttpServeltRequest对象的创建与销毁、以及属性的变化 |
(2)监听器Listener按照监听的事件可以分成3大类,分别为:监听对象创建和销毁的监听器、监听对象中属性变更的监听器、监听 HttpSession 中的对象状态改变的监听器
监听对象创建和销毁的监听器
| 事件源 | 监听器 | 监听器描述 |
|---|---|---|
| ServletContext | ServletContextListener | 用于监听 ServletContext 对象的创建与销毁过程 |
| HttpSession | HttpSessionListener | 用于监听 HttpSession 对象的创建和销毁过程 |
| ServletRequest | ServletRequestListener | 用于监听 ServletRequest 对象的创建和销毁过程 |
监听对象中属性变更的监听器
| 事件源 | 监听器 | 监听器描述 |
|---|---|---|
| ServletContext | ServletContextAttributeListener | 用于监听 ServletContext 对象的属性新增、移除和替换 |
| HttpSession | HttpSessionAttributeListener | 用于监听 HttpSession 对象的属性新增、移除和替换 |
| HttpServletRequest | ServletRequestAttributeListener | 用于监听 HttpServletRequest 对象的属性新增、移除和替换 |
监听HttpSession中的对象状态改变的监听器
| 监听器 | 简介 |
|---|---|
| HttpSessionBindingListener | 用于监听 JavaBean 对象绑定到 HttpSession 对象和从 HttpSession 对象解绑的事件 |
| HttpSessionActivationListener | 用于监听 HttpSession 中对象活化和钝化的过程 |
四大作用域
JavaWeb的四大作用域为PageContext页面域、ServletRequest请求域、HttpSession会话域、ServletContext应用域(全局域)
| 作用域 | 简介 |
|---|---|
| PageContext | 作用范围是整个JSP页面,是四大作用域中最小的一个;生命周期是当对JSP的请求时开始,当响应结束时销毁 |
| ServletRequest | 作用范围是一次请求响应范围 |
| HttpSession | 作用范围是一次会话 |
| ServletContext | 作用范围是整个Web应用,一次应用程序范围有效,全局 |
PageContext页面域
在使用的视图是JSP的时候,域对象有4个,使用Thymeleaf的时候,域对象有3个,没有pageContext
| 页面域 | 简介 |
|---|---|
| 生命周期 | 访问jsp页面时创建,访问结束时销毁 |
| 作用范围 | 当前jsp页面 |
| 功能 | 在整个jsp页面共享数据 |
ServletRequest请求域
| 请求域 | 简介 |
|---|---|
| 生命周期 | 一次请求开始时创建,结束时销毁 |
| 作用范围 | 一次请求响应范围 |
| 功能 | 在整个请求链共享数据 |
HttpSession会话域
| 会话域 | 简介 |
|---|---|
| 生命周期 | 创建、销毁(超时销毁、主动杀死)、意外身亡(服务器宕机) |
| 作用范围 | 整个会话 |
| 功能 | 在整个会发范围内共享数据 |
ServletContext应用域
| 应用域 | 简介 |
|---|---|
| 生命周期 | web应用启动时创建,web应用销毁时销毁 |
| 作用范围 | 整个web应用 |
| 功能 | 在整个web应用中共享数据 |
请求与响应
请求(request)
HTTP请求数据总共分为三部分内容,分别是请求行、请求头、请求体
获取请求行数据
| 方法 | 描述 |
|---|---|
| getMethod() | 获取请求的HTTP方法 |
| getRequestURI() | 获取请求的URI路径部分 |
| getRequestURL() | 获取请求的完整URL |
| getProtocol() | 获取请求使用的协议 |
| getScheme() | 获取请求的协议 |
| getQueryString() | 获取请求的查询字符串部分 |
| getServletPath() | 获取请求的Servlet路径部分 |
获取请求头数据
| 方法 | 描述 |
|---|---|
| getHeader(String name) | 获取指定名称的请求头部的值 |
| getHeaders(String name) | 获取指定名称的请求头部的所有值 |
| getIntHeader(String name) | 获取指定名称的请求头部的整数值 |
| getDateHeader(String name) | 获取指定名称的请求头部的日期值 |
| getContentType() | 获取请求的Content-Type头部的值 |
| getContentLength() | 获取请求的Content-Length头部的值 |
获取请求参数
| 方法 | 描述 |
|---|---|
| getParameter(String name) | 获取指定名称的请求参数的值(单个值) |
| getParameterValues(String name) | 获取指定名称的请求参数的所有值(数组) |
| getParameterMap() | 获取所有请求参数的映射(Map集合) |
获取请求体数据
| 方法 | 简介 |
|---|---|
| getInputStream() | 获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法 |
| getReader() | 获取字符输入流,如果前端发送的是纯文本数据,则使用该方法 |
获取Cookie
| 方法 | 描述 |
|---|---|
| getCookies() | 获取请求中的所有Cookie |
获取远程地址
| 方法 | 描述 |
|---|---|
| getRemoteAddr() | 获取客户端的IP地址 |
| getRemoteHost() | 获取客户端的主机名 |
| getRemotePort() | 获取客户端的连接端口 |
| getRemoteUser() | 获取客户端的用户名(如果有认证) |
获取会话
| 方法 | 描述 |
|---|---|
| getSession(boolean create) | 获取会话对象,如果不存在是否创建 |
| getSession() | 获取会话对象,如果不存在则创建一个新的会话 |
获取认证
| 方法 | 描述 |
|---|---|
| getUserPrincipal() | 获取请求的用户主体(已认证的用户) |
| isUserInRole(String role) | 检查请求的用户是否具有指定角色 |
获取其他
| 方法 | 描述 |
|---|---|
| getLocale() | 获取请求的语言环境 |
| getLocales() | 获取请求支持的所有语言环境 |
request请求域
| 方法 | 简介 |
|---|---|
| setAttribute(String name,Object value); | 存(怎么向ServletContext请求域中存数据) |
| getAttribute(String name); | 取(怎么从ServletContext请求域中取数据) |
| removeAttribute(String name); | 删(怎么删除ServletContext请求域中的数据) |
请求转发相关方法
| 方法 | 简介 |
|---|---|
| getRequestDispatcher(String path) | 根据转发的资源路径path得到转发器RequestDispatcher |
响应(response)
响应消息就是服务器响应给客户端的消息内容, 也叫做响应报文,主要由响应行、响应头部和响应体3个部分组成
设置响应头
| 方法 | 简介 |
|---|---|
| addHeader(String name, String value) | 设置HTTP响应头字段,name指定字段名称,value指定字段值,可以增加同名的响应头字段 |
| setHeader(String name, String value) | 设置HTTP响应头字段,name指定字段名称,value指定字段值,会覆盖同名的头字段 |
| setContentLength(int len) | 设置响应消息的实体内容的大小,单位为字节,即设置Content-Length字段的值 |
| setContentType(String type) | 设置Servlet输出内容的MIME类型,即设置Content-Type字段的值 |
| setCharacterEncoding(String charset) | 设置输出内容字符编码,即设置Content-Type字段的值,该方法优先级比setContentType的高 |
| sendRedirect(String location) | Servlet请求重定向 |
响应体
通过输出流, 通过Response得到网络输出流
| 方法 | 简介 |
|---|---|
| getOutputStream() | 得到响应字节输出流,万能流 |
| getWriter() | 得到响应字符输出流,输出字符 |
响应状态码
| 方法 | 简介 |
|---|---|
| setStatus(int sc) | 设置响应消息状态码,Web服务器默认产生一个状态码为200的状态行 |
| sendError(int sc) | 发送表示错误信息的状态码 |
| sendError(int sc, String msg) | 发送表示错误信息的状态码和错误提示信息 |
Response响应字符数据案例
创建一个类响应字符数据
1 |
|
Response响应字节数据案例
(1)pom.xml添加依赖
1 | <!-- 处理IO的工具类包 --> |
1 |
|
请求转发与重定向
| 转发与重定向 | 简介 |
|---|---|
| 请求转发 | 一次请求,一次响应,浏览器地址不发生变化,参数不会丢失,只能访问内部资源,由于只创建了一次客户端和服务器的链接,相对而言转发会比较节省网络资源 |
| 请求重定向 | 二次请求,二次响应,浏览器地址发生变化,参数会丢失,可以定向到任何资源 |
请求转发(forward)
请求转发是一种在服务器内部的资源跳转方式,本质是转交,在请求的处理过程中,Servlet完成了自己的任务,需要把请求转交给下一个资源继续处理
请求转发的流程

(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求
(2)资源A处理完请求后将请求发给资源B
(3)资源B处理完后将结果响应给浏览器
(4)请求从资源A到资源B的过程就叫请求转发
请求转发的特点
- 浏览器地址栏路径不发生变化,且只能转发到当前服务器的内部资源,不能从一个服务器通过转发访问另一台服务器
- 一次请求响应的过程,对于客户端而言,内部经过了多少次转发,客户端是不知道的
请求转发的实现方式
| 方法 | 简介 |
|---|---|
| request.getRequestDispatcher(“资源B路径”).forward(request,response); | 将请求转发到B路径 |
请求转发的案例
(1)创建一个类,将数据存入request域对象中,然后转发
1 | //添加loadOnStartup属性并修改为0或者正整数,则会在服务器启动的时候调用init()方法 |
(2)创建另一个类,接收转发并从request域对象中获取数据,并将数据打印到控制台
1 | //添加loadOnStartup属性并修改为0或者正整数,则会在服务器启动的时候调用init()方法 |
(3)启动Tomcat,访问http://localhost:8080/ServletA ,路径没有变化,控制台打印如下
1 | 获取请求... |
请求重定向(redirect)
Response重定向是一种资源跳转方式,本质是一种特殊的响应,在请求的处理过程中,Servlet完成了自己的任务,然后以一个响应的方式告诉浏览器:“要完成这个任务还需要你另外再访问下一个资源”
请求重定向的流程

(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求
(2)资源A现在无法处理该请求,就会给浏览器响应一个302的状态码+location的一个访问资源B的路径
(3)浏览器接收到响应状态码为302就会重新发送请求到location对应的访问地址去访问资源B
(4)资源B接收到请求后进行处理并最终给浏览器响应结果,这整个过程就叫重定向
请求重定向的特点
(1)浏览器地址栏路径发生变化,客户端可以知道请求URL有变化,当进行重定向访问的时候,由于是由浏览器发送的两次请求,所以地址会发生变化
(2)可以重定向到任何位置的资源(服务内容、外部均可),因为第一次响应结果中包含了浏览器下次要跳转的路径,所以这个路径是可以任意位置资源。
(3)两次请求响应的过程,不能在多个资源使用request共享数据,因为浏览器发送了两次请求,是两个不同的request对象,就无法通过request对象进行共享数据
请求重定向的实现方式
对于转发来说,因为是在服务端进行的,所以不需要加虚拟目录,但对于重定向,路径最终是由浏览器来发送请求,需要添加虚拟目录
1 | // 动态获取虚拟目录(项目根路径) |
请求重定向的案例
(1)创建一个类设置重定向
1 | //添加loadOnStartup属性并修改为0或者正整数,则会在服务器启动的时候调用init()方法 |
(2)另一个类接收重定向
1 | //添加loadOnStartup属性并修改为0或者正整数,则会在服务器启动的时候调用init()方法 |
(3)启动Tomcat,访问http://localhost:8080/ServletRedirect,会发现路径发生变化,重定向为http://localhost:8080/ServletTest,同时控制台打印如下
1 | 设置重定向.... |
MVC与三层架构
架构思想
架构的分类
对于“架构”来讲,理论上划分了5种架构视图,分别是:逻辑架构、开发架构、运行架构、物理架构、数据架构。
| 分类 | 简介 |
|---|---|
| 逻辑架构 | 逻辑架构关注的是功能,包含用户直接可见的功能,还有系统中隐含的功能,偏向日常所理解的“分层”,把一个项目分为“表现层、业务逻辑层、数据访问层”这样经典的“三层架构”。 |
| 开发架构 | 开发架构则更关注程序包,不仅仅是我们自己写的程序,还包括应用程序依赖的SDK、第三方类库、中间价等 |
| 运行架构 | 应用程序运行中可能出现的一些问题,例如:高并发、多线程 |
| 物理架构 | 系统、网络、服务器等基础设施 |
| 数据架构 | 数据持久化和存储层面的问题,关系型数据库与非关系型数据库的选择问题,例如:数据的分布、复制、同步等 |
为什么需要架构
(1)以前系统简单,一个应用部署在一台服务器上,且大部分开发工作是CRUD,应用结构简单,且易于维护
(2)随着系统业务复杂度越来越高,功能模块越来越庞大,耦合度也越来越高,导致系统的复杂度越来越不可控
(3)为了更好的降低应用及模块间的耦合度,诞生了一些熟知的网络架构(分布式微服务)和应用架构(三层架构、MVC架构),使用框架的好处就是结构清晰易于维护
MVC架构
MVC设计模式简介
MVC是一种软件架构的思想,将软件按照模型、视图、控制器来划分
- 模型(Model):模型表示应用程序的数据和业务逻辑
- 视图(View):视图负责展示模型中的数据给用户,并接受用户的输入
- 控制器(Controller):控制器作为模型和视图之间的中介,处理用户的请求并协调模型和视图的交互
MVC的工作流程
- 用户发送请求:用户在浏览器中输入URL或者与应用程序进行交互,发送请求给服务器。
- 控制器接收请求:服务器接收到请求后,控制器(通常是一个Servlet)负责接收并处理请求。控制器根据请求的类型和参数,选择合适的处理方法。
- 模型处理请求:控制器根据请求的类型和参数,调用相应的模型来处理数据。模型负责处理业务逻辑,包括数据的获取、处理、验证、存储等操作。
- 视图展示数据:模型处理完数据之后,将处理结果返回给控制器。控制器根据处理结果选择适当的视图来展示数据。视图负责将数据渲染成可视化的界面供用户查看。
- 用户与视图交互:用户在浏览器中与视图进行交互,例如填写表单、点击按钮等。用户的操作可能会触发新的请求。

三层架构
三层架构的简介
为了符合高内聚,低耦合思想,可以把各个功能模块划分为了表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)三层架构。三层架构是一种软件设计模式,将应用程序按照功能和责任划分为三个独立的层次,每个层次都有自己的职责和功能,且彼此之间独立操作,提高了系统的可维护性、可扩展性和可测试性。通常由以下三个层级组成:
- 表示层(Presentation Layer):表示层是系统与用户进行交互的界面部分,包括用户界面(如Web页面、移动应用界面、桌面应用界面等)和用户输入处理逻辑。主要作用是
将用户的请求传递给业务逻辑层,并将处理结果展示给用户 - 业务逻辑层(Business Logic Layer):业务逻辑层是应用程序的核心部分,包含了应用程序的业务规则、算法、流程等。主要作用是
处理来自表示层的请求,调用数据访问层提供的数据实现系统的业务逻辑 - 数据访问层(Data Access Layer):数据访问层是与数据存储系统(如数据库或文件系统)交互的部分,包括数据的存储、检索、更新等操作。主要作用是
与数据存储系统(如数据库或文件系统)交互进行交互,执行对数据的增删改查等操作,并将操作结果返回给业务逻辑层。
(2)在三层架构程序设计中,采用面向接口编程。各层之间采用接口相互访问,并通过对象模型的实体类(Model)作为数据传递的载体
(3)层是一种弱耦合结构,层与层之间的依赖是向下的,上层对下层的调用,是通过接口实现的,而真正提供服务的是下层的接口实现类。服务标准接口是相同的,而实现类是可以替换的,这样就实现了层与层间的解耦
三层架构的关系
三层架构的关系:控制层 调用 业务层 处理业务逻辑,业务层调用 Dao 持久化数据,简单调用流程如下
用户访问浏览器向服务端发送请求,浏览器收到响应的数据展示页面(前端页面)
↓ ↑
表现层Controller接收请求,向下调用业务逻辑层Service处理业务逻辑,向上封装结果返回给客户端
↓ ↑
业务层Service处理业务逻辑,向下调用数据访问层Dao操作数据,向上为表现层提供处理结果
↓ ↑
数据访问层Dao向下操作数据库数据,向上为业务逻辑层提供数据

三层架构对应的包和框架
| 三层架构 | 对应包 | 对应框架 |
|---|---|---|
| 表现层 | controller包或web包 | SpringMVC、Struts2 |
| 业务逻辑层 | service包 | Spring |
| 数据访问层 | dao包或mapper包 | Mybatis |
Servlet案例回顾
JavaWeb时做的水果商店案例回顾,基础代码省略,仅保留核心思想与过程
基础水果商店
基础版本中,使用了多个Servlet,一个请求对应一个Servlet
1 | IndexServlet、AddServlet、EditServlet、DelServlet、UpdateServlet |

优化水果商店
(1)由于Servlet太多,可以将多个Servlet合并成一个FruitServlet
1 | IndexServlet、AddServlet、EditServlet、DelServlet、UpdateServlet -> 合并成FruitServlet |

(2)合并成一个FruitServlet后,需要前端多传递一个operate参数与方法名对应,后端接收到operate的值是什么,表明需要调用对应的方法进行响应,如果找不到对应的方法,则抛异常。可以使用switch-case,通过一个operate的值来决定调用FruitServlet中的哪一个方法
1 | // 获取前端传递的operate |
(3)随着项目的业务规模扩大,会有很多的Servlet,意味着会有很多的switch-case,从而造成代码冗余,此时可以使用反射技术,根据方法名的对象,调用类中对应的方法
1 | // 获取前端传递的operate |
引入中央控制器DispatcherServlet
虽然使用了反射技术,但每一个servlet中都有类似的反射技术的代码,因此可以继续抽取,设计中央控制器类:DispatcherServlet

根据url定位controller组件
(1)假设有多个xxxServlet,可以将xxxServlet改名为xxxController,可以创建一个xml文件,在bean标签中,以id属性对应方法名,class属性对应指定包下的类
1 |
|
(2)创建中央控制器DispatcherServlet类,继承HttpServlet,在初始化方法init()中,通过DOM技术解析XML文件,将解析到的id和class属性对应类的实例对象存放到Map集合类型的beanMap容器中
1 | // 定义Map容器 |
(3)从url中提取路径servletPath,对应xml文件中的id(/fruit.do —> fruit)
1 | // 获得请求servlet服务的路径(/xxx.do) |
(4)从beanMap容器中根据路径fruit(id)获取到对应的组件实例FruitController(class)
1 | // 根据路由名称(对应xml中的id),获取对应类的实例。即在Map集合中,根据key获取value |
(5)通过反射,根据组件实例获取实例中的所有方法
1 | // getDeclaredMethods():返回类中(类自身)所有的实例方法,包含public、protected和private方法。 |
(6)获取前端的operate的值,遍历所有的实例方法,若方法与operate相同则进行后续处理,否则抛出异常
1 | // 获取前端传递的operate(用于区分方法) |
调用Controller组件中的方法
(1)由于已经遍历了所有的方法,所以可以统一获取请求参数,并做统一处理(获取即将要调用的方法的参数信息,存放到参数数组)此处只考虑了具体逻辑,另外需要考虑参数的类型问题,详见具体代码
1 | // 统一获取请求参数:获取即将要调用的方法的参数签名信息,返回参数数组 |
(2)执行对应的方法
1 | // invoke(Object obj, Object… args):组件中的方法调用,方法对象.invoke(对象,方法参数) |
(3)视图处理
1 | // 根据执行方法的返回值,做出对应的重定向或页面定位 |
引入IOC控制反转和DI依赖注入(工厂模式)
由于层与层之间调用时,都需要使用new创建对象,导致层与层之间具有耦合性,可以使用IOC控制反转和DI依赖注入实现解耦
(1)创建BeanFactory接口用于根据配置文件获取bean对象
1 | /** |
(2)让中央控制器类实现BeanFactory接口重写getBean()
1 |
|
(3)在中央控制器的init()初始化bean工厂
1 | // 注入 |
(4)使用bean工厂造指定类的对象
1 | beanFactory.getBean(xxx); |
引入事务管理(代理模式)
事务是逻辑上的一组操作,要么都执行,要么都不执行
(1)定义工具类,用来创建MySQL连接对象、获取MySQL连接对象、关闭MySQL连接对象
1 | /** |
(2)使用工具类实现MySQL的开启事务、提交事务、回滚事务
1 | /** |
(3)定义事务过滤器,用来在将一个业务逻辑作为整体,要么都执行,要么都不执行
1 | /** |





