Servlet 使用介绍(1)

来源:互联网 发布:网络有个感叹号怎么办 编辑:程序博客网 时间:2024/06/06 02:30

说明

本篇介绍java web中比较重要的一个技术:servlet。servlet是一种对用户请求动态响应的一个技术,是java web的核心一环。对于一般服务性质的纯后台服务应用而言,或许整个应用是由若干个servlet组成
,而其他方面表现较弱。

servlet

一般的我们的应用都会发布到一个服务应用中,即一个servlet容器中,常见的servlet容器有:Tomcat,JBoss,WebLogic等。我们通过servlet容器处理用户请求,当用户向我们的某个servlet发起请求时,servlet容器会调用并转发请求结果到该servlet,同时会将servlet返回结果回馈给请求方(用户)。其实,servlet本质就是一个接口,我们可以通过注册servlet服务,实现servlet接口,用于监听各种状态先的信息交互。如下,仅仅介绍tomcat中的servlet的相关使用(主要是其他也没用过)。

Tomcat中为servlet的使用提供了一个调用的jar包:sevlet-api.jar ,该jar包位于Tomcat根目录的lib目录下(所有和Tomcat相关的Jar包均放在这里),如下为servlet-api.jar中的包信息:

servlet-api.jar--javax.servlet           //核心--javax.servlet.annotation--javax.servlet.descriptor--javax.servlet.http     //基于http的实现

可以看到,这里主要石油javax.servlet和javax.servlet.http两个包组成实现。其中javax.servlet.Servlet接口为api的核心,servlet容器通过调用其定义方法,实现网络中客户端和服务端之前通信的中转传递,Servlet提供了五个方法,其中三个方法是由servlet容器调用。如下,servlet的源码:

package javax.servlet;import java.io.IOException;public interface Servlet {    /**     *由sevler容器调用,servlet对象初始化后,servlet容器调用此方法     *     */    public void init(ServletConfig config) throws ServletException;    /**     *提供的一个获取ServletConfig对象的方法,该方法由我们自己实现,返回的对象即是init     *的方法传入的参数。     *     */    public ServletConfig getServletConfig();    /**     *该方法需要在init方法成功调用后才可正常调用(即客户端请求的时候必须姚该servlet以及     *初始化成功)     *     */    public void service(ServletRequest req, ServletResponse res)    throws ServletException, IOException;    /**     *返回当前servlet的创建信息包括创建者等(为一个String字串)     *     */    public String getServletInfo();    /**     *由servlet容器调用,当一个servlet容器被销毁时调用,可以用于清理销毁servlet中的占     *用的一些资源。     *     */    public void destroy();}

Servlet接口为最基础的Servlet组件,可供我们最大限度的对servlet进行定制.servlet-api.jar中也为我们提供了它的两个替代实现:一个是javax.servlet.GenericServlet是其实现类,完成它的最基础的一些逻辑实现,但保留其对于网络通信的处理,交由我们自行处理;另一个是javax.servlet.http.HttpServlet,该类是GenericServlet的子类,是对GenericServlet的一种扩展,其对于Servlet的servive方法进行了处理,主要用于Http请求。如下,给出这两个类的实现源码:

  1. GenericServlet

该抽象类并未对servive方法作处理。

public abstract class GenericServlet implements Servlet, ServletConfig,                        java.io.Serializable{    private static final String LSTRING_FILE = "javax.servlet.LocalStrings";    private static ResourceBundle lStrings =        ResourceBundle.getBundle(LSTRING_FILE);    private transient ServletConfig config;    public GenericServlet() { }    /**     *销毁方法     */    public void destroy() {    }    /**     *获取servlet初始化传入参数     *     */    public String getInitParameter(String name) {        ServletConfig sc = getServletConfig();        if (sc == null) {            throw new IllegalStateException(                lStrings.getString("err.servlet_config_not_initialized"));        }        return sc.getInitParameter(name);    }   /**    *servlet参数参数名获取    */    public Enumeration<String> getInitParameterNames() {        ServletConfig sc = getServletConfig();        if (sc == null) {            throw new IllegalStateException(                lStrings.getString("err.servlet_config_not_initialized"));        }        return sc.getInitParameterNames();    }       /**     *实现Servlet方法返回初始化获取的ServletConfig对象     */        public ServletConfig getServletConfig() {               return config;    }    /**     *获取ServletContext对象(Servlet上下文),是在ServletConfig中获取     */    public ServletContext getServletContext() {        ServletConfig sc = getServletConfig();        if (sc == null) {            throw new IllegalStateException(                lStrings.getString("err.servlet_config_not_initialized"));        }        return sc.getServletContext();    }    public String getServletInfo() {            return "";    }    /**     *实现Servlet初始化方法,并回调init()无参方法,可供实现者监听状态.     *     *     */    public void init(ServletConfig config) throws ServletException {          this.config = config;           this.init();    }    /**     * 子类可通过重写监听Servlet对象初始化状态.     */    public void init() throws ServletException {    }    public void log(String msg) {           getServletContext().log(getServletName() + ": "+ msg);    }    public void log(String message, Throwable t) {         getServletContext().log(getServletName() + ": " + message, t);    }    public abstract void service(ServletRequest req, ServletResponse res)    throws ServletException, IOException;    public String getServletName() {        ServletConfig sc = getServletConfig();        if (sc == null) {            throw new IllegalStateException(                lStrings.getString("err.servlet_config_not_initialized"));        }        return sc.getServletName();    }}
  1. HttpServlet

是GenericServlet的子类,对service添加了Http的处理,一般适用于Http通信的Servlet,是较为常用的一种Servlet.

package javax.servlet.http;import java.io.IOException;import java.io.PrintWriter;import java.io.OutputStreamWriter;import java.io.UnsupportedEncodingException;import java.lang.reflect.Method;import java.text.MessageFormat;import java.util.Enumeration;import java.util.Locale;import java.util.ResourceBundle;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 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() { }    /**     *Http协议Get方式请求回调     *     */    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;    }    /**     *Http协议HHEAD(只请求页面的头部)方式请求回调     */    protected void doHead(HttpServletRequest req, HttpServletResponse resp)        throws ServletException, IOException    {        NoBodyResponse response = new NoBodyResponse(resp);        doGet(req, response);        response.setContentLength();    }    /**     *Http协议POST方式请求回调     */    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);        }    }    /**     *Http协议Put方式请求回调     */    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);        }    }    /**     *Http协议Delete方式请求回调     */    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);        }    }    private Method[] getAllDeclaredMethods(Class<?> c) {        if (c.equals(javax.servlet.http.HttpServlet.class)) {            return null;        }        Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());        Method[] thisMethods = c.getDeclaredMethods();        if ((parentMethods != null) && (parentMethods.length > 0)) {            Method[] allMethods =                new Method[parentMethods.length + thisMethods.length];            System.arraycopy(parentMethods, 0, allMethods, 0,                             parentMethods.length);            System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,                             thisMethods.length);            thisMethods = allMethods;        }        return thisMethods;    }    protected void doOptions(HttpServletRequest req, HttpServletResponse resp)        throws ServletException, IOException    {        Method[] methods = getAllDeclaredMethods(this.getClass());        boolean ALLOW_GET = false;        boolean ALLOW_HEAD = false;        boolean ALLOW_POST = false;        boolean ALLOW_PUT = false;        boolean ALLOW_DELETE = false;        boolean ALLOW_TRACE = true;        boolean ALLOW_OPTIONS = true;        for (int i=0; i<methods.length; i++) {            Method m = methods[i];            if (m.getName().equals("doGet")) {                ALLOW_GET = true;                ALLOW_HEAD = true;            }            if (m.getName().equals("doPost"))                ALLOW_POST = true;            if (m.getName().equals("doPut"))                ALLOW_PUT = true;            if (m.getName().equals("doDelete"))                ALLOW_DELETE = true;        }        String allow = null;        if (ALLOW_GET)            allow=METHOD_GET;        if (ALLOW_HEAD)            if (allow==null) allow=METHOD_HEAD;            else allow += ", " + METHOD_HEAD;        if (ALLOW_POST)            if (allow==null) allow=METHOD_POST;            else allow += ", " + METHOD_POST;        if (ALLOW_PUT)            if (allow==null) allow=METHOD_PUT;            else allow += ", " + METHOD_PUT;        if (ALLOW_DELETE)            if (allow==null) allow=METHOD_DELETE;            else allow += ", " + METHOD_DELETE;        if (ALLOW_TRACE)            if (allow==null) allow=METHOD_TRACE;            else allow += ", " + METHOD_TRACE;        if (ALLOW_OPTIONS)            if (allow==null) allow=METHOD_OPTIONS;            else allow += ", " + METHOD_OPTIONS;        resp.setHeader("Allow", allow);    }    /**     *处理TRACE请求     */    protected void doTrace(HttpServletRequest req, HttpServletResponse resp)        throws ServletException, IOException    {        int responseLength;        String CRLF = "\r\n";        StringBuilder buffer = new StringBuilder("TRACE ").append(req.getRequestURI())            .append(" ").append(req.getProtocol());        Enumeration<String> reqHeaderEnum = req.getHeaderNames();        while( reqHeaderEnum.hasMoreElements() ) {            String headerName = reqHeaderEnum.nextElement();            buffer.append(CRLF).append(headerName).append(": ")                .append(req.getHeader(headerName));        }        buffer.append(CRLF);        responseLength = buffer.length();        resp.setContentType("message/http");        resp.setContentLength(responseLength);        ServletOutputStream out = resp.getOutputStream();        out.print(buffer.toString());    }    /**     *http协议处理     */    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 = req.getDateHeader(HEADER_IFMODSINCE);                if (ifModifiedSince < lastModified) {                    // 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);        }    }    private void maybeSetLastModified(HttpServletResponse resp,                                      long lastModified) {        if (resp.containsHeader(HEADER_LASTMOD))            return;        if (lastModified >= 0)            resp.setDateHeader(HEADER_LASTMOD, lastModified);    }    /**     *重写父类方法,转化为http协议处理,调用自有http处理     */    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");        }        request = (HttpServletRequest) req;        response = (HttpServletResponse) res;        service(request, response);    }}// file privateclass NoBodyResponse extends HttpServletResponseWrapper {    private static final ResourceBundle lStrings        = ResourceBundle.getBundle("javax.servlet.http.LocalStrings");    private NoBodyOutputStream noBody;    private PrintWriter writer;    private boolean didSetContentLength;    private boolean usingOutputStream;    // file private    NoBodyResponse(HttpServletResponse r) {        super(r);        noBody = new NoBodyOutputStream();    }    // file private    void setContentLength() {        if (!didSetContentLength) {            if (writer != null) {                writer.flush();            }            setContentLength(noBody.getContentLength());        }    }    public void setContentLength(int len) {        super.setContentLength(len);        didSetContentLength = true;    }    public ServletOutputStream getOutputStream() throws IOException {        if (writer != null) {            throw new IllegalStateException(                lStrings.getString("err.ise.getOutputStream"));        }        usingOutputStream = true;        return noBody;    }    public PrintWriter getWriter() throws UnsupportedEncodingException {        if (usingOutputStream) {            throw new IllegalStateException(                lStrings.getString("err.ise.getWriter"));        }        if (writer == null) {            OutputStreamWriter w = new OutputStreamWriter(                noBody, getCharacterEncoding());            writer = new PrintWriter(w);        }        return writer;    }}/* * Servlet output stream that gobbles up all its data. */// file privateclass NoBodyOutputStream extends ServletOutputStream {    private static final String LSTRING_FILE =        "javax.servlet.http.LocalStrings";    private static ResourceBundle lStrings =        ResourceBundle.getBundle(LSTRING_FILE);    private int contentLength = 0;    // file private    NoBodyOutputStream() {}    // file private    int getContentLength() {        return contentLength;    }    public void write(int b) {        contentLength++;    }    public void write(byte buf[], int offset, int len)        throws IOException    {        if (len >= 0) {            contentLength += len;        } else {            // This should have thrown an IllegalArgumentException, but            // changing this would break backwards compatibility            throw new IOException(lStrings.getString("err.io.negativelength"));        }    }}

如上,Servlet对于用户的请求获取和返回主要是通过方法:

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

实现的。这里,servlet容器在调用时传入两个参数:一个ServletRequest对象,用于接收用户请求信息;一个ServletResponse对象,用于返回请求用户信息。而HttpServlet对于对象则更改为HttpServletRequest和HttpServletResponse对象。其实这两个接口是同样在对应的ServletRequest和ServletResponse接口的基础上扩展的。

Enjoytoday,EnjoyCoding

原创粉丝点击