理解Servlet

2018-08-12 21:57 更新

理解Servlet

本文依然使用00-03、從JSP開始中創(chuàng)建的項(xiàng)目HelloJSP。

本文主要有以下內(nèi)容:

  • 如何使用Servlet編寫Hello Servlet
  • 如何將Servlet與URL對(duì)應(yīng)起來(lái)
  • Servlet如何調(diào)用JSP
  • Servlet如何返回JSON數(shù)據(jù)
  • 如何編寫一個(gè)Dispatcher

Hello Servlet

項(xiàng)目結(jié)構(gòu)如下:

HelloServlet.java內(nèi)容如下:

package me.letiantian.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloServlet extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        try (PrintWriter out = response.getWriter()) {
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet HelloServlet</title>");            
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Servlet HelloServlet at " + request.getContextPath() + "</h1>");
            out.println("</body>");
            out.println("</html>");
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

}

HTTP最常見(jiàn)的方法是GET和POST,在一個(gè)Servlet中對(duì)應(yīng)的處理方法分別是doGet()和doPost()。 response.setContentType("text/html;charset=UTF-8"); 用來(lái)設(shè)置HTTP響應(yīng)頭中的Content-Type。 PrintWriter對(duì)象out的輸出內(nèi)容則是響應(yīng)正文。

web.xml內(nèi)容如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" 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">
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>me.letiantian.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/HelloServlet</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
</web-app>

在這個(gè)配置中,me.letiantian.servlet.HelloServlet與URL/HelloServlet對(duì)應(yīng)。 session-timeout設(shè)置了session的有效時(shí)間,單位是分鐘(不過(guò)目前的程序里還沒(méi)用過(guò)session)。

瀏覽器訪問(wèn)http://127.0.0.1:8084/HelloJSP會(huì)顯示404;訪問(wèn)http://127.0.0.1:8084/HelloJSP/HelloServlet會(huì)顯示Servlet HelloServlet at /HelloJSP,這也正是me.letiantian.servlet.HelloServlet輸出的HTML的渲染結(jié)果。

也可以使用注解將Servlet和URL對(duì)應(yīng)起來(lái)

首先清空web.xml中關(guān)于URL的配置,web.xml最終內(nèi)容如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" 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">

    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>

</web-app>

然后對(duì)me.letiantian.servlet.HelloServlet類略做修改:

package me.letiantian.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javax.servlet.annotation.WebServlet;

@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
    // ......
}

重新啟動(dòng)項(xiàng)目,瀏覽器訪問(wèn)效果和之前是相同的。

Servlet調(diào)用JSP

改寫me.letiantian.servlet.HelloServlet類,內(nèi)容如下:

package me.letiantian.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javax.servlet.annotation.WebServlet;

@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        request.setAttribute("title", "Hello Servlet");
        request.setAttribute("content", "你好");
        RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/jsp/hello.jsp");
        rd.forward(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

}

WEB-INF/下創(chuàng)建目錄jsp,然后在jsp目錄下新建hello.jsp,內(nèi)容如下:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>${title}</title>
    </head>
    <body>
        <h1>${content}</h1>
    </body>
</html>

重啟該項(xiàng)目,訪問(wèn)http://127.0.0.1:8084/HelloJSP/HelloServlet

$ curl -i  http://127.0.0.1:8084/HelloJSP/HelloServlet
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=7CCCFD5467F8330066F827623802FB23; Path=/HelloJSP/; HttpOnly
Content-Type: text/html;charset=UTF-8
Content-Length: 215
Date: Fri, 18 Sep 2015 08:09:58 GMT

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Hello Servlet</title>
    </head>
    <body>
        <h1>你好</h1>
    </body>
</html>

CSS等靜態(tài)文件放在什么地方

在項(xiàng)目下建立static目錄,再這個(gè)目錄下添加test.js,內(nèi)容如下:

console.log("hello world");

web.xml添加以下內(nèi)容:

<servlet-mapping>  
    <servlet-name>default</servlet-name>
    <url-pattern>*.jpg</url-pattern>   
</servlet-mapping>  

<servlet-mapping>  
    <servlet-name>default</servlet-name>
    <url-pattern>*.png</url-pattern>   
</servlet-mapping>  

<servlet-mapping>    
    <servlet-name>default</servlet-name>  
    <url-pattern>*.js</url-pattern>  
</servlet-mapping>  

<servlet-mapping>    
    <servlet-name>default</servlet-name>    
    <url-pattern>*.css</url-pattern>   
</servlet-mapping>

此時(shí),項(xiàng)目結(jié)構(gòu)如下:

啟動(dòng)項(xiàng)目,訪問(wèn)

$ curl -i http://localhost:8084/HelloJSP/static/test.js
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Accept-Ranges: bytes
ETag: W/"27-1442566151000"
Last-Modified: Fri, 18 Sep 2015 08:49:11 GMT
Content-Type: application/javascript
Content-Length: 27
Date: Fri, 18 Sep 2015 08:58:00 GMT

console.log("hello world");
$ curl -i http://localhost:8084/HelloJSP/static/test.js?time=123
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Accept-Ranges: bytes
ETag: W/"27-1442566151000"
Last-Modified: Fri, 18 Sep 2015 08:49:11 GMT
Content-Type: application/javascript
Content-Length: 27
Date: Fri, 18 Sep 2015 08:58:09 GMT

console.log("hello world");

Servlet如何返回JSON數(shù)據(jù)

response.setContentType("text/html;charset=UTF-8");

修改為

response.setContentType("application/json;charset=UTF-8");

out.println輸出JSON格式的字符串即可。

編寫Dispatcher

基于以上的學(xué)習(xí),已經(jīng)可以編寫一個(gè)分發(fā)器了。 將HelloServlet.java修改為DispatcherServlet.java,內(nèi)容修改為:

package me.letiantian.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javax.servlet.annotation.WebServlet;

@WebServlet("/")
public class HelloServlet extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/plain;charset=UTF-8");
        try (PrintWriter out = response.getWriter()) {
            out.println("context: " + request.getContextPath());
            out.println("request uri: " + request.getRequestURI());
            out.println("params: " + request.getParameterMap());
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

}

運(yùn)行項(xiàng)目,訪問(wèn)結(jié)果如下:

$ curl http://localhost:8084/HelloJSP/user
context: /HelloJSP
request uri: /HelloJSP/user
params: {}
$ curl http://localhost:8084/HelloJSP/user?name=letian
context: /HelloJSP
request uri: /HelloJSP/user
params: {name=[Ljava.lang.String;@49ea47b4}
$ curl http://localhost:8084/HelloJSP/static/test.js
console.log("hello world");

(這個(gè)代碼并沒(méi)什么用~)

從這段代碼中可以看到,我們可以通過(guò)request對(duì)象得到HTTP請(qǐng)求信息,特別是request URI。在這個(gè)程序的基礎(chǔ)上,我們 可以繼續(xù)擴(kuò)充它,使得其遇到某個(gè)URI,就調(diào)用指定的處理函數(shù)。慢慢地補(bǔ)充,一個(gè)框架就出來(lái)了。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)