zoukankan      html  css  js  c++  java
  • Servlet和JSP读书笔记(二)

    一. GenericServlet

       1. 前面写的 Servlet和JSP学习笔记(一) 中的实例都是通过实现Servlet接口编写的,这样存在的问题就是:你必须实现Servlet中的所有方法,而不管该方法是否包含有用的

    代码。所以,在此基础上Servlet API 为我们提供了GenericServlet 抽象类。

         2. javax.servlet.GenericServlet接口 的源码如下:

    package javax.servlet;
    
    import java.io.IOException;
    import java.util.Enumeration;
    
    
    public abstract class GenericServlet implements Servlet, ServletConfig,
            java.io.Serializable {
    
        private static final long serialVersionUID = 1L;
    
        private transient ServletConfig config;

    public GenericServlet() { // NOOP }   
        
    @Override public void destroy() { // NOOP by default }

    @Override public String getInitParameter(String name) { return getServletConfig().getInitParameter(name); } @Override public Enumeration<String> getInitParameterNames() { return getServletConfig().getInitParameterNames(); }   /*
          为我们提供了方法获取ServletConfig实例

        */
    @Override public ServletConfig getServletConfig() { return config; } @Override public ServletContext getServletContext() { return getServletConfig().getServletContext(); } @Override public String getServletInfo() { return ""; } /*   在此方法中将ServletConfig对象赋值给一个类成员变量,通过getServletConfig()获取该类级成员变量

      */ @Override public void init(ServletConfig config) throws ServletException { this.config = config; this.init(); } public void init() throws ServletException { // NOOP by default } public void log(String msg) { getServletContext().log(getServletName() + ": " + msg); } public void log(String message, Throwable t) { getServletContext().log(getServletName() + ": " + message, t); } @Override public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;  public String getServletName() { return config.getServletName(); } }

        该抽象类主要做了一下的三件事:

        ①在init方法中将ServletConfig对象赋值给一个类成员变量,通过getServletConfig()获取该类级成员变量。

        ②为Servlet接口中的方法供默认实现。

        ③ 提供方法包装ServletConfig中的方法。

      2. GenericServlet示例。

        备注:根据源码个人需求,在继承GenericServlet抽象类时,我们只需要实现service抽象方法就可以了,其他的方法GenericServlet已经帮我们做了处理。

        ① 编写Servlet 类

    package com.hjj.servlet.two;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.GenericServlet;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    
    public class TestGenericServlet extends GenericServlet {
    
        @Override
        public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
            String name = this.getServletConfig().getInitParameter("two");
            response.setContentType("text/html");
            response.setCharacterEncoding("UTF-8");
            PrintWriter pw = response.getWriter();
            pw.print("<html><head><head><title>测试GenericServlet</title><body> hello "+name+"</body></html>");
                    
            
        }
            
    }

        

        ②因为在之前的实例中我用的是注解的方式进行servlet的配置,所以在这里我使用web.xml进行配置。

     

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE web-app 
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
    "http://java.sun.com/dtd/web-app_2_3.dtd"> 
    <web-app> 
        <servlet>
            <servlet-name>testGenericServlet</servlet-name>
            <servlet-class>com.hjj.servlet.two.TestGenericServlet</servlet-class>
            <init-param>
                <param-name>two</param-name>
                <param-value>GenericServlet</param-value>
            </init-param>
        </servlet>
        
        <servlet-mapping>
            <servlet-name>testGenericServlet</servlet-name>
            <url-pattern>/testGenericServlet</url-pattern>
        </servlet-mapping>
        
    </web-app> 

      

    二. Servlet中的第二个包 javax.servlet.http.* 的主要类型 

        备注:这个包中提供的HttpServlet为我们编写Servlet提供另外一种写法

    public abstract class javax.servlet.http.HttpServlet
    public interface javax.servlet.http.HttpServletRequest
    
    public interface javax.servlet.http.HttpServletResponse

    三.  public class javax.servlet.http.HttpServlet

      1. HttpServlet具体信息为:public abstract class HttpServlet extends  GenericServlet implements java.io.Serializable

      2.该类的部分源码如下:

        

    package javax.servlet.http;
    
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.io.UnsupportedEncodingException;
    import java.lang.reflect.Method;
    import java.text.MessageFormat;
    import java.util.Enumeration;
    import java.util.ResourceBundle;
    
    import javax.servlet.DispatcherType;
    import javax.servlet.GenericServlet;
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    
    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 ResourceBundle lStrings =
            ResourceBundle.getBundle(LSTRING_FILE);
    
        public HttpServlet() {
            // NOOP
        }
    
    
        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 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);
            }
        }
    
      //重载的service方法
        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) {
                    // 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);
    
            } 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);
            }
        }
    
    
       //重写父类GenericServlet的service 
        @Override
        public void service throws ServletException, IOException {
    
            HttpServletRequest  request;
            HttpServletResponse response;
    
            try {
                request = (HttpServletRequest) req;
                response = (HttpServletResponse) res;
            } catch (ClassCastException e) {
                throw new ServletException("non-HTTP request or response");
            }

        
     //实际上调用上的还是上面的重载的方法:protected void service(HttpServletRequest req, HttpServletResponse resp)
         service(request, response);
      }
        
        //此处省略部分源码
    }

      3. 该类继承了GenericServlet。重写的service方法,传递的参数依然是ServletRequest实例和ServletResponse实例。但是我们可以看到源码,它把ServletRequest和

    ServletResponse两个实例分别转化为HttpServletRequest和HttpServletResponse实例。同时实现了重载了一个方法: service(HttpServletRequest req,

    HttpServletResponse resp)。并且在参数类型为ServletRequest和ServletResponse的重写方法service 中调用了参数类型为HttpServletRequest 和

    HttpServletResponse 的重载方法 service。service重载方法做的事情为:判断请求的类型是GET、POST、HEAD、OPTIONS、PUT、DELETE或者TRACE,然后分别调用相应

    的doGet,doPost,doHead,doOptions,doPut,doDelete,doTrace方法。我们常用的请求有GET和POST,因此,我贴上去的源码只有doGet和doPut方法。基于源码的实现,我

    们通过继承HttpServlet去编写一个Servlet应用程序时,只需要实现重写doGet()和doPost()方法即可。

    四. 关于service重载方法传递的两个参数:HttpServletRequest和HttpServletResponse

      1. HttpServletRequest

        ① 具体信息 :public interface extends  ServletRequest 

        ②HttpServletRequest表示HTTP环境中的Servlet请求。

        ③比ServletRequest接口增加的主要方法有: 

    public java.lang.String getContextPath() //返回请求Servlet应用程序的URI部分。
    public Cookie[] getCookies() //返回一个Cookies数组
    public java.lang.String getHeader(java.lang.String name) //返回指定的HTTP 标头的值
    public java.lang.String getMethod() // 返回发出这条请求的HTTP方法的名称
    public java.lang.String getQueryString()//返回请求Servlet应用的URL中的查询字符串
    public HttpSession getSession(boolean create) //返回与这个请求有关的session对象。如果没找到,且create为true,则创建新的session
    public HttpSession getSession() //返回与这个请求有关的session对象,如果没有则创建新的session并且返回

      2. HttpServletResponse

        ①具体信息:public interface HttpServletResponse extends ServletResponse

        ②HttpServletResponse表示HTTP环境下的Servlet响应。

        ③声明的部分方法: 

    public void addCookie(Cookie cookie)           //给当前的响应对象添加cookie
    
    public void sendRedirect(java.lang.String location) throws java.io.IOException // 将浏览器重定向到指定位置
    public void addHeader(java.lang.String name, java.lang.String value ) // 给当前的响应添加标头

     五. 采用继承HttpServlet编写Servlet小示例。

        1. 通过继承HttpServlet实现编写一个Servlet应用程序。
          
    package com.hjj.servlet.two;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    @WebServlet(name="testHttpServlet",urlPatterns="/testHttpServlet")
    public class TestHttpServlet extends HttpServlet{
        
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                System.out.println("我是 doGet 方法,我被调用了");
                response.setContentType("text/html");
                response.setCharacterEncoding("UTF-8");
                
                PrintWriter pw = response.getWriter();
                pw.println("<html><head></head><title>测试HttpServlet</title><body><center>");
                pw.println("<center><h1>提交数据</h1></center>" );
                pw.println("<form method='post' action='testHttpServlet'>");
                pw.println("<p>姓名<input name='name' type='text '/></p>");
                pw.println("<p><input value='提交' type='submit'/></p>");
                pw.println("</form></center></body></html>");
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                System.out.println("我是 doPost 方法,我被调用了");
                response.setContentType("text/html");
                response.setCharacterEncoding("UTF-8");
                
                String name = request.getParameter("name");
                
                PrintWriter pw = response.getWriter();
                pw.println("<html><head></head><title>测试提交数据</title><body>");
                pw.println("<center><h1>");
                pw.println("get提交的表单的值为:"+name);
                pw.println("</h1></center></body></html>");
        }
    }

        2. 在浏览器中输入url:http://localhost:8080/one/testHttpServlet

          页面显示:

          

          控制台打印:

                我是 doGet 方法,我被调用了

       3. 在上一个页面的表单中输入值

          u

        提交后页面显示:

          

        控制台打印:

              我是 doPost 方法,我被调用了

      

            

    service

  • 相关阅读:
    Java Json 数据下划线与驼峰格式进行相互转换
    Java反射常用示例
    ApplicationContextAware 快速获取bean
    Spring AOP自动代理创建者
    Spring依赖检查
    Bean作用域实例
    注入值到Spring bean属性
    用javaConfig 代替 xml 配置
    spring使用@Autowired装载
    Spring 概述
  • 原文地址:https://www.cnblogs.com/HouJiao/p/5439577.html
Copyright © 2011-2022 走看看