Java Web 之 Servlet

1.Servlet接口

1.1先看下Servlet接口都有些什么方法

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();
}

1.2再看下ServletConfig 接口的方法

public interface ServletConfig {
    public String getServletName();

    public ServletContext getServletContext();

    public String getInitParameter(String name);

    public Enumeration<String> getInitParameterNames();
}

2. Servlet 的典型实现类

接下来看看Servlet的子类以及其实现代码

  • public abstract class HttpServlet extends GenericServlet
  • public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable

2.1先看看GenericServlet 类

public abstract class GenericServlet implements Servlet, ServletConfig,
        java.io.Serializable {
    private static final long serialVersionUID = 1L;
    private transient ServletConfig config;

    public GenericServlet() {
        // NOOP
    }
    
来自于Servlet接口的方法开始/
    @Override
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        // 在此调用子类重写的方法,如果重写了的话
        this.init();
    }
    
	// 此方法用于被子类重写
    public void init() throws ServletException {
        // NOOP by default
    }
    
    @Override
    public ServletConfig getServletConfig() {
        return config;
    }
    
    @Override
    public abstract void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException;
    
    @Override
    public String getServletInfo() {
        return "";
    }
       
    @Override
    public void destroy() {
        // NOOP by default
    }
来自于Servlet接口的方法结束/

来自于ServletConfig 接口的方法开始/

    @Override
    public String getServletName() {
        return config.getServletName();
    }
   
    @Override
    public ServletContext getServletContext() {
        return getServletConfig().getServletContext();
    }
    
    @Override
    public String getInitParameter(String name) {
        return getServletConfig().getInitParameter(name);
    }

    @Override
    public Enumeration<String> getInitParameterNames() {
        return getServletConfig().getInitParameterNames();
    }
    
来自于ServletConfig 接口的方法结束/
下面为此类中自定义的两个方法/
    public void log(String msg) {
        getServletContext().log(getServletName() + ": " + msg);
    }
    
    public void log(String message, Throwable t) {
        getServletContext().log(getServletName() + ": " + message, t);
    }
}

2.2再来看看HttpServlet类的实现代码(代码太多了,只提取关键的代码)

public abstract class HttpServlet extends GenericServlet {

    private static final long serialVersionUID = 1L;

    private static final String METHOD_DELETE = "DELETE";
    private static final String METHOD_HEAD = "HEAD";
    private static final String METHOD_GET = "GET";
    private static final String METHOD_OPTIONS = "OPTIONS";
    private static final String METHOD_POST = "POST";
    private static final String METHOD_PUT = "PUT";
    private static final String METHOD_TRACE = "TRACE";

    private static final String HEADER_IFMODSINCE = "If-Modified-Since";
    private static final String HEADER_LASTMOD = "Last-Modified";

    private static final String LSTRING_FILE =
        "javax.servlet.http.LocalStrings";
    private static final ResourceBundle lStrings =
        ResourceBundle.getBundle(LSTRING_FILE);


    /**
     * Does nothing, because this is an abstract class.
     */
    public HttpServlet() {
        // NOOP
    }
    	// 从父类集成过来的service方法
    @Override
    public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException {

        HttpServletRequest  request;
        HttpServletResponse response;
		
		// 将传入的 ServletRequest 强转为 HttpServletRequest 类型
		// 将传入的 ServletResponse 强转为 HttpServletResponse 类型
        try {
            request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
        } catch (ClassCastException e) {
            throw new ServletException("non-HTTP request or response");
        }
        // 调用下面的service 方法,针对于不同的请求类型做对应的处理
        service(request, response);
    }
    
    
  	protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

		// 获取到请求类型
        String method = req.getMethod();
		// 依据请求方式的不同,调用对应的方法处理
		// 如果是Get形式的请求
        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;
                try {
                    ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                } catch (IllegalArgumentException iae) {
                    // Invalid date header - proceed as if none was set
                    ifModifiedSince = -1;
                }
                if (ifModifiedSince < (lastModified / 1000 * 1000)) {
                    // 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);
		// 如果是Post形式的请求
        } 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);
        }
    }

	// 一般继承 HttpServlet 时,将重写此方法
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_get_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
        } else {
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
        }
    }

    protected long getLastModified(HttpServletRequest req) {
        return -1;
    }

    protected void doHead(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

        if (DispatcherType.INCLUDE.equals(req.getDispatcherType())) {
            doGet(req, resp);
        } else {
            NoBodyResponse response = new NoBodyResponse(resp);
            doGet(req, response);
            response.setContentLength();
        }
    }
	// 一般继承 HttpServlet 时,将重写此方法
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_post_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
        } else {
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
        }
    }

    protected void doPut(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_put_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
        } else {
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
        }
    }

    protected void doDelete(HttpServletRequest req,
                            HttpServletResponse resp)
        throws ServletException, IOException {

        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_delete_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
        } else {
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
        }
    }

    protected void doOptions(HttpServletRequest req,
            HttpServletResponse resp)
        throws ServletException, IOException {
	// 方法体省略
    }

    protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
	// 方法体省略
    }

}

2.3我们自己再实现一个Servlet 继承自HttpServlet

public class HelloWorldServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	// 重写在 HttpServlet 中实现的 doPost 方法
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}
	
	// 重写在 HttpServlet 中实现的 doGet 方法
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		ServletConfig config = getServletConfig();

		String user = config.getInitParameter("user");
		System.out.println("user:" + user);

		// 获取全部参数名组成的 Enumeration
		Enumeration<String> parameters = config.getInitParameterNames();
		while (parameters.hasMoreElements()) {
			String param = parameters.nextElement();
			String value = config.getInitParameter(param);
			System.out.println("param: " + param + " value: " + value);
		}

		String servletName = config.getServletName();
		System.out.println("servletName: " + servletName);

		ServletContext servletContext = config.getServletContext();
		String driver = servletContext.getInitParameter("driver");
		System.out.println("driver: " + driver);

		PrintWriter writer = resp.getWriter();
		writer.write("HelloWorld!");
		writer.flush();
		writer.close();
	}
}
// 控制台打印
// user:root
// param: user value: root
// servletName: helloWorld
// driver: com.mysql.jdbc.Driver

3. 启动时web.xml的配置

	<context-param>
		<param-name>driver</param-name>
		<param-value>com.mysql.jdbc.Driver</param-value>
	</context-param>

	<servlet>
		<servlet-name>helloWorld</servlet-name>
		<servlet-class>org.lhyf.servlet.HelloWorldServlet</servlet-class>
		<init-param>
			<param-name>user</param-name>
			<param-value>root</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>helloWorld</servlet-name>
		<url-pattern>/helloword</url-pattern>
	</servlet-mapping>

4. 总结

所有的servlet必须实现定义的方法。
servlet是一个在Web服务器中运行的小型Java程序。 Servlet通常通过HTTP(超文本传输​​协议)接收和响应来自Web客户端的请求。要实现此接口,可以编写扩展 javax.servlet.GenericServlet 或扩展 javax.servlet.http.HttpServlet。
这些被称为生命周期方法,按以下顺序调用:

  1. 构造器:第一次请求Servlet时,创建Servlet的实例,调用构造器(只被调用一次,单例的)
  2. 然后使用init方法初始化。只被调用一次,在创建好实例后立即被调用,用于初始化当前Servlet(当多次访问同一个Servlet时,构造器和init方法只在第一次访问时被调用。)
  3. service方法。被多次调用,每次请求都会调用service方法,用来响应请求。
  4. servlet停止服务,然后使用destroy方法销毁,然后收集垃圾并完成。
    除了生命周期方法之外,该接口还提供了getServletConfig方法,servlet可用于获取任何启动信息,以及getServletInfo方法,该方法允许servlet返回有关其自身的基本信息。

load-on-startup 可以指定Servlet被创建的时机,若为负数,则在第一次请求时创建,若为0或正数,则在当前WEB应用被Servlet容器加载时创建并初始化,且数字越小,越早被创建。
ServletConfig 封装了Servlet的配置信息,并且可以获取 ServletContext 对象

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值