1 servlet

一. javax.Servlet 包

图中展示了 Javax.Servlet 包中的主要类

这里写图片描述
这里写图片描述

  • Servlet 技术的核心是 Servlet 接口, 这是所有 Servlet 类都要直接或间接实现的接口。
  • Servlet 接口定义了 Servlet 与Servlet容器 之间的契约。Servlet 容器会把 Servlet 类加载到内存中, 并在 Servlet 实例中调用特定的方法。在一个应用中, 每一个 Servlet 只能有一个实例。
  • 用户的请求会引发 Servlet 容器调用一个 Servlet 的 service 方法, 并传入 ServletRequest 和 ServletResponse 参数

public class TestServlet implements Servlet {
//init方法在用户第一次发送请求时由 Servlet 容器调用, 并传递一个 ServletConfig 参数,
// 一般情况下这个参数会赋值给类级变量, 以便类中其他方法调用
@Override
public void init(ServletConfig servletConfig) throws ServletException {}

//service方法是用户发送请求时调用, 并且传入 Servletrequest 和 Servletresponse
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {}

//destory方法是在 Servlet 销毁时调用, 一般是在卸载应用时, 可以在这个方法内做清理工作
@Override
public void destroy() {}

//返回关于此 Servlet 的相关信息
@Override
public String getServletInfo() {
    return null;
}

//返回init 中 Servlet 容器传递进来的 ServletConfig 
@Override
public ServletConfig getServletConfig() {
    return null;
}

}
其中
@Override
public void init(ServletConfig servletConfig) throws ServletException {}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
@Override
public void destroy() {}
这三个是声明周期方法
注意: 一个应用中, 所有的用户的同一个请求将公用一个 Servlet 实例, 所以不建议使用类级变量, 除非是只读的, 或者是 java.util.concurrent,atomic 包中的成员
二. servlet 实现

  1. 自己的 Servlet
    @WebServlet(name = “MyServlet”, urlPatterns = {"/my"})
    public class MyServlet implements Servlet {
    private transient ServletConfig servletConfig;
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
    System.out.println(“init”);
    this.servletConfig = servletConfig;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    System.out.println(“service”);
    String serviceName = servletRequest.getServerName();
    String servletName = this.servletConfig.getServletName();
    servletResponse.getWriter().println("" +
    “” +
    " hello from “+servletName+”…"+serviceName+"" +
    “”);
    }

    @Override
    public void destroy() {
    System.out.println(“destroy”);
    }

    @Override
    public String getServletInfo() {
    System.out.println(“getServletInfo”);
    return “My Servlet”;
    }

    @Override
    public ServletConfig getServletConfig() {
    System.out.println(“getServletConfig”);
    return this.servletConfig;
    }
    }

<?xml version="1.0" encoding="UTF-8"?>

<servlet>
    <servlet-name>MyServlet2</servlet-name>
    <servlet-class>com.zcz.study.servlet.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>MyServlet2</servlet-name>
    <url-pattern>/mm</url-pattern>
</servlet-mapping>
  • 注意:在上面代码中, 设置了两种 servelt 访问方式, 一种是注解, 一种是配置 web.xml
  • @WebServlet(name = “MyServlet”, urlPatterns = {"/my”}) 注解中name 可选 定义了本 servlet 的名字, urlPatterns可选, 定义 servlet 访问匹配 url 模式 一般不会省略
  • web.xml配置 servlet 名 , servlet 全限定名, servlet访问url匹配模式
  • 注意: 同一个 Servlet类, 在一个应用中只做一次初始化, 并且所有用户访问同一接口, 共用一个 servlet 实例,但如果注解方式与 web.xml 方式都配置了同一 Servlet 访问, 并且, servlet 名与 url 匹配模式不同, 则这个 servlet 类会产生两个 servlet 实例, 如果, servlet 名配置相同, url 匹配不同, 只匹配 web.xml 的配置, 注解无效, 如果 url 配置相同, servlet 名不同, 应用启动失败org.apache.catalina.LifecycleException(个人发现, so 同一个Servlet 不要设置两种访问)
    三. ServletConfig
  • 获取 Servlet 初始化参数的值, 使用 Servlet 初始化是调用的 init()方法中传入 ServletConfig, 调用获取方法
  • getInitParameter(String name); 获取某一初始化参数
  • servletConfig.getInitParameterNames() 获取所有初始化参数, 返回值为所有初始化名称的一个 Enumeration
  • 最重要的方法就是 getServletContext(); ServletContext 是一个 Servlet 的上下文, 后续介绍,十分重要
  • ServletConfig 接口代码如下

package javax.servlet;

import java.util.Enumeration;

public interface ServletConfig {
String getServletName();

ServletContext getServletContext();

String getInitParameter(String var1);

Enumeration<String> getInitParameterNames();

}
ServletConfig中初始化参数的配置也分两种, 一种是注解方式, 另一种是 web.xml 方式 如下

@WebServlet(name = “ServletConfigDemo”,
urlPatterns = {"/ServletConfigDemo.html"},
initParams = {@WebInitParam(name = “userInfo”, value = “zcz”),
@WebInitParam(name = “email”, value = "123321@163.com")})
public class ServletConfigDemo implements Servlet {
private transient ServletConfig servletConfig;

@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    PrintWriter writer = servletResponse.getWriter();
    Enumeration enumeration =  servletConfig.getInitParameterNames();
    List<String> list = new ArrayList<>();
    while (enumeration.hasMoreElements()){
        String s = (String) enumeration.nextElement();
        System.out.println(s);
        String s1 = this.servletConfig.getInitParameter(s);
        System.out.println(s1);
        list.add(s1);
    }
    writer.print("<html>" +
            "<head></head>" +
            "<body>"+servletConfig.getServletContext().getContextPath()+"</body>" +
            "</html>");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
    this.servletConfig = servletConfig;
}

@Override
public ServletConfig getServletConfig() {
    return this.servletConfig;
}

@Override
public String getServletInfo() {
    return "ServletConfigDemo";
}

@Override
public void destroy() {

}

}

servletConfigDemo
com.zcz.study.servlet.ServletConfigDemo

userInfo
zzz


email
123321@qq.com



servletConfigDemo
/ServletConfigDemo.html

四. ServletContext

  • ServletContext 表示 Servlet 应用程序。
  • 每个应用程序只有一个 Context。
  • 在分布式环境中, 一个应用程序同事部署到 多个容器中, 并且每台 Java 虚拟机都有一个 ServletContext对象。
  • ServletContext可以共享能通过应用程序的所有资源访问信息, 内不是由一个 Map 存储实现的。
    五. GenericServlet

public abstract class GenericServlet implements Servlet, ServletConfig, Serializable

  • 它是一个抽象类,实现了部分 Servlet, ServletConfig 的部分接口, 使开发者舍去了不必要的操作

public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {}

  • ServletConfig 不需要开发者去定义初始化了, 在 GenericServlet 中有了默认实现, 但如果开发者还想自己实现其它的初始化内容, 可以覆盖 GenericServlet 方法中的 init()方法, 这是一个无参方法, 并且不会覆盖 servletConfig 的初始化.

public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

  • 开发者要创建自己的 Servlet 可以继承 GenericServlet 抽象类, 大多数情况下只需要实现唯一抽象方法Service 方法即可
    六. Http Servlet
    我们所写的大多数 Servlet 都是用来处理 Http 请求的, 在 ServletApi.jar 中有一个包 javax.servlet.http ,包含了所有处理 Http请求的类, javax.servlet.http中许多类都覆盖了 javax.servlet中的类型,下图为主要类与包截图
    这里写图片描述

这里写图片描述

  1. HttpServlet

public abstract class HttpServlet extends GenericServlet

  • HttpServlet是继承 GenericServlet , 在HttpServlet中, 不需要再覆盖 service 方法, 它将 service 方法根据请求的不同实现了doGet, doPost, doHead, doPut, doTrace, doOptions, doDelete 这七个方法, 这七个方法分别表示一种 Http请求, 但最常用的是 doGet和 doPost, 一般只覆盖这两个方法即可.
    下面是 HttpServlet 中重写的父类 service方法
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    HttpServletRequest request;
    HttpServletResponse response;
    try {
    request = (HttpServletRequest)req;
    response = (HttpServletResponse)res;
    } catch (ClassCastException var6) {
    throw new ServletException(“non-HTTP request or response”);
    }

    this.service(request, response);
    }

  • 将 ServletRequest 和 ServletResponse 向下转换为 HTTPServletRequest 和 HttpServletresponse总是能成功, 因为在调用一个 Servlet 的 service方法时, Servlet 容器总会预计使用Http, 所以传递一个HTTPServletRequest 和 HttpServletresponse.

下面方法是 HttpService 自己实现的 service方法, 将请求响应分发到各自的请求中
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if(method.equals(“GET”)) {
lastModified = this.getLastModified(req);
if(lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader(“If-Modified-Since”);
} catch (IllegalArgumentException var9) {
ifModifiedSince = -1L;
}

        if(ifModifiedSince < lastModified / 1000L * 1000L) {
            this.maybeSetLastModified(resp, lastModified);
            this.doGet(req, resp);
        } else {
            resp.setStatus(304);
        }
    }
} else if(method.equals("HEAD")) {
    lastModified = this.getLastModified(req);
    this.maybeSetLastModified(resp, lastModified);
    this.doHead(req, resp);
} else if(method.equals("POST")) {
    this.doPost(req, resp);
} else if(method.equals("PUT")) {
    this.doPut(req, resp);
} else if(method.equals("DELETE")) {
    this.doDelete(req, resp);
} else if(method.equals("OPTIONS")) {
    this.doOptions(req, resp);
} else if(method.equals("TRACE")) {
    this.doTrace(req, resp);
} else {
    String errMsg = lStrings.getString("http.method_not_implemented");
    Object[] errArgs = new Object[]{method};
    errMsg = MessageFormat.format(errMsg, errArgs);
    resp.sendError(501, errMsg);
}

}

七. web.xml与注解
web.xml 中的 servlet 配置可以覆盖注解的配置, 并且 web.xml 中可以添加注解中没有的属性,
例如

MyServlet2
com.zcz.study.servlet.MyServlet
10

10 配置使 servlet 在应用启动时创建, 而不是第一次调用时创建,如果一个 Servlet 的初始化非常耗时, 那么这个配置就相当重要了
关于 web.xml 将在后续详细学习

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值