前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Servlet详解

Servlet详解

作者头像
秋白
发布2019-02-21 09:53:27
发布2019-02-21 09:53:27
60000
代码可运行
举报
文章被收录于专栏:java小白java小白
运行总次数:0
代码可运行

一、简介

Servlet是server+Applet的缩写,表示一个服务器应用。Servlet就是一套规范,按照这套规范写的代码就可以直接在Java服务器上面运行。

二、Servlet接口

Servlet是一套规范,那么在Java中规范则是接口。

2.1 Servlet3.1中Servlet的接口定义如下
代码语言:javascript
代码运行次数:0
运行
复制
public interface Servlet {
    public void init(ServletConfig config) throws ServletException;
    public ServletConfig getServletConfig();    
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;	
    public String getServletInfo();    
    public void destroy();
}

Servlet接口介绍

web.xml配置

代码语言:javascript
代码运行次数:0
运行
复制
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.lbx.servlet.HelloServlet</servlet-class>
        <init-param>
            <param-name>initParam</param-name>
            <param-value>initValue</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

1 public void init(ServletConfig config) throws ServletException;

 <load-on-startup>值</load-on-startup> 

  1. init()方法初始化内容,被调用时,web容器会把config依赖传进去。
  2. load-on-startup的值不为负数时,web容器启动时会调用init方法。
  3. 没有填写load-on-startup标签或者标签里面的值是负数的话,访问该Servlet的时候会才会调用init方法。
  4. 同一个Servlet的init方法在整个流程中只会调用一次。

2  public  ServletConfig getServletConfig();  

        getServletConfig()方法用来获取Servlet的配置,比如上面 <init-param>标签里面的参数。下面会详细介绍这个方法。

3 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException; 

        service方法用于处于请求,web容器会解析HTTP协议,封装成对象传进去。

4  public String getServletInfo();  

        getServletInfo()获取servlet相关的信息,如作者、版权等,这个方法在需要自己实现,默认返回空字符串。

5 public void destroy();

        destory()方法主要用于Servlet的销毁,当应用从tomcta移除或者关闭服务器时会被调用,用于释放资源,只会调用一次。

2.2 ServletConfig接口定义

代码语言:javascript
代码运行次数:0
运行
复制
public interface ServletConfig {
    public String getServletName();
    public ServletContext getServletContext();
    public String getInitParameter(String name);
    public Enumeration<String> getInitParameterNames();
}

ServeltConfig接口介绍

  1. getServeltName():用于获取Servlet的名字,也就是web.xml中定义的servlet-name。
  2. getServeltContext():获取ServeltContext对象,全局共享这个对象,一个应用中只能有一个ServletContext对象。可获取<context-param>里面内容。
  3. getInitParameter(): 获取init-param配置的值。
  4. getInitParameterNames():获取配置的所有Init-param的名字集合。

三、GenericServlet

     GenericServlet这个类实现了Servlet和ServletConfig接口(service()方法用abstract修饰了),可以直接调用Servlet和ServletConfig里的方法,比如获取ServletConfig中的方法时候可以直接调用,而无须调用getServletConfig().getServletContext()了,不过底层实现其实是在内部调用了,代码如下:

代码语言:javascript
代码运行次数:0
运行
复制
    public ServletContext getServletContext() {
        ServletConfig sc = getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(
                lStrings.getString("err.servlet_config_not_initialized"));
        }

        return sc.getServletContext();
    }

GenericServlet实现了Servlet的init(ServletConfig config)方法,在里面将config复制给了内部变量config,然后调用无参的init()方法,这个方法是模板方法,在子类中可以通过覆盖它来完成自己的初始化工作。

代码语言:javascript
代码运行次数:0
运行
复制
public void init(ServletConfig config) throws ServletException {
	this.config = config;
	this.init();
}
public void init() throws ServletException {

}

这种做法有三个作用:

  1. 将参数config设置给内部属性config,这样有其他地方需要这个对象就可直接调用。
  2. 做初始化操作时,不用关心config对象。
  3. 重写init()方法不需要调用super.init(config)。

四、HttpServlet

这个类是我们最常使用的类,继承了GenericServlet,写servlet直接继承就可以了,无需重新实现Servlet接口,这个类主要作用是如何处理请求。

看代码:

代码语言:javascript
代码运行次数:0
运行
复制
    @Override
    public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException
    {
        HttpServletRequest  request;
        HttpServletResponse response;
        
        if (!(req instanceof HttpServletRequest &&
                res instanceof HttpServletResponse)) {
            throw new ServletException("non-HTTP request or response");
        }
        //向下转型为HttpServletRequest
        request = (HttpServletRequest) req;
        response = (HttpServletResponse) res;
        //调用http的处理方法
        service(request, response);
    }

问题一:为什么可以将ServletRequest 强转为HttpServletRequest呢?

     因为在tomcat内部创建的这个request它就是httpServletRequest接口的子类。

问题二:为什么要将ServletRequest 强转为HttpServletRequest呢?

  1. 因为ServletRequest中只提供了获取基本信息的方法。没有获取用户请求类型的方法,而且还包含了许多方法。

执行完上面方法,最后会调用service方法,调用的不是用一个service,因为传入参数类型不一样,重载方法

这个方法的作用是:获取Http请求类型,将不同请求类型路由到不同的处理方法。具体方法都是doXXX的结构,doGet,doPost,doPut,doDelete方法都是模板方法,而且如果子类没有实现将返回404错误页面。

代码语言:javascript
代码运行次数:0
运行
复制
 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) {
                doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                if (ifModifiedSince < lastModified) {
                   
                    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 {
           
            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);
        }
    }

流程图

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018年06月17日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、简介
  • 二、Servlet接口
    • Servlet接口介绍
    • 2.2 ServletConfig接口定义
    • ServeltConfig接口介绍
  • 三、GenericServlet
  • 四、HttpServlet
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档