Servlet是Oracle公司提供的一门用于开发动态web资源的技术,属于Java EE体系中的一种核心规范。它是沟通服务器后台和前端的中间件,负责动态地向前端提供静态数据,如HTML、JSON等。

基础创建

Servlet作为一种规范,它其实是一个javax.servlet.Servlet接口。Tomcat服务器可以帮助创建Servlet接口的实现类对象(下简称Servlet对象),并在合适的时候调用其中的方法,将数据传递到前端,被浏览器直接访问。

  • 一个动态后端项目拥有什么:首先需要IDE中集成一个服务器,帮助创建Servlet对象并调用实现的方法。在STS中,服务器需要在Performance-Server-Runtime Environment中配置。创建项目后,选择一个动态资源服务器作为项目的运行服务器,如Tomcat。然后在src中编写Servlet实现类代码(或者是其封装)。WEB-INF存储安全性的隐藏网页(只能通过内部跳转访问)和配置文件web.xml,其中的lib目录存储项目使用到的其它依赖jar包。

image.png

  • 什么时候创建Servlet对象:默认情况下,在客户端(浏览器)首次访问该资源时,服务器会调用该Servlet实现类的构造方法,创建Servlet对象。在每个Web项目运行期间,每种Servlet实现类只会创建一个对象。通过修改配置中的load-on-startup来配置启动优先级。
  • 调用什么方法,何时调用:调用的是Servlet对象中实现的抽象方法,一共有5个:

    1. void init(ServletConfig config) throws ServletException; // 创建Servlet对象后立即调用1次
    2. ServletConfig getServletConfig(); // 用于获取ServletConfig对象的工具方法
    3. void service(ServletRequest req, ServletResponse res)
    4. throws ServletException, IOException; // 每次访问Servlet资源时调用1次,
    5. // ServletRequest能够获取请求对象中封装的HTTP请求数据,如请求行、请求头、请求体等
    6. // 能够将响应返回的数据封装进ServletResponse中
    7. String getServletInfo(); // 用于获取Servlet对象元数据的工具方法
    8. void destroy(); // 销毁Servlet对象前立即调用1次
  • Tomcat服务器如何创建Servlet对象:需要为Tomcat服务器添加配置数据,告诉服务器Servlet对象的对象名,实现类的全类名等。这些配置文件包装在web.xml文件中:

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
    3. <display-name>hello</display-name><!-- 项目名 -->
    4. <servlet>
    5. <servlet-name>hello</servlet-name><!-- Servlet对象名,随意 -->
    6. <servlet-class>com.briup.web.HelloWorld</servlet-class><!-- Servlet实现类的全类名 -->
    7. <load-on-startup>1</load-on-startup><!-- Servlet对象创建的优先级,越小越先被创建 -->
    8. </servlet>
    9. <servlet-mapping><!-- 设置一个URI -->
    10. <servlet-name>hello</servlet-name><!-- 对应的Servlet对象名 -->
    11. <url-pattern>/test</url-pattern><!-- Servlet资源映射路径(URI) -->
    12. </servlet-mapping>
    13. <!-- 之后就可以通过“IP:端口/项目名/资源映射路径”访问Servlet对象资源了 -->
    14. </web-app>

    在代码中,可以在实现类中使用@WebServlet注解替代web.xml,为服务器添加Servlet对象配置,为Servlet对象指定资源映射路径(路由)、优先级等,相当于servlet-mapping标签的作用: ```java @WebServlet(“/test3”) // 指定资源映射路径url-pattern

@WebServlet(value = {“/test3”, “.ml”, “/“}) // 指定多个资源映射路径,并使用通配符

@WebServlet(value = “/test3”, loadOnStartup = 1, // 指定资源映射路径和优先级 initParams = { // 配置初始化参数 @webInitParam(name = “encoding”, value = “UTF-8”), // 指定资源初始化时的HTTP响应报文编码 @webInitParam(name = “kk”, value = “11”) // 指定资源初始化时的HTTP响应报文自定义属性 } )

  1. - **如何访问资源,整个Servlet对象的生命周期是怎样的**:当服务器启动后,即会读取相应的web.xml配置文件,然后使用这一配置创建相应的Servlet对象(仅一个),并调用init方法,对创建好的servlet对象进行初始化操作。通过资源映射路径可以访问相应的Servlet对象资源,每访问一次,就调用一次其中的service(req, res)方法。在Servlet对象销毁(如服务器关闭或项目重新加载)前,调用destroy方法。
  2. - 因为服务器访问是并发的,Tomcat会对并发进行处理,产生线程来访问Servlet对象。由于Servlet对象只有一个,故在实现类中声明的成员变量就会有线程安全的问题。详见后文章节。
  3. - 资源映射路径一定要写“/”,否则服务器会报错,无法启动。资源映射路径还具有通配符,可以在映射路径末尾使用“*”匹配任意一串字符,但通配符的优先级最低,先匹配更具体的映射路径;但是,当使用“*.xxx”具有后缀名的格式时,无需“/”。匹配优先级:“/具体路径”>“/*”>“*.xxx”>“/”。
  4. <a name="mi6J0"></a>
  5. ## 封装
  6. javax.servlet.GenericServlet和javax.servlet.http.HttpServlet是对上面方式的两种封装。<br />GenericServlet是实现了Servlet接口的一个类。可以继承GenericServlet类,重写其中的方法。
  7. ```java
  8. @WebServlet("/test2")
  9. public class TwoServlet extends GenericServlet {
  10. @Override
  11. public void init() throws ServletException {
  12. // GenericServlet封装的无参init方法
  13. }
  14. @Override
  15. public void service(ServletRequest req,
  16. ServletResponse res) throws ServletException, IOException {
  17. // 每次访问Servlet资源时调用的方法
  18. }
  19. }

HttpServlet是继承了GenericServlet类的一个类,封装得更彻底,可以根据HTTP请求的类型调用相应的方法,是最常用的方式。可以继承HttpServlet类,重写其中的方法。

  1. @WebServlet("/test3")
  2. public class ThreeServlet extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp)
  5. throws ServletException, IOException {
  6. // GET请求调用的方法
  7. }
  8. @Override
  9. protected void doPost(HttpServletRequest req, HttpServletResponse resp)
  10. throws ServletException, IOException {
  11. doGet(req, resp); // POST请求调用和GET请求相同的方法
  12. }
  13. }