Servlet创建方式,配置方式-12月8日讲课内容

2020-12-08T23:36:00

概述

Servlet(Server Applet),全称Java Servlet,未有中文译文。是用 Java 编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态 Web 内容。狭义的 Servlet 是指 Java 语言实现的一个接口,广义的 Servlet 是指任何实现了这个 Servlet 接口的类,一般情况下,人们将Servlet 理解为后者

Servlet运行于支持Java的应用服务器中。从实现上讲,Servlet 可以响应任何类型的请求,但绝大多数情况下 Servlet 只用来扩展基于HTTP协议的Web服务器。

简单理解:

Servlet 是 Java Web 服务端的一个小程序,主要用户数据的交互,Web 数据展示和数据传递,这里的 Servlet 是一个动态资源。

Servlet 程序可以应对所有类型的请求和响应,Servlet 主要还是用于HTTP 协议的WEB服务器程序实现。

工作模式【重点】

  1. 浏览器端发送请求至服务器
  2. 服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器
  3. 服务器将响应返回客户端

tomcat 和 servlet 的关系【了解】

Tomcat 是 Web 应用服务器,是一个 Servlet/JSP 容器。Tomcat 作为 Servlet 容器,负责处理客户请求,把请求传送给 Servlet,并将 Servlet 的响应传送回给客户。而Servlet是一种运行在支持 Java 语言的服务器上的组件。Servlet 最常见的用途是扩展 Java Web 服务器功能,提供非常安全的,可移植的,易于使用的 CGI 替代品。

1、Tomcat将http请求文本接收并解析,然后封装成HttpServletRequest类型的request对象,所有的HTTP头数据读可以通过request对象调用对应的方法查询到。

2、Tomcat同时会要响应的信息封装为HttpServletResponse类型的response对象,通过设置response属性就可以控制要输出到浏览器的内容,然后将response交给tomcat,tomcat就会将其变成响应文本的格式发送给浏览器

Java Servlet API 是 Servlet容器 (tomcat) 和 servlet 之间的接口,它定义了 serlvet 的各种方法,还定义了 Servlet 容器传送给 Servlet 的对象类,其中最重要的就是 ServletRequest 和 ServletResponse。所以说我们在编写servlet 时,需要实现 Servlet 接口,按照其规范进行操作。

初识

步骤

1、创建类并继承自HttpServlet
2、重写doGet和doPost方法(两个方法实际是一个)
3、声明@WebServlet并加上默认属性(访问路径)

案例代码

/**
 * @description 第一个Servlet程序
 *
 * @WebServlet 注解的意思是声明程序的入口,注解中的属性为请求的路径
 * 【注意】属性前必须要加 / !!!
 */
@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
    /**
     * 处理Post请求
     *
     * @param req HttpServletRequest对象:浏览器请求数据内容对象
     * @param resp HttpServletResponse对象:浏览器响应数据内容对象
     * @throws ServletException Servlet异常
     * @throws IOException IO异常
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost被执行");
        resp.getWriter().append("Hello Servlet");
    }

    /**
     * 处理Get请求
     *
     * @param req HttpServletRequest对象:浏览器请求数据内容对象
     * @param resp HttpServletResponse对象:浏览器响应数据内容对象
     * @throws ServletException Servlet异常
     * @throws IOException IO异常
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet被执行");
        
        // 实际调用的仍然是doget方法
        doPost(req, resp);
    }
}

html页面

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>测试Servlet</title>
</head>
<body>
    <form action="HelloServlet" method="get">
        <input type="submit" value="get请求">
    </form>

    <form action="HelloServlet" method="post">
        <input type="submit" value="post请求">
    </form>
</body>
</html>

【注意】

  1. Servlet代码中的@WebServlet注解中的属性值前必须要加 /
  2. HTML页面中跳转页面不要加 /

servlet 核心接口和类

// 两个相关核心包
javax.servlet
javax.servlet.http
    
// 顶级父类接口,定义了生命周期方法以及获取配置的方法
public interface Servlet;

// 初始化当前Servlet程序,这里需要的参数是ServletConfig,ServletConfig是当前Servlet的配置,该配置可以从注解方式或者从当前项目中的web.xml加载获取
public void init(ServletConfig config) throws ServletException;
        
// 获取ServletConfig对象,当前对象中保存有Servlet配置内容
public ServletConfig getServletConfig();

// 【核心方法】Servlet提供服务的方法,浏览器访问当前Servlet程序,service方法是起作用,真实调用的还是doget和doPost
// ServletRequest对应的是请求对象
// ServletResponse 对应的是响应对象
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
        
// 获取当时Servlet程序信息对应字符串,几乎不用,数据都保存在数据库中
public String getServletInfo();
        
// 销毁当前Servlet程序,可以由Tomcat服务器执行,也可也通过servlet程序自己调用        
public void destroy();
        
// 对 Servlet 的扩展,完成了一些不太关心的方法,对我们来说只需重写 service 方法即可    
public abstract class GenericServlet;

// 根据初始化参数名字获取对应的值,而且参数值为String
public String getInitParameter(String name);

// 获取ServletContext对象,一个Servlet Application有且只有一个ServletContext对应,这是Servlet上下文对象,对应整个Servlet项目,此方法同时实现了Servlet接口中的 init 初始化方法
public ServletContext getServletContext();
            
// 符合HTTP协议的Servlet,继承自GenericServlet,最常用,需要重写 doGet 和 doPost 方法    
public abstract class HttpServlet;

// 符合HTTP GET请求的处理方式
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
     
// 符合HTTP POST请求的处理方式     
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
         
// 用于 Servlet 之间的通信
public interface ServletContext;
    
// 扩展ServletRequest接口,为HTTP servlet提供请求信息。servlet容器创建一个HttpServletRequest对象,并将其作为参数传递给servlet的服务方法(doGet、doPost)。
public interface HttpServletRequest;
    
// 扩展ServletResponse接口以在发送响应时提供特定于http的功能。servlet容器创建一个HttpServletResponse对象,并将其作为参数传递给servlet的服务方法(doGet、doPost等)。
public interface HttpServletResponse;
    
// 提供一种技术来识别跨多个页面请求或访问Web站点的用户,并存储有关该用户的信息,用于会话技术
public interface HttpSession;
    
// 创建一个cookie, servlet发送给Web浏览器的少量信息,由浏览器保存,然后发送回服务器。cookie的值可以唯一地标识客户端,因此cookie通常用于会话管理。
public class Cookie;

【重点】HttpServlet 中的 doGet 和 doPost 方法

三种创建 Servlet 的方式

【注意】不管是哪种方式都一定要加上@WebServlet注解!!!

实现 servlet 接口【鸡肋】

/**
 * 实现Servlet接口
 * 代码中存在太多和业务逻辑无关的代码,增加了程序员的压力!!!
 * 不要这么写!!!
 */
@WebServlet("/ServletImpl")
public class ServletImpl implements Servlet {

    /**
     * 构造方法
     */
    public ServletImpl() {
        System.out.println("constructor method be called");
    }

    /**
     * 初始化方法
     *
     * @param servletConfig 需要使用ServletConfig类对象,也就是Servlet配置来完成初始化操作
     * @throws ServletException Servlet异常
     */
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init method be called");
    }

    /**
     * 获取Servlet配置对象
     *
     * @return 获取ServletConfig对象
     */
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /**
     * 提供服务核心方法,其实就是doGet和doPost
     *
     * @param servletRequest ServletRequest对象
     * @param servletResponse ServletResponse对象
     * @throws ServletException Servlet异常
     * @throws IOException      IO异常
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service method be called");

        // 设置字符集为UTF-8
        servletResponse.setContentType("text/html; charset=utf-8");

        // 写入内容
        servletResponse.getWriter().append("<font color=red size=30px style=text-align: center>service方法被执行~</font>");
    }

    /**
     * 获取Servlet信息
     * @return Servlet信息
     */
    @Override
    public String getServletInfo() {
        return null;
    }

    /**
     * 销毁的方法
     */
    @Override
    public void destroy() {
        System.out.println("destroy method be called");
    }
}

太过繁琐,需要关注的东西太多,pass

继承 GenericServlet 类【鸡肋】

/**
 * 继承自GenericServlet创建Servlet
 */
@WebServlet("/ExtendsGeneric")
public class ExtendsGeneric extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        servletResponse.setContentType("text/html; charset=utf-8");

        servletResponse.getWriter().append("<div style='color: aquamarine'>北纬线的思念被季风吹远</div>");
    }
}

相比于实现 Servlet,友好太多,但是还不够友好,因为没有对应Http协议请求的处理方法

继承 HttpServlet 类【重点】

/**
 * 继承自HttpServlet创建Servlet
 */
@WebServlet("/ExtendsHttpServlet")
public class ExtendsHttpServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=utf-8");
        resp.getWriter().append("<font color='green' size=7>晚餐可以吃午餐肉吗?</font>");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

【注意】一定要重写 doGet 和 doPost 方法

使用继承 HttpServlet 类的优点

HttpServlet 在实现 Servlet 接口的时候,已经实现了 servlet 中所有方法,因此继承自 HttpSrvlet 的类,不需要再去重写相应的生命周期等方法,并且支持 HTTP 协议

Servlet 生命周期

  • Servlet 构造方法被执行
  • 然后使用 init 方法进行初始化。
  • 浏览器端对 service 方法的任何调用都将被处理
  • Servlet 退出,使用 destroy 方法进行销毁,然后垃圾收集并完成。

案例代码

/**
 * Servlet生命周期
 */
@WebServlet("/ServletLife")
public class ServletLife implements Servlet {

    /**
     * 构造方法
     */
    public ServletLife() {
        System.out.println("ServletLife Constructor called");
    }

    /**
     * 初始化方法
     *
     * @param config 需要使用ServletConfig类对象,也就是Servlet配置来完成初始化操作
     * @throws ServletException Servlet异常
     */
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("init method called");
    }

    /**
     * 获取ServletConfig对象
     *
     * @return 获取ServletConfig对象
     */
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /**
     * 提供服务核心方法
     *
     * @param req ServletRequest对象
     * @param res ServletResponse对象
     * @throws ServletException Servlet异常
     * @throws IOException      IO异常
     */
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("service method called");
    }

    /**
     * 获取Servlet信息
     * @return Servlet字符串信息
     */
    @Override
    public String getServletInfo() {
        return null;
    }

    /**
     * 销毁Servlet
     */
    @Override
    public void destroy() {
        System.out.println("destroy method called");
    }
}

两种配置方式【重点】

通过 @WebServlet 注解

@WebServlet注解用于标注在一个继承了HttpServlet类之上,属于类级别的注解

【注意】Servlet3.0之后允许使用注解方式配置!!!

常用格式

@WebServlet("/TestServlet")
public class useAnnotation extends HttpServlet {
    doGet();
    doPost();
}

常用属性描述

属性类型是否必须描述
asyncSupportedboolean指定Servlet是否支持异步操作
displayNameString指定Servlet显示名称
initParamsWebInitParam[]配置初始化参数
loadOnStartupint标记容器是否在应用启动时就加载这个Servlet,默认 -1,选择加载 1
nameString指定Servlet名称
urlPatternsString[]是/否允许当前Servlet有多个匹配方式,和value互斥
value【重点】String[]否/是url资源匹配方式,和urlPatterns互斥

案例代码

/**
 * 通过注解配置Servlet
 */
@WebServlet(urlPatterns = {"/urlPatterns", "/aa"}, // 多个匹配路径,与value属性互斥,只能存在一个
        name = "AnnotationServlet", // 自定义Servlet名,没啥用
        displayName = "AnnotationServlet", // 显示名,没啥用
        loadOnStartup = 1,  // 加载时自动启动
        initParams = {@WebInitParam(name = "username", value = "易烊千玺"), @WebInitParam(name = "password", value = "欧阳娜娜")}) // 初始化参数
public class UseOnAnnotation extends HttpServlet {
    public UseOnAnnotation() {
        System.out.println("constructor be called");
    }
    
    @Override
    public void init() throws ServletException {
        System.out.println("init method be called");
        super.init();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=utf-8");

        resp.getWriter().append("test annotation");

        // 获取初始化参数
        String username = getServletConfig().getInitParameter("username");
        String password = getServletConfig().getInitParameter("password");

        resp.getWriter().append(username).append(":").append(password);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        doPost(req, resp);
    }
}

通过 web.xml 文件

核心内容

<!--Servlet核心配置,必须告知Servlet程序对应的名字和Servlet程序对应的class(Java类)-->
<servlet>
    <!-- ServletName -->
    <servlet-name>UseWebXML</servlet-name>
    <!-- Servlet对应的class,必须是完整的包名.类名 -->
    <servlet-class>com.fc.d_configServlet.UseWebXML</servlet-class>
</servlet>

<!-- Servlet映射关系 -->
<servlet-mapping>
    <!--声明映射到哪一个Servlet,必须与Servlet-name中相同-->
    <servlet-name>UseWebXML</servlet-name>
    <!--URL-->
    <url-pattern>/UseWebXML</url-pattern>
</servlet-mapping>

XML 配置文件

<?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_3_1.xsd"
         version="3.1">

    <!--Servlet核心配置,必须告知Servlet程序对应的名字和Servlet程序对应的class(Java类)-->
    <servlet>
        <!-- ServletName -->
        <servlet-name>UseWebXML</servlet-name>
        <!-- Servlet对应的class,必须是完整的包名.类名 -->
        <servlet-class>com.fc.d_configServlet.UseWebXML</servlet-class>

        <!-- 当前Servlet程序初始化操作,需要放在servlet-class之后 -->
        <init-param>
            <param-name>彭于晏</param-name>
            <param-value>真帅</param-value>
        </init-param>
        <init-param>
            <param-name>欧阳娜娜</param-name>
            <param-value>真美</param-value>
        </init-param>

        <!-- Tomcat启动时当前Servlet -->
        <load-on-startup>1</load-on-startup>

    </servlet>

    <!-- Servlet映射关系 -->
    <servlet-mapping>
        <!--声明映射到哪一个Servlet,必须与Servlet-name中相同-->
        <servlet-name>UseWebXML</servlet-name>
        <!--URL-->
        <url-pattern>/UseWebXML</url-pattern>
    </servlet-mapping>

    <!-- Servlet映射关系2 -->
    <servlet-mapping>
        <!--声明映射到哪一个Servlet,必须与Servlet-name中相同-->
        <servlet-name>UseWebXML</servlet-name>
        <!--第二个URL-->
        <url-pattern>/UseWebXML2</url-pattern>
    </servlet-mapping>
</web-app>

案例代码

/**
 * 使用Web.xml方式
 */
public class UseWebXML extends HttpServlet {
    public UseWebXML() {
        System.out.println("constructor be called");
    }

    @Override
    public void init() throws ServletException {
        System.out.println("init method be called");
        super.init();
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=utf-8");
        resp.getWriter().append("猫(>^ω^<)喵");

        String parameter1 = getServletConfig().getInitParameter("彭于晏");
        String parameter2 = getServletConfig().getInitParameter("欧阳娜娜");

        System.out.println(parameter1 + ":" + parameter2);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

两种方式比较

   @WebServlet注解
       配置简单,直观,高效
       url-pattern 冲突问题,并且是在Tomcat启动时发现,需要注意细节
   
   web.xml配置文件
       繁琐,麻烦,步骤繁多
       url-pattern 一旦写错或者冲突,web.xml文件会提示错误!!!
当前页面是本站的「Baidu MIP」版。发表评论请点击:完整版 »