JavaWeb
Servlet
继承关系
HttpServlet–>GenericServlet–>Servlet
service方法
当请求来到时,service
方法会自动响应(实际上是Web容器Tomcat调用),在HttpServlet
中会分析请求的方式(get、post、head、delete等),然后再决定调用哪个方法(doGet
、doPost
、doHead
、doDelete
),这些方法默认都是405响应,需要程序员继承HttpServlet
并重写这些方法。
服务配置
在web.xml
中配置,或者使用注解@WebServlet
配置。
1 | <!-- 一个servlet对应多个servlet-mapping --> |
生命周期
Servlet初始化、提供服务、销毁,对应三个方法init
、service
、destroy
。默认情况下:第一次接收请求时,Servlet会进行实例化(调用构造方法)、初始化(调用init
)、再提供服务(调用service
);从第二次请求开始,都只提供服务;当Web容器关闭,其中的所有Servlet实例都会被销毁。我们可以通过<load-on-startup>
设置各个Servlet的启动顺序,数字越小越早启动。
通过案例可以发现,一个Servlet实例只会被一次。
1 | package com.joe.servlet; |
会话跟踪
Http无状态,即服务器无法判断两次请求是否是同一个客户端发送的,我们需要使用会话跟踪技术来解决无状态的问题。
当第一次发送请求时,服务器给客户端分配一个“Session ID”,接下来的每次请求客服端都主动告知服务器自己的“Session ID”。
1 | package com.joe.servlet; |
第一次访问服务网址localhost:8080/Servlet/SessionTracking
,响应头中包含了设置的“Session ID”。
1 | Connection: keep-alive |
接下来再发起请求,请求头中自带“Session ID”。
1 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 |
保存作用域
-
page(页面级别)
-
request(一次请求响应范围)
用户向
servlet1
发送请求后,又再次向servlet2
发送请求,输出null
。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20package com.joe.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Joe Zhu
*/
public class Servlet1 extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("username","joe");
resp.sendRedirect("servlet2");
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package com.joe.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Joe Zhu
*/
public class Servlet2 extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(req.getAttribute("username"));
}
}将
Servlet1
的代码改动如下,进行请求内转发,输出joe
。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20package com.joe.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Joe Zhu
*/
public class Servlet1 extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("username", "joe");
req.getRequestDispatcher("servlet2").forward(req, resp);
}
} -
session(一次会话范围有效)
输出
joe
。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20package com.joe.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Joe Zhu
*/
public class Servlet1 extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getSession().setAttribute("username", "joe");
resp.sendRedirect("servlet2");
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package com.joe.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Joe Zhu
*/
public class Servlet2 extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(req.getSession().getAttribute("username"));
}
} -
application(一次应用程序范围有效)
过滤器
设置过滤器需要,实现接口javax.servlet.Filter
。过滤器用于拦截请求,需要用注解@WebFilter
或XML配置;如果采取注解的方式配置,那么过滤器链的拦截顺序是按全类名的字典序排序;如果采取XML方式进行配置,那么按照配置的先后顺序拦截。
1 | package com.joe.servlet; |
监听器
- ServletContextListener监听ServletContext对象的创建和销毁的过程。
- HttpSessionListener监听HttpSession对象的创建和销毁的过程。
- ServletRequestListener监听ServletRequest对象的创建和销毁的过程。
- ServletContextAttributeListener监听ServletContext中属性的创建、修改和销毁。
- HttpSessionAttributeListener监听HttpSession中属性的创建、修改和销毁。
- ServletRequestAttributeListener监听ServletRequest中属性的创建、修改和销毁。
- HttpSessionBindingListener监听某个对象在Session域中的创建与移除。
- HttpSessionActivationListener监听某个对象在Session中的序列化与反序列化。
MVC
-
Model(模型)
- POJO (Plain Ordinary Java Object,简单的Java对象)或 VO(Value Object,值对象)
- DAO(Data Access Object,数据访问对象)
- BO(Business Object,业务对象)
-
View(视图)用于做数据展示以及和用户交互。
-
Controller(控制器)接收客服端请求,具体业务功能借助Model组件完成。
书城项目
踩坑记录
遇到的问题 | 解决方案 |
---|---|
Maven已经导入mysql-connector-java-8.0.28.jar ,用JDBC连数据库时,Class.forName("com.mysql.cj.jdbc.Driver") 报异常。 |
构建Web项目时,用到的jar包放在 WEB-INF/lib 目录下,这一点在Tomcat的webapps中可以看到。在“项目结构-工件-输出”设置更方便。 其它 ClassNotFind 等异常也类似。 |
重装了IDEA后打开web项目,web目录没有蓝点,web项目无法正常构建。 | 在项目结构中选中对应模块,设置web目录。IDEA webapp文件夹没有蓝色小圆点的解决方案_无发可脱-CSDN博客 |
表单中,用Thymleaf标签th:action 无法正常解析。 |
使用原始的action 。 |
maven项目编译后没有xml文件。 | 在pom.xml中增加配置。Spring编译后没有xml配置文件解决方法_林老头的博客-CSDN博客 |
UTF-8 序列的字节 3 无效。 | 解决3 字节的 UTF-8 序列的字节 3 无效_lzupb的博客-CSDN博客 |
method.getParameters() 获取不到实际形参名。 |
编译时添加-parameters 参数。jdk1.8获取目标方法参数的名称_jxz999000的博客-CSDN博客 |