Servlet簡述,API

Servlet是用Java編寫的服務(wù)器端程序,是Sun公司提供的一套接口規(guī)范,用來處理基于HTTP協(xié)議的客戶端請求,響應(yīng)給瀏覽器的動態(tài)資源。

下面通過做個簡單的用戶名提交網(wǎng)頁,了解下Servlet的工作流程。

1.引入Servlet-api.jar
在Tomcat的lib文件夾中引入servlet-api.jar
項目結(jié)構(gòu)
2.實現(xiàn)Servlet
public class DemoServlet extends HttpServlet {

    //Servlet是單列模式,只有一個對象
    //此對象是根據(jù)web.xml的配置信息通過反射生成的
    //因此一定要保證Servlet 的實現(xiàn)類有一個 public 修飾且無參的構(gòu)造函數(shù)
    //因為反射生成類,需要的是無參公開的構(gòu)造函數(shù)
    public DemoServlet() {

    }

    //用來初始化當(dāng)前Servlet,只在服務(wù)器啟動時調(diào)用一次
    @Override
    public void init(ServletConfig config) throws ServletException {

    }

    //每次連接服務(wù)器都會調(diào)用
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        //獲取用戶提交的用戶名
        //參數(shù)name對應(yīng),網(wǎng)頁表單里name的值
        String name = req.getParameter("name");
        System.out.println("用戶提交的用戶名為:" + name);
    }

    //銷毀,只有在停止服務(wù)器時才會調(diào)用,因此一般不將銷毀資源寫在這里
    @Override
    public void destroy() {

    }
}
3.web.xml中配置Servlet映射
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <servlet>
        <!-- 3. 為下面的映射定義一個可找到的名稱 -->
        <servlet-name>DemoServlet</servlet-name>
        <!-- 4. Tomcat通過包找到用戶寫好的Servlet -->
        <servlet-class>com.servlet.DemoServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <!-- 2.根據(jù)用戶自定義的servlet名稱找到servlet -->
        <servlet-name>DemoServlet</servlet-name>
        <!-- 1.表單提交時,action對應(yīng)的servlet -->
        <url-pattern>/demo</url-pattern>
    </servlet-mapping>

</web-app>

2.在index.jsp中編寫界面
<html>
  <head>
    <title>Demo</title>
  </head>
  <body>

    <%-- action="處理此請求的servlet"--%>
    <form action="/demo" method="get">

        <input type="text" placeholder="用戶名" name="name">
        <input type="submit" value="提交">
    </form>
  </body>
</html>
界面效果

Servlet的配置
1.完全匹配
請求必須完全匹配設(shè)定的url-pattern
<servlet-mapping>
        <servlet-name>DemoServlet</servlet-name>
        <url-pattern>/demo</url-pattern>
</servlet-mapping>

2.目錄匹配
請求(/aa/bb/ccc)都會檢索到該目錄指向的Servlet
<url-pattern>/aa/bb/cc/*</url-pattern>

3.擴(kuò)展名匹配
后綴名為.demo的就能訪問
<url-pattern>*.demo</url-pattern>

4.缺省配置
當(dāng)請求的資源地址,所有的Servlet都不匹配時,就由缺省配置的Servlet處理
<url-pattern>/</url-pattern>
其他細(xì)節(jié)
1. 一個Servlet可以有多個<url-pattern>

2.非常消耗資源的初始化操作,要放到服務(wù)器啟動時
<servlet>
        <servlet-name>ServletResponseTest</servlet-name>
        <servlet-class>com.w.servlet.ServletResponseTest</servlet-class>

        <!-- 數(shù)字越小越先執(zhí)行初始化 -->
        <load-on-startup>0</load-on-startup>
</servlet>
Servlet使用注解配置映射信息
Serlvet3.0引入了注解的方式配置映射信息

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1"

    注意:一定要在配置清單中添加
    metadata-complete="false">

</web-app>
@WebServlet(value = "/demo",
        loadOnStartup = 1,
        initParams = { @WebInitParam(name = "", value = "") }
        )
public class DemoServlet extends HttpServlet {
    
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        
        String name = req.getParameter("name");
        System.out.println("用戶提交的用戶名為:" + name);
    }
}

Servlet相關(guān)API

1.ServletConfig(javax.servlet.ServletConfig)

當(dāng)Servlet中存在硬編碼,要將其配置到 web.xml 中,以提高文件可維護(hù)性。

將配置的信息抽取出來放到web.xml文件中

    <servlet>
        <servlet-class>com.w.run.HellowServlet</servlet-class>
        <servlet-name>HelloServlet</servlet-name>

        <!-- 初始化參數(shù)配置 -->
        <init-param>
            <!-- 參數(shù)名稱 -->
            <param-name>encoding</param-name>
            <!-- 參數(shù)值 -->
            <param-value>UTF-8</param-value>
        </init-param>
    </servlet>
public class DemoServlet extends HttpServlet {

    @Override
    public void init(ServletConfig config) throws ServletException {
        ServletConfig servletConfig = getServletConfig();//獲取配置信息類
        String encoding = config.getInitParameter("encoding");
        System.out.println(encoding);
    }
}
Config 其他API
public class DemoServlet extends HttpServlet {

    @Override
    public void init(ServletConfig config) throws ServletException {

        //獲取全部初始化參數(shù)
        Enumeration<String> initParameterNames = config.getInitParameterNames();
        while (initParameterNames.hasMoreElements()) {
            System.out.println(initParameterNames.nextElement());
        }

        //獲取當(dāng)前servlet的名稱
        String servletName = config.getServletName();
        System.out.println(servletName);

        //獲取當(dāng)前servlet的上下文
        ServletContext servletContext = config.getServletContext();
    }
}
2.ServletContext

ServletContext對象,代表一個Web應(yīng)用,封裝了該Web應(yīng)用的信息,該對象在服務(wù)器啟動時,創(chuàng)建,該Web應(yīng)用銷毀時,銷毀。

  @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        ServletContext context = getServletContext();
        context.setAttribute("key", "Value");
        context.getAttribute("key");
        context.removeAttribute("key");
    }
ServletContext重要API
配置全局參數(shù)所有Servlet中都能獲取

<?xml version="1.0" encoding="UTF-8"?>
<web-app>

    <!-- 全局初始化參數(shù),在所有Servlet中都能獲取 -->
    <context-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </context-param>

</web-app>
@Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        ServletContext context = getServletContext();
        
        //獲取Web.xml中配置的全局參數(shù)
        context.getInitParameter("encoding");

        //獲取Web應(yīng)用中任何資源的絕對路徑
        context.getRealPath("path");
    }

Servlet的Request,Response

public class DemoServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

    }
}
1.ServletRequest(子接口實現(xiàn):HttpServletRequest)

用來處理基于HTTP協(xié)議的請求,其對象在每次請求時創(chuàng)建,響應(yīng)結(jié)束后銷毀。

Request常用的API

@Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        /**
         * 以下是獲取用戶提交的請求里參數(shù)的方法
         */
        req.getParameter("name"); //獲取指定名稱的參數(shù)的值
        req.getParameterMap();  //獲取所有請求參數(shù)并封裝到一個Map
        req.getParameterNames();  //獲取所有請求參數(shù)的名稱
        req.getParameterValues("");  //獲取多個表單的值,CheckBox的

        //Request的域?qū)ο螅瑐鬟f數(shù)據(jù)
        req.setAttribute("key","value");
        req.getAttribute("key");
        req.removeAttribute("key");

        req.getContextPath(); //獲取上下文路徑
        req.getHeader("User-Agent"); //獲取指定名稱的請求頭信息

        req.getMethod();  //獲取請求方式
        req.getRequestURI();  //獲取資源的名稱
        req.getRequestURL();  //獲取請求資源的全路徑
    }
BeanUtils框架的使用

表單提交的多個參數(shù),往往需要封裝成JavaBean,用傳統(tǒng)寫法太過繁瑣,這就需要借助框架幫助。

    try {
            /**
             * BeanUtils工作原理:將Map中的數(shù)據(jù),根據(jù)Key與實體的屬性的對應(yīng)關(guān)系封裝
             * 只要Key的名字與實體的屬性名字一樣就自動封裝到實體中
             */

            User user = new User();
            BeanUtils.populate(user, req.getParameterMap());

        } catch (Exception e) {
            e.printStackTrace();
        }
2.ServletResponse(子接口實現(xiàn):HttpServletResponse)

用來處理基于HTTP協(xié)議的請求后的響應(yīng)信息。

Response常用API

@Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        //Response獲得流不需要手動關(guān)閉,Tomcat會幫助我們關(guān)閉
        //getWrite()和getOutputStream(); 不允許同時調(diào)用,這里只做演示
        PrintWriter writer = resp.getWriter();
        ServletOutputStream outs = resp.getOutputStream();

        resp.setStatus(201); //設(shè)置狀態(tài)碼
        resp.setHeader("key", "value"); //設(shè)置響應(yīng)頭
        resp.addHeader("key", "value"); //添加響應(yīng)頭
    }
Servlet請求響應(yīng)時,中文亂碼問題
Tomcat默認(rèn)使用的ISO-8859-1的方式處理請求參數(shù),不適合中文的編碼。
MIME類型(文件格式)"text/html"的響應(yīng)問題。

1.解決辦法
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");

2..用解碼編碼的方式
byte[] bytes = name.getBytes("ISO-8859-1");  //解碼
name = new String(bytes, "UTF-8");  //編碼

3.. 修改Tomcat配置,但只支持get請求。
 <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               URIEncoding="utf-8"/>

4.在獲取請求參數(shù)之前設(shè)置請求編碼,只支持post請求。
req.setCharacterEncoding("UTF-8");
Response響應(yīng)流程
1.客戶端發(fā)送請求到服務(wù)端Tomcat
2.服務(wù)端Tomcat引擎發(fā)送Request請求

3.服務(wù)端響應(yīng)的數(shù)據(jù)會存到Response緩沖區(qū)
4.Tomcat引擎取出Response緩沖區(qū)的內(nèi)容,與引擎自己添加的信息組裝成一個Http響應(yīng)給客戶端。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容