Servlet
Servlet简介与运行流程
Servlet是Java编程语言编写的服务器端程序,主要用于处理客户端请求并生成响应。Servlet运行在支持Java Servlet规范的Web服务器上,如Apache Tomcat、Jetty等。Servlet通常用于创建动态网页、处理表单数据、与数据库交互等任务。通过Servlet,开发人员可以编写灵活、可扩展的服务器端程序,实现与客户端的交互和数据处理。在Java EE(Enterprise Edition)中,Servlet是构建Web应用程序的重要组件之一。
动态资源和静态资源
- 动态资源:
- 需要在程序运行时通过代码运行生成的资源,在程序运行之前无法确定的数据,运行时动态生成
- 动态资源指的不是视图上的动画效果或者是简单的人机交互效果
- 静态资源
- 无需再程序运行时通过代码运行生成的资源,在程序运行之前就写好的资源。列如:html,cs,js,img
Servlet运行流程
- 客户端发起请求:
客户端向服务器发起HTTP请求,请求可以是GET、POST、PUT等类型的请求。 - Web服务器接收请求:
Web服务器(如Tomcat)接收到请求。 - 请求分发:
Web服务器根据请求的URL找到对应的Servlet。这通常通过web.xml文件中的映射关系或者使用注解来确定。 - Servlet加载:
如果Servlet尚未加载到内存中,Web服务器会加载Servlet类。这包括加载Servlet类的字节码并实例化Servlet对象。 - Servlet初始化:
在Servlet实例化后,Servlet容器会调用其init()方法进行初始化。开发人员可以在init()方法中执行一些初始化操作,如建立数据库连接、加载配置文件等。 - 创建请求对象和响应对象:
Servlet容器创建HttpServletRequest对象和HttpServletResponse对象,用于在Servlet中处理请求和生成响应。 - 调用service()方法:
当有请求到达时,Servlet容器调用Servlet的service()方法,并将请求和响应对象作为参数传递给该方法。 - 确定请求类型:
service()方法确定请求的类型(GET、POST等),然后调用相应的doXXX()方法(如doGet()、doPost()等)来处理请求。 - 处理请求:
在doXXX()方法中,开发人员编写处理请求的逻辑。这可能涉及从请求对象中读取参数、调用业务逻辑、访问数据库等操作。 - 生成响应:
Servlet根据请求处理结果生成响应内容,可以是HTML、JSON、XML等格式的数据。响应内容会被写入到HttpServletResponse对象中。 - 响应返回给客户端:
Servlet容器将生成的响应返回给客户端,客户端接收并处理响应内容。 - 调用destroy()方法:
当Servlet容器关闭应用或重新加载时,会调用Servlet的destroy()方法。在destroy()方法中,开发人员可以执行清理操作,如关闭数据库连接、释放资源等。
servlet开发步骤
- 创建一个javaweb项目
- 在src下创建一个servlet包,并在包中创建一个Servlet类
- 该类去继承HttpServlet类
- 重写service方法,该方法中的HttpServletRequest对应了客户端请求中的信息,HttpServletResponse对应了服务器将要响应的信息
- 通过HttpServletRequest对象中的getParameter(String)方法可以获得requese对象中的数据
- 通过Response的getWriter()方法可以返回一个PrintWriter对象使用该对象的write()方法可以向响应体输入信息
- 在WEB-INF目录下的web.xml配置路径映射
一个及其简单例子
demo
├── WEB-INF
│ └── web.xml
├── src
│ └── com.atli.servlet
│ └── UserServlet.java
├── index.html
<!--index.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="get" action="userServlet">
用户名:<input type="text" name="username"><br>
<input type="button" value="校验">
</form>
</body>
</html>
//UserServlet.java
/**
* servlet开发流程
* 1.创建javaweb项目,同时将tomcat添加为当前项目依赖
* 2.重写service方法 service(HttpServletRequest req, HttpServletResponse resp)
* 3.在service方法中定义业务处理代码
* 4.在web.xml中,配置Servlet对应的请求映射路径
*/
public class UserServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.从requese对象中获取请求中的任何信息
String username = req.getParameter("username");
//2.处理业务代码
String info = "YES";
if("li".equals(username)) {
info = "NO";
}
//3.将要响应的数据放入response中
PrintWriter out = resp.getWriter();//该方法返回的是一个向响应体中打印字符串的打印流
out.write(info);
}
}
<!--web.xml-->
<!--
1.配置Servlet类,并起一个别名
servlet-class 告诉tomcat对应的要实例化的Servlet类
servlet-name 用于关联请求的映射路径
-->
<!--
在一次具体的请求中列如http://localhost:8080/demo/userServlet
通过localhost找到服务器为本机
之后又通过8080端口找到是tomcat服务器
再通过demo找到了是demo这个项目
再然后通过userServlet->url-pattern->esrvlet-name->servlet-class找到了UserServlet的路径,最后,通过反射得到了UserServlet的字节码,然后通过反射执行了service方法
-->
<servlet>
<servlet-name>userServlet</servlet-name>
<servlet-class>com.atli.servlet.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<esrvlet-name>userServlet</esrvlet-name>
<url-pattern>/userServlet</url-pattern>
</servlet-mapping>
servlet开发的注意事项
Content-Type
- Content-Type 是一个HTTP响应头部字段,用于指示客户端(通常是浏览器)如何解析接收到的响应内容
- 通过设置 Content-Type,服务器告诉客户端发送的数据是什么类型的数据,以便客户端能够正确地处理这些数据。
- 常见的 Content-Type 类型
- text/html:HTML 格式的文本
- text/plain:纯文本
- application/json:JSON 格式数据
- application/xml:XML 格式数据
- image/jpeg:JPEG 图像
- image/png:PNG 图像
- application/pdf:PDF 文件
- application/octet-stream:二进制流数据
- 可以使用HttpServletResponse 对象的 setContentType 方法来设置响应的 Content-Type
Servlet_url-pattern
- url-pattern用于指定Servlet的映射路径,可以在web.xml文件中配置。
- 精确匹配:
- 指定一个具体的URL路径
<url-pattern>/path</url-pattern>
- 通配符匹配:
/*
:匹配所有路径,包括子路径<url-pattern>/*</url-pattern>
/path/*
:匹配指定路径下的所有子路径<url-pattern>/path/*</url-pattern>
- 扩展名匹配:
- 匹配指定扩展名的URL
<url-pattern>*.extension</url-pattern>
- 精确匹配和扩展名匹配的结合:
<url-pattern>/path/*.extension</url-pattern>
- 默认Servlet:
/
:用于指定默认Servlet,处理所有未匹配到其他Servlet的请求<url-pattern>/</url-pattern>
注解方式配置Servlet
直接在servlet类前写上@WebServlet(“路径”)就可以了
Servlet生命周期
- 加载和实例化:
当服务器启动时或者第一次请求到达时,Servlet容器加载Servlet类。
Servlet容器通过调用Servlet的无参构造函数实例化Servlet对象。 - 初始化:
Servlet容器调用Servlet的init(ServletConfig config)方法进行初始化。
init()方法只会在Servlet第一次被加载时调用,用于执行一次性的初始化操作。
在init()方法中,通常会进行一些配置的读取、资源的加载和其他初始化操作。 - 请求处理:
每次有请求到达时,Servlet容器会调用Servlet的service(ServletRequest request, ServletResponse response)方法。
service()方法根据请求的类型(GET、POST等)来调用相应的处理方法(doGet(), doPost()等)。
在处理请求时,Servlet可以与客户端交互,执行业务逻辑并生成响应。 - 销毁:
当服务器关闭或者需要卸载Servlet时,Servlet容器会调用Servlet的destroy()方法。
destroy()方法用于执行一些清理工作,如释放资源、关闭数据库连接等。
destroy()方法只会在Servlet被销毁时调用一次。
- Servlet在Tomcat中是单例的
- Servlet的成员变量在多个线程栈之中是共享的
- 不建议在service方法中修改成员变量,在并发请求时会出现线程安全问题
- 可以在tomcat启动时实例化servlet,方法是在web.xml文件中设置
<load-on-startup>
其中,-1表示启动时不实例化,其它正整数表示在启动时的实例化顺序
defaultServlet
defaultServlet 是 Apache Tomcat 中的一个内置 Servlet,在 Java Servlet 容器中,它用于提供静态资源,如 HTML、图片、CSS 和 JavaScript 文件。当向 Tomcat 发出请求以获取一个资源,而该资源不匹配 web.xml 部署描述符中的任何 Servlet 映射时,defaultServlet 负责处理该请求。
defaultServlet 在 Web 应用程序的 web.xml 文件中进行配置,通常映射到处理根 URL(“/”)或任何不匹配其他 Servlet 映射的请求。
使用 defaultServlet 可以有效地提供静态内容,并处理不需要其他 Servlet 在您的应用程序中进行动态处理的资源请求。
Servlet继承结构
Servlet接口:javax.servlet.Servlet
Servlet接口是所有Servlet类的根接口。它定义了Servlet的生命周期方法,包括:
void init(ServletConfig config) throws ServletException:在Servlet被初始化时调用。
void service(ServletRequest req, ServletResponse res) throws ServletException, IOException:用于处理客户端请求并生成响应。
void destroy():在Servlet被销毁前调用。
GenericServlet类:javax.servlet.GenericServlet
GenericServlet类是一个抽象类,实现了Servlet接口。它提供了Servlet接口中的一些方法的默认实现,包括:
void init():初始化Servlet。
void destroy():销毁Servlet。
ServletConfig getServletConfig():获取Servlet的配置信息。
String getServletInfo():获取Servlet的信息。
HttpServlet类:javax.servlet.http.HttpServlet
HttpServlet类继承自GenericServlet类,专门用于处理HTTP协议的Servlet。它提供了针对不同HTTP请求方法的处理方法,包括:
void doGet(HttpServletRequest req, HttpServletResponse res):处理HTTP GET请求。
void doPost(HttpServletRequest req, HttpServletResponse res):处理HTTP POST请求。
void doPut(HttpServletRequest req, HttpServletResponse res):处理HTTP PUT请求。
void doDelete(HttpServletRequest req, HttpServletResponse res):处理HTTP DELETE请求。
还有其他方法如doOptions(), doHead(), doTrace()等。
ServletConfig和ServletContext
ServletConfig
ServletConfig 是 Java Servlet API 中的一个接口,它在 servlet 初始化期间提供配置信息给 servlet。它允许 servlet 访问在 Web 部署描述符(web.xml 文件)中定义的初始化参数,并提供方法来获取有关 servlet 配置的信息。
ServletConfig 接口提供的一些常用方法包括:
getInitParameter(String name):该方法检索具有给定名称的初始化参数的值。
getInitParameterNames():该方法返回初始化参数的名称作为 String 对象的枚举。
getServletContext():该方法返回对 ServletContext 对象的引用,该对象提供有关 servlet 环境的信息。
Servlet 通常使用 ServletConfig 对象来检索在部署描述符中配置的初始化参数,或者获取对 ServletContext 的引用以访问应用程序范围的资源。
<!--只是对于单个的servlet对象-->
<servlet>
<init-param>
<param-name>myParam</param-name>
<param-value>value</param-value>
</init-param>
</servlet>
public class MyServlet extends HttpServlet {
private ServletConfig config;
public void init(ServletConfig config) throws ServletException {
this.config = config;
String myParam = config.getInitParameter("myParam");
System.out.println("myParam 的值为:" + myParam);
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext context = config.getServletContext();
// 使用 ServletContext 对象进行操作,比如获取属性或读取文件
}
}
ServletContext
为所有Servlet提供配置参数
ServletContext 可以通过 getInitParameter() 方法来获取 web 应用程序的初始化参数,这些参数通常在 web.xml 文件中配置。通过这种方式,所有的 servlet 都可以访问这些公共的参数,而不需要每个 servlet 都去单独配置。
举例来说,如果在 web.xml 文件中配置了一个初始化参数:
<context-param>
<param-name>dbName</param-name>
<param-value>myDatabase</param-value>
</context-param>
然后在 servlet 中可以通过 ServletContext 来获取这个参数:
String dbName = getServletContext().getInitParameter("dbName");
获取文件路径和上下文
获取文件路径:
String filePath = servletContext.getRealPath("/WEB-INF/myfile.txt");
这将返回文件myfile.txt在Web应用程序中的实际路径。请注意,这种方法在Servlet 3.0及更高版本中已被标记为不推荐使用。
获取上下文路径:
String contextPath = servletContext.getContextPath();
这将返回Web应用程序的上下文路径,例如/mywebapp.
获取资源路径:
URL resourceUrl = servletContext.getResource("/WEB-INF/myfile.txt");
ServletContext域对象
通过ServletContext域对象,可以在整个Web应用程序中存储数据,这些数据对所有的Servlet和JSP页面都是可见的。通常情况,ServletContext域对象用于在应用程序中共享配置信息、数据库连接、日志记录器等数据。
webapp中的三大域对象分别是:应用域,会话域,请求域
要在Servlet中使用ServletContext域对象,可以通过以下步骤进行:
获取ServletContext对象:可以通过调用ServletConfig的getServletContext()方法来获取ServletContext对象。
使用ServletContext对象:一旦获取了ServletContext对象,就可以使用它的setAttribute()和getAttribute()方法来存储和检索数据。
示例代码如下所示:
public class MyServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) {
// 获取ServletContext对象
ServletContext context = getServletContext();
// 存储数据到ServletContext域对象中
context.setAttribute("key", "value");
// 从ServletContext域对象中获取数据
String value = (String) context.getAttribute("key");
// 在控制台输出获取到的值
System.out.println(value);
}
}
HttpServletRequest与HttpServletResponse
请求行与请求头
请求行(Request Line)包含以下三个部分:
方法(Method):指定请求的方法,如GET、POST、PUT、DELETE等。
资源路径(Resource Path):指定请求的资源路径,即客户端希望访问的资源在服务器上的位置。
协议版本(HTTP Version):指定所使用的HTTP协议的版本,如HTTP/1.1。
示例请求行:GET /index.html HTTP/1.1
请求头(Request Headers)包含了关于请求的附加信息,如:
Host:指定请求的主机名和端口号。
User-Agent:发送请求的用户代理信息,通常是浏览器的类型和版本。
Accept:指定客户端能够接受的内容类型。
Content-Type:指定请求体的内容类型。
Authorization:包含用于验证请求的凭据。
Cookie:包含客户端的Cookie信息。
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
Request获取请求行和请求头
获取请求行信息
获取请求方法:
String method = request.getMethod();
获取请求的 URI:
String uri = request.getRequestURI();
获取协议和协议版本:
String protocol = request.getProtocol();
获取请求头信息
获取单个请求头:
String headerValue = request.getHeader("HeaderName");
获取所有请求头的名称:
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
String headerValue = request.getHeader(headerName);
// Do something with headerName and headerValue
}
Request获取请求中的键值对
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
public class MyServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
// 获取单个参数的值
String parameterValue = request.getParameter("parameterName");
// 获取所有参数的键值对
Map<String, String[]> parameterMap = request.getParameterMap();
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
String paramName = entry.getKey();
String[] paramValues = entry.getValue();
for (String paramValue : paramValues) {
System.out.println("Parameter Name: " + paramName + ", Value: " + paramValue);
}
}
}
}
HttpServletResponse设置响应信息
设置响应内容类型(Content Type):
java
response.setContentType("text/html");
设置响应字符编码:
java
response.setCharacterEncoding("UTF-8");
写入响应内容:
java
PrintWriter out = response.getWriter();
out.println("Hello, World!");
设置响应状态码:
java
response.setStatus(HttpServletResponse.SC_OK);
设置响应头部信息:
java
response.setHeader("HeaderName", "HeaderValue");
请求转发和响应重定向
请求转发
- 请求转发通过HttpServletRequest对象获取请求转发器实现。
- 请求转发是服务器内部的行为,对客户端是屏蔽的
- 客户端只发送了一次请求,客户端地址栏不变
- 服务端只产生了一对请求和响应对象,这一对请求和响应对象会继续传递给下一个资源
- 全程只有一个HttpServletRequset对象,所以请求参数可以传递,请求域众多数据也可以传递
- 请求转发可以转发给其它Servlet动态资源,也可以转发给一些静态资源以是西安页面跳转
- 请求转发可以转发给WEB-INF下受保护的资源
响应重定向
- 响应重定向通过HttpServletResponse对象的sendRedirect方法实现
- 响应重定向是服务端通过302响应码和路径,告诉客户端自己去找其他资源,是再服务端提示下的,客户端的行为
- 客户端至少发送了两次请求,客户端地址栏是要变化的
- 服务端产生了多对请求和响应对象,且请求和响应对象不会传递给下一个资源
- 因为全程产生了多个HttpServletRequset对象,所以请求参数不可以传递,请求域中的数据也不可以传递
- 重定向可以是其他Servlet动态资源,也可以是一些静态资源以实现页面跳转
- 重定向不可以给到WEB-INF下受保护的资源
MVC架构模式
MVC是软件工程中的的一种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分。用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑
M:Model模型层
- 存放和数据库对象的实体类以及一些用于存储非数据库表完整相关的VO对象
- 存放一些对数据进行逻辑运算操作的一些业务处理代码
- Model层常见包
- 实体类包(pojo/entity/bean)专门存放和数据库对应的实体类和一些VO对象
- 数据库访问包(dao/mapper)专门存放对数据库不同表格CURD方法封装的一些类
- 服务包(service)专门存放对数据进行业务逻辑预算的一些类
V:view视图层
- 存放一些视图文件相关的代码html css js等
- 在前后端分离的项目中,后端已经没有视图文件,该层次已演化成独立的前端项目
- View层常见包
- web目录下的视图资源html css js img等
- 前端工程化后,在后端项目中已经不存在了
C:Controller控制层
- 接收客户端请求,获得请求数据
- 将准备号的数据响应给客户端
- Controller层常见包
- 控制层包controller