Servlet是Java EE的核心。基于xml配置的方式已经过时,现在是基于注解注入。过时的方法不在细说
Servlet是Web容器的组件,其不直接处理Http请求,而是由容器创建后转发给Servlet
什么是Servlet
他就是一个 Java 编程语言中的一个class,用于扩展服务器的功能。
servlet 可以响应任何类型的请求,但它们通常用于扩展由 Web 服务器托管的应用程序。对于这样的应用程序,Java Servlet 技术定义了特定于 HTTP 的 servlet 类。
换言之Java EE封装了Http请求的Servlet,并且定义了http通用的方法,其他类型的Servlet也可以基于其他协议用Servlet实现
Web容器的作用
Servlet是运行在Web容器中,当HTTP请求转发给Web时,Web容器会创建一个HttpServletRequest和HttpServletResponse对象,根据配置信息去查找相应的Servlet,同时将对象传递给Servlet
换言之,Web容器已经帮我们做了很多的事情,我们需要做的只是定义业务逻辑,即Servlet中的service()方法。觉得牛逼可以研究tomcat源码...
在专门的Http实现abstract类HttpServlet定义了Http的请求方式post、get、delete等7种请求方法,由service方法判断逻辑
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
if (ifModifiedSince < lastModified) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
//
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
怎么使用servlet
Servlet是JavaEE的体系框架标准规范SPI,根本在于JavaSE。是SE的拓展。
Servelt规范可以单独升级,但是因为基于SE的基础,所以低版本的SE可能不支持高版本的Servlet规范。
引入servlet规范jar
在使用springboot的时候我们无需引入单独的servlet规范,因为springboot内置的tomcat中已经含有servlet规范不需要单独引入
在没有springboot的单独体系中则需要引入EE相关规范
下面基本涵盖了所有的ee规范标准,当然也可以单独引入servlet4.0
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.mvc</groupId>
<artifactId>javax.mvc-api</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>javax.xml.ws</groupId>
<artifactId>jaxws-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.jws</groupId>
<artifactId>javax.jws-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
serlvet功能
- 对客户端发送的数据进行拦截
url参数、Ajax表单提交Servlet可以对请求进行拦截进行预处理(访问权限、字符集等),称之为拦截器 - 读取客户端请求的隐含数据
例如请求IP、缓存Cookie、客户端类型 - 运行结果或产生数据
- 发送响应数据
对客户端发送响应数据,让客户端获取请求结果
servlet生命周期
**servlet 的生命周期由部署了 servlet 的容器控制。**当请求映射到 servlet 时,容器将执行以下步骤。
1.如果 servlet 的实例不存在,则 Web 容器:
2.加载 servlet 类
3.创建 servlet 类的实例
4.通过调用方法初始化 Servlet 实例(创建和初始化 Servlet中介绍了初始化init)
5.容器调用该方法,传递请求和响应对象。
6.如果需要删除 servlet,容器将通过调用 servlet 的方法完成
所有的所有是容器主导,servlet只是组件!!!
- 编写一个最简单的servlet
@WebServlet(name = "helloServlet", value = "/hello-servlet")
public class HelloServlet extends HttpServlet {
private String message;
@Override
public void init() {
message = "Hello World!";
System.out.println("init");
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
// Hello
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h1>" + message + "</h1>");
out.println("</body></html>");
}
@Override
public void destroy() {
System.out.println("destory");
}
}
由servlet直接渲染返回页面,
创建和初始化
使用注释在 Web 应用程序中定义 servlet 组件。此注解是在类上指定的,并且包含有关所声明的 servlet 的元数据。带注释的 servlet 必须至少指定一个 URL 模式。
HttpServletRequest
HttpServletRequest从何而来?由Web容器为我们生成
我们只需要关注其有哪些方法供我们使用
我们无需关注所有方法,有的放矢,需要时再去查找
ServletRequest及常用API
ServletRequest是一个对象以向 servlet 提供客户端请求信息。 servlet 容器创建一个ServletRequest对象并将其作为参数传递给 servlet 的service方法。
ServletRequest对象提供的数据包括参数名称和值、属性和输入流。 扩展ServletRequest接口可以提供额外的特定于协议的数据
获取字符
- BufferedReader getReader()
以字符流读取body 适用于获取字符串等
获取文件
- ServletInputStream getInputStream() 获取文件
以二进制字节流读取body 适用于获取字节文件等 - Part getPart(String name)。 获取multipart/form-data 文件
获取指定名称的Part - Collection
getParts() 获取multipart/form-data 文件
获取此请求的所有Part组件,前提是它的类型为multipart/form-data
使用这2个注解的前提是需要有
@MultipartConfig(location="",maxFileSize=)注解配置限制位置和文件大小
tomcat容器默认实现ApplicationHttpRequest
RequestDispatcher
该对象接收来自客户端的请求并将它们发送到服务器上的任何资源(例如 servlet、HTML 文件或 JSP 文件)。
servlet 容器创建RequestDispatcher对象,该对象用作位于特定路径或由特定名称指定的服务器资源的包装器。
因为是由Servlet创建的RequestDispatcher对象 Java EE并没有做具体实现
其包含2个方法
- void forward(ServletRequest request, ServletResponse response)
将该Aservlet转发给其他Bservlet,最终由B返回(转发是在一个servlet资源内部) - void include(ServletRequest request, ServletResponse response)
在该Aservlet中调用其他Bservlet,最终由A返回
tomcat中的RequestDispatcher实现类
ApplicationDispatcher
RequestDispatcher标准实现,它允许将请求转发到不同的资源以创建最终响应,或者在来自该资源的响应中包含另一个资源的输出。
HttpServletResponse
容器将ServletResponse、ServletRequest传递给servlet执行,servlet执行之后返回给容器,容器再将ServletResponse返回给调用请求的客户端
- void sendError(int sc)
使用指定的状态代码向客户端发送错误响应并清除缓冲区。 服务器将保留 cookie - void sendRedirect(String location)
使用指定的重定向位置 URL 向客户端发送临时重定向响应并清除缓冲区。 缓冲区将被此方法设置的数据替换。 重定向,浏览器参与其中
ServletResponse及其常用API
- ServletOutputStream getOutputStream()
获得二进制数据的ServletOutputStream 。 servlet 容器不对二进制数据进行编码。再调用flush() 提交response。 - PrintWriter getWriter()
返回一个可以向客户端发送字符文本的PrintWriter对象。 PrintWriter使用getCharacterEncoding返回的字符编码。 - setCharacterEncoding(String charset)
将发送到客户端的响应的字符编码(MIME 字符集)设置为 UTF-8。 如果响应字符编码已由ServletContext.setResponseCharacterEncoding 、部署描述符或使用 setContentType() 或 setLocale() 方法设置,则此方法中设置的值将覆盖这些值中的任何一个。 用text/html的String调用setContentType用UTF-8的String调用这个方法等价于用text/html; charset=UTF-8的String调用setContentType text/html; charset=UTF-8 text/html; charset=UTF-8 - void setContentType(String type)
如果响应尚未提交,则设置发送到客户端的响应的内容类型。 给定的内容类型可能包括字符编码规范,例如text/html;charset=UTF-8 。
Comments | 0 条评论