本文依然使用[00-03、從JSP開始](https://github.com/someus/another-tutorial-about-java-web/blob/master/00-03.md)中創建的項目HelloJSP。
本文主要有以下內容:
* 如何使用Servlet編寫Hello Servlet
* 如何將Servlet與URL對應起來
* Servlet如何調用JSP
* Servlet如何返回JSON數據
* 如何編寫一個Dispatcher
## [](https://github.com/someus/another-tutorial-about-java-web/blob/master/00-04.md#hello-servlet)Hello Servlet
項目結構如下:
[](https://github.com/someus/another-tutorial-about-java-web/blob/master/img/00-04/01.png)
`HelloServlet.java`內容如下:
~~~
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最常見的方法是GET和POST,在一個Servlet中對應的處理方法分別是doGet()和doPost()。`response.setContentType("text/html;charset=UTF-8");`?用來設置HTTP響應頭中的Content-Type。 PrintWriter對象out的輸出內容則是響應正文。
`web.xml`內容如下:
~~~
<?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>
~~~
在這個配置中,`me.letiantian.servlet.HelloServlet`與URL`/HelloServlet`對應。?`session-timeout`設置了session的有效時間,單位是分鐘(不過目前的程序里還沒用過session)。
瀏覽器訪問`http://127.0.0.1:8084/HelloJSP`會顯示404;訪問`http://127.0.0.1:8084/HelloJSP/HelloServlet`會顯示`Servlet HelloServlet at /HelloJSP`,這也正是`me.letiantian.servlet.HelloServlet`輸出的HTML的渲染結果。
### [](https://github.com/someus/another-tutorial-about-java-web/blob/master/00-04.md#也可以使用注解將servlet和url對應起來)也可以使用注解將Servlet和URL對應起來
首先清空web.xml中關于URL的配置,web.xml最終內容如下:
~~~
<?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>
~~~
然后對`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 {
// ......
}
~~~
重新啟動項目,瀏覽器訪問效果和之前是相同的。
## [](https://github.com/someus/another-tutorial-about-java-web/blob/master/00-04.md#servlet調用jsp)Servlet調用JSP
改寫me.letiantian.servlet.HelloServlet類,內容如下:
~~~
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/`下創建目錄`jsp`,然后在`jsp`目錄下新建`hello.jsp`,內容如下:
~~~
<!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>
~~~
重啟該項目,訪問`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>
~~~
## [](https://github.com/someus/another-tutorial-about-java-web/blob/master/00-04.md#css等靜態文件放在什么地方)CSS等靜態文件放在什么地方
在項目下建立static目錄,再這個目錄下添加`test.js`,內容如下:
~~~
console.log("hello world");
~~~
在`web.xml`添加以下內容:
~~~
<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>
~~~
此時,項目結構如下:
[](https://github.com/someus/another-tutorial-about-java-web/blob/master/img/00-04/02.png)
啟動項目,訪問
~~~
$ 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");
~~~
## [](https://github.com/someus/another-tutorial-about-java-web/blob/master/00-04.md#servlet如何返回json數據)Servlet如何返回JSON數據
將
~~~
response.setContentType("text/html;charset=UTF-8");
~~~
修改為
~~~
response.setContentType("application/json;charset=UTF-8");
~~~
。
`out.println`輸出JSON格式的字符串即可。
## [](https://github.com/someus/another-tutorial-about-java-web/blob/master/00-04.md#編寫dispatcher)編寫Dispatcher
基于以上的學習,已經可以編寫一個分發器了。 將HelloServlet.java修改為DispatcherServlet.java,內容修改為:
~~~
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);
}
}
~~~
運行項目,訪問結果如下:
~~~
$ 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");
~~~
(這個代碼并沒什么用~)
從這段代碼中可以看到,我們可以通過request對象得到HTTP請求信息,特別是request URI。在這個程序的基礎上,我們 可以繼續擴充它,使得其遇到某個URI,就調用指定的處理函數。慢慢地補充,一個框架就出來了。
## [](https://github.com/someus/another-tutorial-about-java-web/blob/master/00-04.md#資料)資料
本節中,JSP使用了表達式語言,可以參考:
[JSTL 入門: 表達式語言](http://www.ibm.com/developerworks/cn/java/j-jstl0211/index.html)
[JSP 表達式語言](http://www.runoob.com/jsp/jsp-expression-language.html)
- JSP & Servlet
- 00-00、序
- 00-01、相關軟件的安裝
- 00-02、理解HTTP
- 00-03、從JSP開始
- 00-04、理解Servlet
- 00-05、過濾器與監聽器
- 00-06、使用velocity模板引擎
- 00-07、使用數據庫連接池
- 00-08、Tomcat的運行機制
- Spring MVC
- 01-00、Spring與依賴注入
- 01-01、Spring與面向切面編程
- 01-02、使用Spring MVC構建Hello World
- 01-03、JdbcTemplate
- 01-04、基于注解的URL映射
- 01-05、JSON
- 01-06、校驗器
- 01-07、國際化
- 01-08、攔截器
- 01-09、文件上傳
- 01-10、轉換器與格式化
- Book
- Online Tutorial
- Q & A
- Learn More
- Supplement