Servlet

Servlet 的 HelloWorld

1.创建一个 Servlet 接口的实现类.

public class HelloServlet implements Servlet{
}

2.在 web.xml 文件中配置和映射这个 Servlet

<!-- 配置和映射 Servlet -->
    <servlet>
        <!-- Servlet 注册的名字 -->
        <servlet-name>helloServlet</servlet-name>
        <!-- Servlet 的全类名 -->
        <servlet-class>org.xst.servlet.HelloServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <!-- 需要和某一个 servlet 节点的 serlvet-name 子节点的文本节点一致 -->
        <servlet-name>helloServlet</servlet-name>
        <!-- 映射具体的访问路径: / 代表当前 WEB 应用的根目录. -->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

Servlet 容器

运行 Servlet、JSP、Filter 等的软件环境

Tomcat如何与Servlet协同工作

Servlet规范中的关键要求之一是,它们只能处理整个数据事务处理的某些部分。例如,servlet代码本身不会监听某个端口上的请求,也不会直接与客户端进行通信,也不负责管理其对资源的访问。相反,这些东西是由servlet容器Tomcat管理的。

如何工作

一个http请求到来,servlet容器(tomcat)将请求封装成servlet中的request对象,在requset中我们可以得到所有的http信息,然后可以对数据进行对应操作,最后再把数据封装成servlet的response对象,容器将response对象解析之后封装成一个http response.

什么是servlet

  • servlet 是一个java接口.
  • Servlet是J2EE 规范中的一种
  • servlet就是一群人来指定java应用中使用web的各种规范.统一接口.
public interface Servlet {
    /**
     * Called by the servlet container to indicate to a servlet that the 
     * servlet is being placed into service.
     */
    public void init(ServletConfig config) throws ServletException;   

    /**
     * Returns a {@link ServletConfig} object, which contains
     * initialization and startup parameters for this servlet.
     * The <code>ServletConfig</code> object returned is the one 
     * passed to the <code>init</code> method. 
     */
    public ServletConfig getServletConfig(); 

    /**
     * Called by the servlet container to allow the servlet to respond to 
     * a request.
     *
     * <p>This method is only called after the servlet's <code>init()</code>
     * method has completed successfully.
     */
    public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;

    /**
     * Returns information about the servlet, such as author, version, and copyright.
     * 
     * <p>The string that this method returns should
     * be plain text and not markup of any kind (such as HTML, XML,etc.).
     */

    public String getServletInfo();

    /**
     * Called by the servlet container to indicate to a servlet that the
     * servlet is being taken out of service.  This method is
     * only called once all threads within the servlet's
     * <code>service</code> method have exited or after a timeout
     * period has passed. After the servlet container calls this 
     * method, it will not call the <code>service</code> method again
     * on this servlet.
     *
     * <p>This method gives the servlet an opportunity 
     * to clean up any resources that are being held (for example, memory,
     * file handles, threads) and make sure that any persistent state is
     * synchronized with the servlet's current state in memory.
     */

    public void destroy();
}

Servlet 生命周期的方法(以下方法都是由 Serlvet 容器负责调用.)

1. 构造器:

只被调用一次. 只有第一次请求 Servlet 时, 创建 Servlet 的实例. 调用构造器. 这说明 Serlvet 的单实例的!

2. init 方法:

只被调用一次. 在创建好实例后立即被调用. 用于初始化当前 Servlet.

3. service 方法:

被多次调用. 每次请求都会调用 service 方法. 实际用于响应请求的.

4. destroy 方法:

只被调用一次. 在当前 Servlet 所在的 WEB 应用被卸载前调用. 用于释放当前 Servlet 所占用的资源.

load-on-startup 参数:

1. 配置在 servlet 节点中:

    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>org.xst.servlet.HelloServlet</servlet-class>
        <!-- 可以指定 Servlet 被创建的时机 -->
        <load-on-startup>1</load-on-startup>
    </servlet>

2. load-on-startup: 可以指定 Serlvet 被创建的时机.

若为负数, 则在第一次请求时被创建.若为 0 或正数, 则在当前 WEB 应用被Serlvet 容器加载时创建实例, 且数组越小越早被创建.

关于 serlvet-mapping

  1. 同一个Servlet可以被映射到多个URL上,即多个 元素的子元素的设置值可以是同一个Servlet的注册名。
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>org.xst.servlet.HelloServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
  1. 在Servlet映射到的URL中也可以使用 * 通配符,但是只能有两种固定的格式:
    一种格式是“.扩展名”,另一种格式是以正斜杠(/)开头并以“/”结尾。
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>org.xst.servlet.HelloServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

ServletConfig

/**
 * A servlet configuration object used by a servlet container
 * to pass information to a servlet during initialization. 
 */
public interface ServletConfig {
    /**
     * Returns the name of this servlet instance.
     * The name may be provided via server administration, assigned in the 
     * web application deployment descriptor, or for an unregistered (and thus
     * unnamed) servlet instance it will be the servlet's class name.
     */
    public String getServletName();

    /**
     * Returns a reference to the {@link ServletContext} in which the caller
     * is executing.
     */
    public ServletContext getServletContext();

    /**
     * Returns a <code>String</code> containing the value of the 
     * named initialization parameter, or <code>null</code> if 
     * the parameter does not exist.
     */
    public String getInitParameter(String name);

    /**
     * Returns the names of the servlet's initialization parameters
     * as an <code>Enumeration</code> of <code>String</code> objects, 
     * or an empty <code>Enumeration</code> if the servlet has
     * no initialization parameters.
     */
    public Enumeration getInitParameterNames();
}

封装了 Serlvet 的配置信息, 并且可以获取 ServletContext 对象

1. 配置 Serlvet 的初始化参数

         <!--配置当前 WEB 应用的初始化参数-->
    <context-param>
        <param-name>cuser</param-name>
        <param-value>croot</param-value>
    </context-param>

    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>org.xst.servlet.HelloServlet</servlet-class>
        <!-- 配置 Serlvet 的初始化参数。 且节点必须在 load-on-startup 节点的前面 -->
        <init-param>
            <!-- 参数名 -->
            <param-name>user</param-name>
            <!-- 参数值 -->
            <param-value>root</param-value>
        </init-param>
        <load-on-startup>0</load-on-startup>
    </servlet>

2. 获取Servlet初始化参数

public class HelloServlet extends GenericServlet {


    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        String user = getInitParameter("user"); //获取 servlet 的初始化参数
        System.out.println(user); //root

        String cuser = getServletContext().getInitParameter("cuser"); //获取 web 应用的初始化参数
        System.out.println(cuser); //croot
    }
}

ServletContext

/**
 * <p>The <code>ServletContext</code> object is contained within 
 * the {@link ServletConfig} object, which the Web server provides the
 * servlet when the servlet is initialized.
 */
public interface ServletContext {
    /**
     * Returns the context path of the web application.
     */
    public String getContextPath();

    /**
     * Returns a <code>ServletContext</code> object that 
     * corresponds to a specified URL on the server.
     */

    public ServletContext getContext(String uripath);

    /**
     * Returns the MIME type of the specified file, or <code>null</code> if 
     * the MIME type is not known. The MIME type is determined
     * by the configuration of the servlet container, and may be specified
     * in a web application deployment descriptor. Common MIME
     * types are <code>"text/html"</code> and <code>"image/gif"</code>.
     */
    public String getMimeType(String file);

    /**
     * Returns a URL to the resource that is mapped to a specified
     * path. The path must begin with a "/" and is interpreted
     * as relative to the current context root.
     */
    public URL getResource(String path) throws MalformedURLException;   

    /**
     * Returns the resource located at the named path as
     * an <code>InputStream</code> object.
     *
     * <p>The data in the <code>InputStream</code> can be 
     * of any type or length. The path must be specified according
     * to the rules given in <code>getResource</code>.
     * This method returns <code>null</code> if no resource exists at
     * the specified path. 
     */
    public InputStream getResourceAsStream(String path);  

    /**
     * Returns a <code>String</code> containing the real path 
     * for a given virtual path. For example, the path "/index.html"
     * returns the absolute file path on the server's filesystem would be
     * served by a request for "http://host/contextPath/index.html",
     * where contextPath is the context path of this ServletContext..
     *
     * <p>The real path returned will be in a form
     * appropriate to the computer and operating system on
     * which the servlet container is running, including the
     * proper path separators. This method returns <code>null</code>
     * if the servlet container cannot translate the virtual path
     * to a real path for any reason (such as when the content is
     * being made available from a <code>.war</code> archive).
     */
    public String getRealPath(String path);

    /**
     * Returns the name and version of the servlet container on which
     * the servlet is running. 
     */
    public String getServerInfo();

    /**
     * Returns a <code>String</code> containing the value of the named
     * context-wide initialization parameter, or <code>null</code> if the 
     * parameter does not exist.
     *
     * <p>This method can make available configuration information useful
     * to an entire "web application".  For example, it can provide a 
     * webmaster's email address or the name of a system that holds 
     * critical data.
     */
    public String getInitParameter(String name);

    /**
     * Returns the names of the context's initialization parameters as an
     * <code>Enumeration</code> of <code>String</code> objects, or an
     * empty <code>Enumeration</code> if the context has no initialization
     * parameters.
     */
    public Enumeration getInitParameterNames();

    /**
     * Returns the servlet container attribute with the given name, 
     * or <code>null</code> if there is no attribute by that name.
     * An attribute allows a servlet container to give the
     * servlet additional information not
     * already provided by this interface. See your
     * server documentation for information about its attributes.
     * A list of supported attributes can be retrieved using
     * <code>getAttributeNames</code>.
     *
     * <p>The attribute is returned as a <code>java.lang.Object</code>
     * or some subclass.
     * Attribute names should follow the same convention as package
     * names. The Java Servlet API specification reserves names
     * matching <code>java.*</code>, <code>javax.*</code>,
     * and <code>sun.*</code>.
     */
    public Object getAttribute(String name); 

    /**
     * Returns an <code>Enumeration</code> containing the 
     * attribute names available
     * within this servlet context. Use the
     * {@link #getAttribute} method with an attribute name
     * to get the value of an attribute.
     */
    public Enumeration getAttributeNames(); 

    /**
     * Binds an object to a given attribute name in this servlet context. If
     * the name specified is already used for an attribute, this
     * method will replace the attribute with the new to the new attribute.
     * <p>If listeners are configured on the <code>ServletContext</code> the  
     * container notifies them accordingly.
     * <p>
     * If a null value is passed, the effect is the same as calling 
     * <code>removeAttribute()</code>.
     * 
     * <p>Attribute names should follow the same convention as package
     * names. The Java Servlet API specification reserves names
     * matching <code>java.*</code>, <code>javax.*</code>, and
     * <code>sun.*</code>.
     */ 
    public void setAttribute(String name, Object object);

    /**
     * Removes the attribute with the given name from 
     * the servlet context. After removal, subsequent calls to
     * {@link #getAttribute} to retrieve the attribute's value
     * will return <code>null</code>.
     * <p>If listeners are configured on the <code>ServletContext</code> the 
     * container notifies them accordingly.
     */
    public void removeAttribute(String name);

    /**
     * Returns the name of this web application corresponding to this ServletContext as specified in the deployment
     * descriptor for this web application by the display-name element.
     * @return      The name of the web application or null if no name has been declared in the deployment descriptor.
     */
    public String getServletContextName();
}

1.可以由 SerlvetConfig 获取

ServletContext servletContext = servletConfig.getServletContext()

2. 该对象代表当前 WEB 应用: 可以认为 SerlvetContext 是当前 WEB 应用的一个大管家. 可以从中获取到当前 WEB 应用的各个方面的信息.

GenericServlet

/**
 * <p>To write a generic servlet, you need only
 * override the abstract <code>service</code> method. 
 */
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;

    /**
     *
     * Does nothing. All of the servlet initialization
     * is done by one of the <code>init</code> methods.
     *
     */
    public GenericServlet() { }

   /**
     * Called by the servlet container to indicate to a servlet that the
     * servlet is being taken out of service.  See {@link Servlet#destroy}.
     */

    public void destroy() {
    }   

    /**
     * Returns a <code>String</code> containing the value of the named
     * initialization parameter, or <code>null</code> if the parameter does
     * not exist.  See {@link ServletConfig#getInitParameter}.
     */ 
    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);
    } 

   /**
    * Returns the names of the servlet's initialization parameters 
    * as an <code>Enumeration</code> of <code>String</code> objects,
    * or an empty <code>Enumeration</code> if the servlet has no
    * initialization parameters.  See {@link
    * ServletConfig#getInitParameterNames}.
    */
    public Enumeration getInitParameterNames() {
        ServletConfig sc = getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(
                lStrings.getString("err.servlet_config_not_initialized"));
        }

        return sc.getInitParameterNames();
    }

    /**
     * Returns this servlet's {@link ServletConfig} object.
     */

    public ServletConfig getServletConfig() {
        return config;
    }

    /**
     * Returns a reference to the {@link ServletContext} in which this servlet
     * is running.  See {@link ServletConfig#getServletContext}.
     *
     * <p>This method is supplied for convenience. It gets the 
     * context from the servlet's <code>ServletConfig</code> object.
     */
    public ServletContext getServletContext() {
        ServletConfig sc = getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(
                lStrings.getString("err.servlet_config_not_initialized"));
        }

        return sc.getServletContext();
    }

    /**
     * Returns information about the servlet, such as author, version, and copyright. 
     * By default, this method returns an empty string.  Override this method
     * to have it return a meaningful value.  See {@link Servlet#getServletInfo}.
     */
    public String getServletInfo() {
        return "";
    }

    /**
     * Called by the servlet container to indicate to a servlet that the
     * servlet is being placed into service.  See {@link Servlet#init}.
     *
     * <p>This implementation stores the {@link ServletConfig}
     * object it receives from the servlet container for later use.
     * When overriding this form of the method, call 
     * <code>super.init(config)</code>.
     */
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }

    /**
     * A convenience method which can be overridden so that there's no need
     * to call <code>super.init(config)</code>.
     *
     * <p>Instead of overriding {@link #init(ServletConfig)}, simply override
     * this method and it will be called by
     * <code>GenericServlet.init(ServletConfig config)</code>.
     * The <code>ServletConfig</code> object can still be retrieved via {@link
     * #getServletConfig}. 
     */ 
    public void init() throws ServletException {

    }

    /**
     * Writes the specified message to a servlet log file, prepended by the
     * servlet's name.  See {@link ServletContext#log(String)}.
     */ 
    public void log(String msg) {
    getServletContext().log(getServletName() + ": "+ msg);
    }

    /**
     * Writes an explanatory message and a stack trace
     * for a given <code>Throwable</code> exception
     * to the servlet log file, prepended by the servlet's name.
     * See {@link ServletContext#log(String, Throwable)}.
     */
    public void log(String message, Throwable t) {
    getServletContext().log(getServletName() + ": " + message, t);
    } 

    /**
     * Called by the servlet container to allow the servlet to respond to
     * a request.  See {@link Servlet#service}.
     * 
     * <p>This method is declared abstract so subclasses, such as 
     * <code>HttpServlet</code>, must override it.
     */

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

    /**
     * Returns the name of this servlet instance.
     * See {@link ServletConfig#getServletName}.
     */
    public String getServletName() {
        ServletConfig sc = getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(
                lStrings.getString("err.servlet_config_not_initialized"));
        }

        return sc.getServletName();
    }
}
  1. 是一个 Serlvet. 是 Servlet 接口和 ServletConfig 接口的实现类. 但是一个抽象类. 其中的 service 方法为抽象方法
  2. 如果新建的 Servlet 程序直接继承 GenericSerlvet 会使开发更简洁.
  3. 具体实现:
    ①. 在 GenericServlet 中声明了一个 SerlvetConfig 类型的成员变量, 在 init(ServletConfig) 方法中对其进行了初始化
    ②. 利用 servletConfig 成员变量的方法实现了 ServletConfig 接口的方法
    ③. 还定义了一个 init() 方法, 在 init(SerlvetConfig) 方法中对其进行调用, 子类可以直接覆盖 init() 在其中实现对 Servlet 的初始化.
    ④. 不建议直接覆盖 init(ServletConfig), 因为如果忘记编写 super.init(config); 而还是用了 SerlvetConfig 接口的方法,则会出现空指针异常.
    ⑤. 新建的 init(){} 并非 Serlvet 的生命周期方法. 而 init(ServletConfig) 是生命周期相关的方法.

HttpServlet

  1. HttpServlet是一个 Servlet, 继承自 GenericServlet. 针对于 HTTP 协议所定制.
  2. 在 service() 方法中直接把 ServletReuqest 和 ServletResponse 转为HttpServletRequest 和 HttpServletResponse.并调用了重载的 service(HttpServletRequest, HttpServletResponse)
  3. 在 service(HttpServletRequest, HttpServletResponse) 获取了请求方式: request.getMethod(). 根据请求方式有创建了doXxx() 方法(xxx 为具体的请求方式, 比如 doGet, doPost)
@Override
 public void service(ServletRequest req, ServletResponse res)
    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");
    }
    service(request, response);
}

public void service(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    //1. 获取请求方式.
    String method = request.getMethod();

    //2. 根据请求方式再调用对应的处理方法
    if("GET".equalsIgnoreCase(method)){
        doGet(request, response);
    }else if("POST".equalsIgnoreCase(method)){
        doPost(request, response);
    }
}

public void doPost(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException{
    // TODO Auto-generated method stub

}

public void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
    // TODO Auto-generated method stub

}

HttpServletRequest是 SerlvetRequest 的子接口. 针对于 HTTP 请求所定义. 里边包含了大量获取 HTTP 请求相关的方法.

ServletResponse: 封装了响应信息, 如果想给用户什么响应, 具体可以使用该接口的方法实现.

*getWriter(): 返回 PrintWriter 对象. 调用该对象的 print() 方法, 将把 print() 中的参数直接打印到客户的浏览器上.

设置响应的内容类型: response.setContentType(“application/msword”);

void sendRedirect(String location): 请求的重定向. (此方法为 HttpServletResponse 中定义.)

login应用

在 web.xml 文件中设置一个 WEB 应用的初始化参数user,和一个loginServlet的初始化参数 password.
定义一个 login.html, 里边定义两个请求字段: user, password. 发送请求到 loginServlet
在创建一个 LoginServlet, 在其中获取请求的 user, password. 比对其和 web.xml 文件中定义的请求参数是否一致
若一致, 响应 Hello:xxx, 若不一致, 响应 Sorry: xxx xxx 为 user.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         id="WebApp_ID" version="2.5">
    <!-- 配置web 应用 的初始化参数-->
    <context-param>
        <param-name>cuser</param-name>
        <param-value>root</param-value>
    </context-param>

    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>org.xst.servlet.LoginServlet</servlet-class>
        <!-- 配置 Serlvet 的初始化参数。 且节点必须在 load-on-startup 节点的前面 -->
        <init-param>
            <param-name>ipassword</param-name>
            <param-value>root</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
</web-app>
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取xml 中loginServlet 的数据
        String cuser = getServletContext().getInitParameter("cuser"); //获取web应用的初始化参数
        String ipassword = getInitParameter("ipassword"); //获取servlet的初始化参数
        // 获取页面的数据
        String user = request.getParameter("user");
        String password = request.getParameter("password");
        if(cuser.equals(user) && ipassword.equals(password)){
            System.out.println("hello:" + user);
        }else{
            System.out.println("sorry");
        }
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>

<form action="/login" method="post">
    user:<input type="text" name="user" value=""><br><br>
    password:<input type="password" name="password" value=""><br><br>
    <input type="submit" value="登陆">
</form>
</body>
</html>
http://localhost:8080/login.html

请求的转发和重定向区别

本质区别

请求的转发只发出了一次请求, 而重定向则发出了两次请求.

具体:

1. 地址栏

请求的转发: 地址栏是初次发出请求的地址.
请求的重定向: 地址栏不再是初次发出的请求地址. 地址栏为最后响应的那个地址

2. request对象

请求转发: 在最终的 Servlet 中, request 对象和中转的那个 request 是同一个对象.
请求的重定向: 在最终的 Servlet 中, request 对象和中转的那个 request 不是同一个对象.

3. 资源访问

请求的转发: 只能转发给当前 WEB 应用的的资源
请求的重定向: 可以重定向到任何资源.

4. /的意义

请求的转发: / 代表的是当前 WEB 应用的根目录
请求的重定向: / 代表的是当前 WEB 站点的根目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值