JavaEE

首先JavaEE就是在之前JavaSE本地运行的基础上,增加了企业级Web应用中的技术标准,也就是说现在JavaEE可以开发WEB应用了。

JavaEE平台包含了13个技术规范

image-20251028185502277

JAVEE阶段需要学习的核心技能

Servlet、JSP、JSTL/EL、JavaBean、MVC模式、过滤器Filter、监听器listener、Ajax 分页

然后既然是JavaEE开发那么就需要有个服务器,然后再利用JavaEE的库来开发web项目,然后常用的Web容器有Tomcat和Jetty

WEB应用运行流程:

  1. 用户访问 http://localhost:8080/hello
  2. 请求到达 Tomcat(Web 容器)
  3. Tomcat 根据 web.xml 或注解,找到对应的 Servlet
  4. Servlet 处理请求,可能调用 Service → DAO → 数据库
  5. 处理完成后,跳转到 JSP 页面(View)
  6. JSP 被编译成 Servlet,结合 JSTL/EL 渲染 HTML
  7. 返回 HTML 响应给浏览器
  8. Filter 可能在请求前后做日志、编码、权限检查
  9. Listener 可能在应用启动时初始化数据库连接池

Tomcat

那么我们安装了Tomcat就类似于我们有了一个应用服务器了,那么我们的项目要在里面部署。

具体Tomcat怎么实现就不需要我们了解了,然后我们要了解Tomcat怎么部署,先了解Tomecat的目录结构与介绍。

image-20251028191514874

Tomcat目录介绍

  • bin 目录 主要是用来存放tomcat的命令文件,命令文件分为 .sh结尾的linux命令,和.bat结尾的windows命令

  • conf 目录 里面有很多xml 主要用来存放tomcat的配置文件

  • lib 目录 主要用来存放tomcat运行需要加载的jar包类似于库
  • logs 目录用来存放日志文件
  • temp 目录 用来存放运行产生的临时文件
  • webapps 目录 用来存放应用程序,服务器启动时会加载这个目录下的应用程序,应用程序可以以文件夹、war包的形式发布应用。
  • work 目录 用来存放tomcat在运行时 编译后的文件,比如jsp 编译后的文件。

看到这里会有疑惑jar 包和war 包有什么区别

简单理解就是Jar包是打包java类库或者独立应用程序,类似于exe

而war包是打包的一个java web应用 需要部署到web容器里面才能运行。

Tomcat部署项目

webapps里面

首先在webapps里面创建自己的项目目录,然后项目目录里面有静态资源比如html还有各种img就部署好了

image-20251028192910480

然后根据url就能访问到我们部署的资源了

不在webapps里面

这个需要在conf目录下修改噢诶之文件,然后这样就会访问我们指定的路径从而访问到我们的项目了

ocalhost中添加配置文件


建议配置文件名和项目名相同

image-20251028193212257

Tomcat 常见配置

之前说到配置这里就需要了解tomcat的配置文件了,在conf目录下常见的配置文件

  • context.xml 这个是Tomcat的公用的环境配置比如数据库连接池、日志路径、临时目录路径等公共环境。Tomcat会定时扫描这个文件,一旦发现文件被修改(时间戳变了),就会自动重新加载这个文件,不需要重启服务器。

  • web.xml 是每个 Web 应用的配置文件,位于 WEB-INF/ 目录下。它定义了 Servlet、Filter、Listener、欢迎页等核心行为。
    $CATALINA_HOME/conf/web.xml 是 Tomcat 提供的全局默认配置,所有应用在没有明确配置时,会使用这里的默认值

  • server.xml 是tomcat它是 Tomcat 服务器的主配置文件,定义了整个服务器的架构和行为。你可以把它想象成 Tomcat 的“大脑”或“蓝图”,它决定了:

    • Tomcat 启动几个“服务”
    • 监听哪些端口
    • 部署哪些 Web 应用
    • 如何处理请求
  • tomcat-users.xml 它定义了可以访问 Tomcat 管理界面的用户、密码和角色。Tomcat 自带几个管理页面:

    • Manager App:部署、启动、停止 Web 应用
    • Host Manager:管理虚拟主机

    要访问这些页面,就需要在 tomcat-users.xml 中配置用户。

下面举个例子把配置串起来

假设现在要在一台服务器上用tomcat搭建两个系统“

1、员工管理系统

访问地址http://hr.techcorp.com:8080/hr-app

2、客户支持系统

访问地址 http://support.techcorp.com:8080/support-app

第一步配置server.xml 这个决定了整个tomcat如何运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<Server port="8005" shutdown="SHUTDOWN">
<Service name="Catalina">

<!-- HTTP 连接器:监听 8080 端口 -->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />

<!-- 核心引擎 -->
<Engine name="Catalina" defaultHost="localhost">

<!-- 虚拟主机 1:hr.techcorp.com -->
<Host name="hr.techcorp.com" appBase="webapps-hr"
unpackWARs="true" autoDeploy="true">
<Context path="/hr-app" docBase="hr-app" reloadable="true"/>
</Host>

<!-- 虚拟主机 2:support.techcorp.com -->
<Host name="support.techcorp.com" appBase="webapps-support"
unpackWARs="true" autoDeploy="true">
<Context path="/support-app" docBase="support-app" reloadable="true"/>
</Host>

<!-- 默认主机(备用) -->
<Host name="localhost" appBase="webapps"/>

</Engine>
</Service>
</Server>
  • 定义了两个虚拟主机hr.techcorp.comsupport.techcorp.com
  • 每个主机有自己的应用目录(webapps-hrwebapps-support),避免混乱
  • 监听 8080 端口接收请求
  • 每个 Web 应用(如 /hr-app)都有自己的 <Context> 配置

第二步配置context.xml 两个系统都要访问同一个数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<Context>

<!-- 公用的数据库连接池(所有应用都可以用) -->
<Resource name="jdbc/TechCorpDB"
auth="Container"
type="javax.sql.DataSource"
maxTotal="20"
maxIdle="10"
maxWaitMillis="10000"
username="dbuser"
password="securepass123"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/techcorp_db"/>

</Context>
  • 在 Tomcat 启动时,创建了一个全局的数据库连接池

    hr-app和support-app都可以通过 JNDI 获取这个数据源:

    1
    DataSource ds = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/TechCorpDB");
  • 不需要每个应用自己管理数据库连接,统一、安全、高效

相当于公司建立了一个“公共数据库服务中心”,所有部门都可以申请连接,不用自己建。

第三步 配置web.xml 每个系统的内部规则

这里有两个系统所以需要有两个web.xml

示例 hr-app/WEB-INF/web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<web-app>

<!-- 系统名称 -->
<display-name>HR Management System</display-name>

<!-- 欢迎页 -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

<!-- 登录过滤器:检查用户是否已登录 -->
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>com.techcorp.hr.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- 员工信息 Servlet -->
<servlet>
<servlet-name>EmployeeServlet</servlet-name>
<servlet-class>com.techcorp.hr.servlet.EmployeeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>EmployeeServlet</servlet-name>
<url-pattern>/employee/*</url-pattern>
</servlet-mapping>

<!-- 全局参数 -->
<context-param>
<param-name>companyName</param-name>
<param-value>TechCorp</param-value>
</context-param>

</web-app>
  • 定义了这个应用的 URL 路由(/employee/*EmployeeServlet
  • 添加了登录检查过滤器
  • 设置了欢迎页
  • 使用了全局的数据库连接(来自 context.xml

第四步 配置tomcat-users.xml 文件位置 $CATALINA_HOME/conf/tomcat-users.xml

这个是决定谁可以登录管理后台

1
2
3
4
5
6
7
8
9
10
11
12
<tomcat-users>

<!-- 角色定义 -->
<role rolename="manager-gui"/> <!-- 可以部署应用 -->
<role rolename="admin-gui"/> <!-- 可以管理虚拟主机 -->
<role rolename="manager-script"/> <!-- 可以用脚本自动部署 -->

<!-- 用户配置 -->
<user username="ops_admin" password="OpsPass123!" roles="manager-gui,admin-gui"/>
<user username="ci_cd" password="AutoDeploy456" roles="manager-script"/>

</tomcat-users>
  • ops_admin可以登录:
    • http://hr.techcorp.com:8080/manager/html → 部署 hr-app.war
    • http://support.techcorp.com:8080/host-manager/html → 管理虚拟主机
  • ci_cd 是 Jenkins 用的账号,用于自动化部署

总结

image-20251029004421511

1、redirectPort有什么用?这个是用于如果某个请求本来应该走https的,但是现在走的是http,那么就会把它重定向到8433端口,然后再在server.xml中配置https的Connctor标签,否则跳过去也没人接。

2、配置了全局数据库连接池之后,如何进行数据库连接?

首先在web.xml中配置引用全局数据库资源,然后在dao层获取连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import java.sql.Connection;

public class EmployeeDAO {
public void saveEmployee(Employee emp) throws Exception {
// 1. 查找 JNDI 数据源
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource) envCtx.lookup("jdbc/TechCorpDB");

// 2. 获取连接(连接来自 Tomcat 维护的连接池)
try (Connection conn = ds.getConnection()) {
// 执行 SQL 操作
PreparedStatement ps = conn.prepareStatement("INSERT INTO employee ...");
ps.executeUpdate();
}
}
}

3、tomcat-users.xml是干什么的?

首先一般部署的时候我们是在linux服务器上,然后部署的tomcat,然后这时候如果没有root权限就可以随便修改,但是对于一个公司来说,就会分配权限了,没有root权限的人是看不到控制不了tomcat的,那么这时候tomcat自带了管理页面,内置了两个web应用,后期就会访问

  • http://localhost:8080/manager/html → 图形化部署 WAR 包
  • http://localhost:8080/host-manager/html → 查看虚拟主机

但如果你没在 tomcat-users.xml 中配置用户,访问时就会弹出登录框,拒绝你进入。然后这时候就需要账号和密码登录进去配置了。

对于远程的电脑,部署war包在tomcat上,既可以通过gui来部署,也可以通过脚本来传输war包来部署。

具体的其他问题和配置文本可以后期需要用的时候通过百度和自己的记录记一下。

Tomcat 的主要组件

image-20251029013508452

image-20251029013717199

Server组件 服务器根容器

一个server实例 就是一个JVM,一个物理机上如果启动了多个server实例,必须配置不同的端口,在server.xml中配置。

Service组件 服务组合

Service主要用于关联一个引擎和与此引擎相关的连接器。

Connector组件 连接器(接收请求)

支持处理不同请求的组件,一个引擎可以有一个或多个连接器,以适应多种请求方式。默认只开启了处理Http协议的连接器。如果需要使用其他协议,需要在Tomcat中配置该协议的连接器。

在Tomcat中连接器类型通常有4种:

1)HTTP连接器

2)SSL连接器

3)AJP 1.3连接器

4)proxy连接器

1
2
3
<Connector   port="8888" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />

port:监听的端口

protocol:连接器使用的协议,默认为HTTP/1.1;

connectionTimeout:等待客户端发送请求的超时时间,单位为毫秒;
redirectPort:如果某连接器支持的协议是HTTP,当接收客户端发来的HTTPS请求时,则转发至此属性定义的端口;

maxThreads:支持的最大并发连接数,默认为200个;

Engine组件 引擎(请求处理器)

Engine是Servlet处理器的一个实例,Engine需要defaultHost属性来定义一个接受所有发往非明确定义虚拟主机的请求的host组件。

假设url已经进入到tomcat里面但是服务访问的服务没有对应的服务给到他就会走这个defaultHost那么这个defaulthost也要配置一个对应的context给他

Host组件 虚拟主机

位于Engine容器中用于接受请求并且进行相应处理的虚拟主机。可以运行Servlet或者JSP来处理请求

<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">

name:虚拟主机的名称,Tomcat通过在请求URL中的域名与name中的值匹配,用于查找能够处理该请求的虚拟主机。如果未找到则交给在Engine中defaultHost指定的主机处理;

appBase:此Host的webapps目录,即指定存放web应用程序的目录的路径;

autoDeploy:在Tomcat处于运行状态时放置于appBase目录中的应用程序文件是否自动进行deploy;默认为true;

unpackWARs:在启用此webapps时是否对WAR格式的归档文件先进行展开;默认为true;

Context组件 Web 应用上下文

Context是Host的子标签,代表指定一个Web应用,它运行在某个指定的虚拟主机(Host)上;每个Web应用都是一个WAR文件,或文件的目录;

Servlet

上面讲到服务器级别的,现在我们了解的是Servlet是在Context里面的。然后Servlet是 单进程多线程的方式执行的

Servlet继承结构

首先我们写代码的时候需要用到servlet开发,也就是接收到前端传给我们的请求然后我们用Servlet进行接受和响应,那么这时候javaEE已经写好了类给我们进行使用了

image-20251029015937724

看到这个图后,可以看出实际开发的时候直接继承HttpServlet然后重写这个结构的doGet和doPost方法即可。里面还有个service方法,里面需要传封装好的请求和响应的对象。

Servlet生命周期

Servlet的生命周期是由容器管理的,分别经历四各阶段:

阶段 次数 时机

创建 1次 第一次请求

初始化 1次 实例化之后

执行服务 多次 每次请求

销毁 1次 停止服务

当前端请求到具体服务的Servlet时,容器就会实例化这个Servlt(tomcat已经帮我们写好了,我们只是重写了doGet或者doPost方法而已),然后调用Init方法,并在新的线程中执行service方法处理请求,处理结束后不会销毁而是缓存,当前端再次请求就会继续调用,在 Web 应用被卸载、Tomcat 正常关闭、或应用重新加载时被销毁

Servlet的请求和转发

当我们需要相应一个页面或者相应数据或者处理请求数据的时候我们就需要接收前端给我们的数据然后发送给前端(响应就是原路返回不需要我们配置)。

这时候我们还是继承HttpServlet这个类,然后重写service方法

1
2
3
4
5
6
@WebServlet(urlPatterns = "/servlet1.do")
public class Servlet1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servlet1 service invoked");
}

那么现在我们已经有了请求类和转发类了。我们要考虑的是转发,接受请求已经把路径配置好了。

了解转发之前需要了解 RequestDispatcher类

因为我们的接受请求和发送请求都在容器内部做了很多事情,所以我们不能直接将req和resp直接return给下一个类,如果需要把req和resp给下一个Servlet或者响应的话都需要这个RequestDispatcher类来帮我们传递。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
String username = req.getParameter("username");
String password = req.getParameter("password");

if ("admin".equals(username) && "123".equals(password)) {
// 登录成功,把请求“转发”给 welcome.jsp
req.setAttribute("user", username); // 传数据
RequestDispatcher rd = req.getRequestDispatcher("/welcome.jsp");
rd.forward(req, resp); // 🚚 快递员出发!
} else {
resp.getWriter().println("登录失败");
}
}
}

然后这个RequestDispatcher接受的数据是传送给的下一个页面,或者路径,然后就会根据路径转发给下一个页面或者servlet了。

然后这个类里面有两个转发方法。

forword转发

forword方法用来把后面的事情全部交给下一个,会把相应的缓冲区清空,完全让下一个目标来处理响应。

include转发

include方法不会清空,他是内容拼接。

当一个资源被 include 时,它不能改变响应的状态码或响应头

因为响应的状态码和响应头是由源 Servlet(即调用 include 的那个)主导设置

被包含的资源只能输出响应体(body),不能修改控制信息(header/status)

总结
对比项 forward() include()
控制权 完全交给目标资源 当前 Servlet 仍控制流程
执行后续代码 ❌ 不再执行 ✅ 继续执行
响应输出 目标资源生成完整响应 多个资源共同生成响应
能否先输出 ❌ 不能,否则报错 ✅ 可以先输出部分内容
能否多次调用 ❌ 一个请求只能 forward 一次 ✅ 可以 include 多个资源
典型用途 登录后跳转首页、MVC 视图渲染 页头、页脚、菜单、广告位
数据传递 通过 req.setAttribute() 通过 req.setAttribute()
URL 是否变化 ❌ 浏览器地址栏不变 ❌ 浏览器地址栏不变
客户端感知 不知道跳转 不知道内容是拼的

Servlet的重定向

重定向是一个servlet处理不了没然后返回地址让前端再次发送http请求。

这时候会有状态码302,然后用的是resp类的redirect方法,直接返回地址,这个时候如果用户点击请求过多可能会造成重复提交。

那为了解决这个可以用 PRG(post redirect get )模式 + Token机制

PRG的意思是发送post请求后跳转到一个get请求的页面,这样及时刷新页面也是刷新get请求不会修改数据,是一个幂等的效果很安全。但是这个防止不了一开始由于重复点击按钮导致的多次Post请求。

这时候用到了token,token一开始存在然后验证之后就删除,然后重定向,这时候如果多次点击,由于已经删除了,也没办法重复提交Post请求了。

会话

看到这里需要了解到Cookie和HttpSession了。

由于HTTP协议是一个无状态的协议,所以服务端并不会记录当前客户端浏览器的访问状态,但是在有些时候我们是需要服务端能够记录客户端浏览器的访问状态的,如获取当前客户端浏览器的访问服务端的次数时就需要会话状态的维持。在Servlet中提供了Cookie对象与HttpSession对象用于维护客户端与服务端的会话状态的维持。二者不同的是Cookie是通过客户端浏览器实现会话的维持,而HttpSession是通过服务端来实现会话状态的维持。

Cookie特点

1、用字符串存储数据

2、用Key Value结构存储

3、有大小限制

4、保存在浏览器内存上

5、Cookie可以持久化在磁盘上,也可以保存在内存上

6、浏览器每次发送请求都会携带Cookie

7、Cookie不支持中文如果需要中文需要转码,4.0后支持

Cookie对象的创建

Cookie cookie = new Cookie("key","value)

resp.addCookie(cookie)

通过New创建Cookie对象,然后通过HttpServletResponse对象将cookie写回给客户端浏览器

Cookie中数据的获取

Cookie[] cookies - request.getCookies()

状态Cookie和持久Cookie

持久化Cookie需要再代码里面手动调用setMaxAge(秒数),这样来设置为持久化Cookie,否则默认为状态Cookie。

状态Cookie会在会话结束后自动消除,浏览器关闭后销毁。

HttpSession

会话就是当浏览器第一次发送请求携带cookie的时候,然后服务端发现他没有jsessionid然后服务端就会创建一个jsessionid给cookie然后第二次请求就会携带者这个id的cookie发到服务端然后默认情况下会存在服务器内存中比如tomcat的jvm的堆内存中,如果是分布式系统会存到redis或者数据库中,那么想问这个操作是tomcat已经帮我们写好的这句话。当然sessionid是按需创建的如果我们没有调用request.getSeesion这个方法就不会创建JSESSIONID

特点

1、保存在服务端

2、可以存储任何类型的数据

3、key value结构,value是object类型

4、存储数据大小无限制

获取

session.setAttribute("key",value)

将数据存储到HttpSession对象中

Object value = session.getAttribute("key")

根据key获取HttpSession中的数据,返回Object

Enumeration<String> attributeNames = session.getAttributeNames()

获取HttpSession中所有的key,返回枚举类型

session.removeAttribute("key")

根据key删除HttpSession中的数据

String id = session.getId()

根据获取当前HttpSession的SessionID,返回字符串类型

销毁

两种:一种是通过web,xml中设定超时时间

第二种是在HttpSession对象中的invalidate方法销毁当前的Session对象。

域对象

什么是域对象,就是能够存储数据,获取数据,传递数据的对象。

这些对象都是认为定好的,根据生效“范围”来区别

Request域 HTTPServletRequest 一次请求/请求转发
Session域 HTTPSession 一次会话(跨请求)
Application域 ServletContext 任意一次请求和会话(跨会话)

setAttribute(name,value); 设置修改数据
getAttribute(name);获得数据的方法
removeAttribute(name);移除数据的方法

JSP四大域对象
Page域
Request域
Session域
Application域

Application就是当前web服务内,跨请求,跨会话,直到项目关闭才会销毁。

过滤器和监听器

过滤器

image-20251029041314893

它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理。使用Filter的完整流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。

Filter接口中有一个doFilter方法,当开发人员编写好Filter,并配置对哪个web资源进行拦截后,Web服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,doFilter方法中有一个filterChain对象,用于继续传递给下一个filter,在传递之前我们可以定义过滤请求的功能,在传递之后,我们可以定义过滤响应的功能

使用过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class MyFilter implements Filter {
// 初始化方法
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
// 作出过滤的方法
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Filter doFilter 对请求作出过滤");
// 通过一行代码 放行请求
// 放行请求,交给过滤器链继续进行过滤 最后到达资源
filterChain.doFilter(servletRequest, servletResponse);

System.out.println("Filter doFilter 对响应作出过滤");

servletResponse.getWriter().print("filter 追加一些数据");
}
// 销毁方法
@Override
public void destroy() {
}
}

写完代码后在web.xml中配置对那些请求进行过滤以及配置过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<filter>
<filter-name>filter1</filter-name>
<filter-class>com.filter.MyFilter1</filter-class>

</filter>
<filter>
<filter-name>filter2</filter-name>
<filter-class>com.filter.MyFilter2</filter-class>
</filter>
<!--这里的顺序决定了过滤器的顺序-->
<filter-mapping>
<filter-name>filter2</filter-name>
<url-pattern>/myServlet1.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/myServlet1.do</url-pattern>
</filter-mapping>
</web-app>

生命周期

1 WEB 容器启动时,会对Filter进行构造并初始化 一次
2 每次请求目标资源时,都会执行doFilter的方法
3 WEB容器关闭是,会销毁Filter对象

决定过滤器的执行顺序是由filter-mapping标签决定

注解

image-20251029042030649

监听器

类似于前端的事件绑定,java中的监听器用于监听web应用中某些对象、信息的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。常用于统计在线人数和在线用户,系统加载时进行信息初始化,统计网站的访问量等等。

监听器怎么分类?

按监听的对象划分

a.ServletContext对象监听器

b.HttpSession对象监听器

c.ServletRequest对象监听器

按监听的事件划分

a.对象自身的创建和销毁的监听器

b.对象中属性的创建和消除的监听器

c.session中的某个对象的状态变化的监听器

一共有哪些监听器?分别处理的是什么事情?

java中一共给我们提供了八个监听器接口,分别用于监听三个域对象,每个监听器都有专门监听的事件

Request

ServletRequestListener (处理request对象创建和销毁)
ServleRequestAttributeListener (处理域对象中的数据添加 替换 删除)

Session

HttpSessionListener (处理session对象创建和销毁)
HttpSessionAttributeListener (处理session域对象中的数据添加 修改 删除)
HttpSessionBindingListener (处理session对象监听器绑定和解绑定接口)
HttpSessionActivationListener (处理session对象钝化和活化状态接口)

Application

ServletContextListener (处理application对象创建和销毁)
ServletContextAttributeListener (处理application域对象中的数据添加 修改 删除)

监听器如何使用?

两步走使用

1定义监听器,根据需求实现对应接口

2在web.xml中配置监听器,让监听器工作

配置监听器 使用web.xml 或者通过@WebListener注解都可以

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">

<listener>
<listener-class>com.listener.MyRequestListener</listener-class>
</listener>
</web-app>

分页

简单来说:大量数据无法一次性全部显示在网页上?怎么办?只能选取其中的一部分,将大量数据分成好几段,每一段我们用一个网页显示,也就是一页,在页面上我们可以手动控制我们要选择的页面.分页就是将大量数据分成很多页显示的一种处理手段.

数据库上通过Limit来实现

思路

image-20251029042519506

浏览器向后台发送的信息应该是什么?

参数1:要查询的是第几页

参数2:页大小—size

其他参数: 查询条件

服务器向浏览器返回的数据应该是什么?

数据1:当前页的所有信息 List<Object>

数据2:当前第几页 currentPage

数据3:信息总条数 totalsize

数据4:总页码数 totalpage

数据5:页大小 size

AJAX

异步访问,局部刷新

后续学Axios的库方法即可,这里不用死记硬背ajax的库方法

同步和异步

同步就是顺序执行。

异步:指发送一个请求,不需要等待返回,随时可以再发送下一个请求,即不需要等待。在部分情况下,我们的项目开发中都会优先选择不需要等待的异步交互方式。将用户请求放入消息队列,并反馈给用户,系统迁移程序已经启动,你可以关闭浏览器了。然后程序再慢慢地去写入数据库去。这就是异步。异步不用等所有操作等做完,就响应用户请求。即先响应用户请求,然后慢慢去写数据库,用户体验较好 但是这样的话无法取消前一次操作了

JSON格式

如果响应的数据是一个对象或者对象集合,数据处理起来会非常麻烦,可以使用JSON格式处理。是一种轻量级的数据交换格式。

采用完全独立于编程语言的文本格式来存储和表示数据。

1
2
-- JSON格式创建对象
-- {"属性名":"属性值","属性名":属性值 ... ... }

JSON 与 JS 对象的关系

其实,可以这么理解:JSON 是 JS 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。

1
2
3
var obj = {a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可以使用引号包裹的

var json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串

JSON 和 JS 对象互转

要实现从JSON字符串转换为JS对象,使用 JSON.parse() 方法:

1
var obj = JSON.parse('{"a": "Hello", "b":   "World"}'); //结果是 {a: 'Hello', b: 'World'}

要实现从JS对象转换为JSON字符串,使用 JSON.stringify() 方法:

1
var json = JSON.stringify({a: 'Hello', b: 'World'}); //结果是  '{"a": "Hello", "b": "World"}'

json格式和java对象之间转换

GSON工具类的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@WebServlet("/testServlet.do")
public class TestServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
User user1 =new User("晓明1",10,"男",new Date());
User user2 =new User("晓明2",10,"男",new Date());
User user3 =new User("晓明3",10,"男",new Date());
User user4 =new User("晓明4",10,"男",new Date());
User user5 =new User("晓明5",10,"男",new Date());
ArrayList<User> list =new ArrayList<>();
Collections.addAll(list,user1,user2,user3,user4,user5);
// 响应普通文本数据
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
GsonBuilder gsonBuilder = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss");
Gson gson = gsonBuilder.create();
String str = gson.toJson(list);
System.out.println(str);
resp.getWriter().print(str);
}
}