這篇文章, 我主要分享JavaWeb動(dòng)態(tài)網(wǎng)頁開發(fā).要談JavaWeb動(dòng)態(tài)網(wǎng)頁開發(fā).我們就要來了解Servlet, 所以我會按如下進(jìn)行分享
Servlet的規(guī)范
Servlet的請求流程
Servlet初始化參數(shù)
Servlet繼承體系的設(shè)計(jì)原因
-
Servlet請求和響應(yīng)
主要圍繞Servlet的原理
和Servlet的應(yīng)用
兩條主線來分享.
Servlet的原理:
包含Servlet的規(guī)范
、Servlet的基本請求流程
、Servlet繼承體系的設(shè)計(jì)原因
Servlet的應(yīng)用:
包含Servlet初始化參數(shù)
迫靖、Servlet請求和響應(yīng)
1.什么是Servlet規(guī)范
Servlet是一套規(guī)范, 所謂的規(guī)范就是做了約束
.
-
是一個(gè)規(guī)范
.Servlet是一個(gè)規(guī)范,所謂的規(guī)范就是Servlet約束了一些東西, 主要約束了容器
、約束了項(xiàng)目目錄結(jié)構(gòu)
钉嘹,約束了我們的代碼
. -
是一個(gè)組件
. Servlet也可以看成是一個(gè)組件, 因?yàn)橐粋€(gè)遵循Servlet規(guī)范的程序可以跑在實(shí)現(xiàn)Servlet規(guī)范的容器中求冷。
2.如何編寫一個(gè)最簡單的Servlet的步驟
- 創(chuàng)建一個(gè)HelloServlet類繼承自HttpServlet.竟稳。
- 復(fù)寫其service方法, 在其中編寫業(yè)務(wù)邏輯處理請求健蕊。
- 配置web.xml. 增加xml中的servlet對象和servlet-mapping對象.其中servlet對象用來關(guān)聯(lián)我們的類,并給這個(gè)類一個(gè)別名。servlet-mapping對象用來映射servlet和和訪問的資源名罩缴。這樣才來告訴tomcat容器, 一旦請求來了, 該根據(jù)資源名去找哪個(gè)servlet做處理蚊逢。
3.如何研究Servlet對象的生命周期
Servlet對象生命周期依賴于容器, 因?yàn)镾ervlet規(guī)范已經(jīng)約定了Servlet對象必須放在實(shí)現(xiàn)Servlet規(guī)范的容器中運(yùn)行, 換區(qū)話說Servlet對象從出生到死亡都由容器調(diào)度。所以容器負(fù)責(zé)Servlet的創(chuàng)建箫章、初始化烙荷、運(yùn)行、釋放
.
要了解Servlet具體的生命周期, 我們先介紹以下上個(gè)方法.這三個(gè)方法是Servlet的生命周期方法.
生命周期方法
- init(ServletConfig); 負(fù)責(zé)初始化Servlet.
- service(ServletRequest, ServletResponse); 負(fù)責(zé)處理請求.
- destory(); 負(fù)責(zé)釋放Servlet.
觀察Servlet的生命周期
我們可以創(chuàng)建一個(gè)HelloServlet如下, 并且給它提供一個(gè)無參構(gòu)造方法, 分別在上面上個(gè)生命周期方法中做打印, 來研究其調(diào)用順序.
創(chuàng)建HelloServlet, 繼承自HttpServlet.復(fù)寫
其生命周期方法
package com.sweetcs.web.servlet;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloServlet extends HttpServlet{
public HelloServlet() {
// TODO Auto-generated constructor stub
System.out.println("Servlet構(gòu)造方法");
}
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
super.init(config);
System.out.println("Servlet init");
}
@Override
protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
System.out.println("Servlet service");
}
@Override
public void destroy() {
// TODO Auto-generated method stub
super.destroy();
System.out.println("Servlet destroy");
}
}
web.xml中配置資源名的要交個(gè)哪個(gè)servlet處理
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0"
metadata-complete="true">
<display-name>Welcome to Tomcat</display-name>
<description>
Welcome to Tomcat
</description>
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.sweetcs.web.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
第一次訪問http://127.0.0.1:8080/hello打印輸出
第二檬寂、三次訪問http://127.0.0.1:8080/hello打印輸出
通過上述觀察可以發(fā)現(xiàn),第一次訪問是依次調(diào)用了構(gòu)造方法
桶至、init方法
昼伴、service方法
.但是什么時(shí)候Servlet對象的destory方法才會調(diào)用呢?我們進(jìn)行以下兩種方式驗(yàn)證镣屹。
- 第一種停止tomcat的運(yùn)行, 點(diǎn)擊帶有叉號的貓
輸出如下,說明調(diào)用了destory方法, Servlet被正確的釋放掉.
- 第二種直接終止程序.
輸出如下, 說明Servlet對象的destory方法沒有被容器調(diào)用, 也就是說Servlet沒有被正確的釋放掉.
根據(jù)上述實(shí)驗(yàn)驗(yàn)證,我們可以得出以下結(jié)論
總結(jié)
-
Servlet的生命周期是先由容器
創(chuàng)建Servlet對象, 所以會調(diào)用其構(gòu)造方法
.然后再調(diào)用init方法進(jìn)行初始化, 最后調(diào)用service方法處理請求. -
由次可以見Servlet只在第一次訪問時(shí)候創(chuàng)建
.創(chuàng)建完后容器就調(diào)用了servlet的init方法. -
Servlet對象在整個(gè)容器中只有一份,屬于單例
.因?yàn)槎啻蔚南嗤瑄rl的請求過來, 都沒有再調(diào)用構(gòu)造方法, 顯然沒有在創(chuàng)建新的Sevlet對象. -
Servlet必須提供無參數(shù)構(gòu)造器
.由于Sevlet對象不是我們手動(dòng)創(chuàng)建的, 而是交給容器負(fù)責(zé)圃郊。在這里我們使用的是tomcat容器.而tomcat容器是使用反射技術(shù)Class clazz = Class.forName();
和clazz.newInstance()
創(chuàng)建Servlet對象.所以我們必須提供無參構(gòu)造器.當(dāng)然Java中如果你不提供構(gòu)造器, 默認(rèn)就會存在一個(gè)無參構(gòu)造器。 -
要正確的讓Servlet得到釋放
, 必須得停止tomcat容器.如果是程序異常中斷, Servlet并不能得到釋放.
4.Servlet請求流程
我們了解了Servlet的規(guī)范女蜈、Servlet的生命周期描沟、接著我們研究下我們從瀏覽器
通過http協(xié)議請求相應(yīng)的資源的時(shí)候飒泻。服務(wù)器端的Servlet從接受到請求的到響應(yīng)的流程.
- 1.當(dāng)
tomcat服務(wù)器
接受到瀏覽器
的請求時(shí), 會進(jìn)行URL的解析.將URL分解出ContextPath
和ResourceName
.即上下文路徑
和資源名稱
. - 2.解析完成后,
tomcat會去讀取其conf/server.xml
中的所有Context對象
.(我把Context元素叫對象) - 3.然后根據(jù)
ContextPath
的值和Context對象
的path屬性
進(jìn)行比較, 找到對應(yīng)的Context對象。
如果沒有找到對應(yīng)的Context對象就報(bào)404 Not Found
.
如果有找到對應(yīng)的Context對象則進(jìn)入第4步.(如下是一個(gè)Context元素<Context docBase='xxx' path='contextPath' />
) - 4.讀取Context對象的docBase屬性值,即為項(xiàng)目的部署路徑所在地址.tomcat會根據(jù)該地址取讀取其下的
WEB-INF/web.xml
配置文件. - 5.解析
web.xml
中的所有Servlet-Mapping對象, 并用ResouceName和Servlet-Mapping對象的url-pattern比較.如果知道到匹配的進(jìn)入第6步, 否者也是報(bào)404 Not Found
. - 6.根據(jù)找到的Servlet-Mapping對象的servlet-name繼續(xù)找到Servlet對象對應(yīng)的全限定類名.
- 7.
嘗試去 Servlet緩存池獲取對應(yīng)的Servlet對象
.根據(jù)全限定類名取對應(yīng)的Servlet對象.如果取到, 則直接調(diào)用其service方法(傳入已經(jīng)創(chuàng)建好的request和reponse對象) - 8.如果Servlet緩存池中沒有對應(yīng)的對象, 則使用反射技術(shù), 加載解析出來的全限定類名.并調(diào)用其newInstance()方法創(chuàng)建Servlet對象.
- 9.創(chuàng)建ServletConfig對象, 該對象即代表web.xml.調(diào)用Servlet對象的init方法.
servlet.init(config)
- 調(diào)用Servlet對象的service方法處理請求, 相應(yīng)數(shù)據(jù).
servlet.service(request, response)
- 調(diào)用Servlet對象的service方法處理請求, 相應(yīng)數(shù)據(jù).
- 如果有重復(fù)的請求進(jìn)來, 則進(jìn)入第7步.
注意
-
server.xml
文件配置了contextPath.web.xml
配置了資源名稱. -
server.xml
文件讓tomcat根據(jù)contextPath去找到對應(yīng)的根目錄地址.web.xml
文件根據(jù)tomcat根據(jù)資源名稱知道對應(yīng)的Servlet類,再通過反射技術(shù)創(chuàng)建Sevlet對象.
5.Servlet初始化參數(shù)
了解完Servlet的請求流程, 我們也就明白了底層是如何創(chuàng)建Servlet對象, 同時(shí)知道了配置文件的作用吏廉。接著我們就順著該流程的第一個(gè)步驟, 創(chuàng)建并初始化Servlet對象, 想來了解下Servlet的初始化參數(shù).
5.1 init(config)
什么是初始化參數(shù), 即Servlet在創(chuàng)建后, 我們可能會需要它附帶一些屬性, 并且我們用配置好的參數(shù)來初始化這些Servlet.這些參數(shù)都是配置在web.xml
的<Servlet元素>
中.
如下我們給HelloServlet配置初始化參數(shù), 并讀取出來查看.
web.xml配置, 在servlet元素
中添加init-param元素
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.sweetcs.web.servlet.HelloServlet</servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</servlet>
Java代碼
public class HelloServlet extends HttpServlet{
private ServletConfig config;
public HelloServlet() {
// TODO Auto-generated constructor stub
System.out.println("Servlet構(gòu)造方法");
}
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
super.init(config);
this.config = config;
System.out.println("Servlet init");
}
@Override
protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
System.out.println("Servlet service");
String encoding = config.getInitParameter("encoding");
System.out.println(encoding);
}
@Override
public void destroy() {
// TODO Auto-generated method stub
super.destroy();
System.out.println("Servlet destroy");
}
}
啟動(dòng)tomcat, 并瀏覽器輸入http://127.0.0.1:8080/hello.打印如下,可以正確的將配置參數(shù)讀取出來.
Servlet構(gòu)造方法
Servlet init
Servlet service
UTF-8
5.2
根據(jù)5.1我們知道一個(gè)ServletConfig對象
對應(yīng)
的就是其WEB-INF下的web.xml配置文件
.其主要作用就是用來讀取配置文件中的Servlet元素的初始化信息
泞遗。
其有以下兩個(gè)常用接口
-
public String getInitParameter(String name);
根據(jù)配置的參數(shù)的key讀取對應(yīng)的value值 -
public Enumeration<String> getInitParameterNames();
可以讀取到所有的配置參數(shù)的key值.
6 Servlet繼承體系的設(shè)計(jì)原因
上面我們分享了如何編寫一個(gè)Servlet程序、以及Servlet的生命周期過程席覆、Servlet的請求流程和Servlet的初始化參數(shù)史辙。接著我們就來研究下Servlet的繼承體系。我主要借助eclipse和源碼來和大家分享下Servlet的繼承體系的結(jié)構(gòu)和設(shè)計(jì)原因.
1.Servlet的是一個(gè)規(guī)范
, 我們?nèi)绾巫裱湟?guī)范來編寫程序呢?
我們通過查看Servlet接口
可以看到其對應(yīng)的接口代碼.如果讓我們自己來實(shí)現(xiàn)一個(gè)Servlet程序,那么我們首先得實(shí)現(xiàn)其Servlet接口.
并且我們得實(shí)現(xiàn)其生命周期方法
, 來讓tomcat能管理Servlet對象佩伤、并且我們得實(shí)現(xiàn)ServletConfig接口.讓Servlet能得到正確的初始化.依照這個(gè)思路我們可以寫出第一個(gè)版本實(shí)現(xiàn)Servlet接口.
package com.sweetcs.web.servlet;
import java.io.IOException;
import javax.security.auth.login.Configuration;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class MyServlet implements Servlet{
private ServletConfig config;
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
System.out.println("初始化參數(shù)");
this.config = config;
}
@Override
public ServletConfig getServletConfig() {
// TODO Auto-generated method stub
return this.config;
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("處理請求");
}
@Override
public String getServletInfo() {
// TODO Auto-generated method stub
return null;
}
@Override
public void destroy() {
// TODO Auto-generated method stub
System.out.println("desotry servlet");
}
}
為了讓tomcat能正確找到對應(yīng)的Servlet我們還需要配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0"
metadata-complete="true">
<display-name>Welcome to Tomcat</display-name>
<description>
Welcome to Tomcat
</description>
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.sweetcs.web.servlet.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
</web-app>
啟動(dòng)tomcat.并在瀏覽器中輸入http://127.0.0.1:8080/test進(jìn)行測試.
初始化參數(shù)
處理請求
2.如何讀取初始化參數(shù)
我們現(xiàn)在遵循Servlet接口開發(fā)的Servlet程序能正常運(yùn)行了,但是我們?nèi)绾巫x取配置呢?我們可以這樣做,用一個(gè)ServletConfig屬性存儲該ServletConfig對象, 在service方法需要的時(shí)候進(jìn)行讀取.我們在service方法中讀取
如下代碼
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("處理請求");
String encoding = config.getInitParameter("encoding");
}
為什么上述實(shí)現(xiàn)需要重構(gòu)
上述代碼并不存在問題, 但是如果我們現(xiàn)在有10個(gè)Servlet要編寫, 我們就得重復(fù)的在每個(gè)Servlet中存儲一個(gè)ServletConfig屬性用來存儲ServletConfig.而且我們還得為每個(gè)Servlet實(shí)現(xiàn)上述代碼中的所有接口聊倔。這時(shí)候代碼就重復(fù)了, 一旦代碼重復(fù), 我們就要考慮進(jìn)行重構(gòu),如何進(jìn)行重構(gòu)呢?對于重復(fù)代碼我們可以采用繼承方式
或者組合方法
.一般我們都使用組合方式進(jìn)行重構(gòu), 但是在這里由于我們編寫的Servlet都是必須實(shí)現(xiàn)該規(guī)范的, 所以我們并沒必要去用組合的方式.
由此思路我們可以將這些代碼抽取到一個(gè)類中, 我們把它叫MyGenericServlet
3.消除Servlet接口重復(fù)代碼,實(shí)現(xiàn)MyGenericServlet
package com.sweetcs.web.servlet;
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public abstract class MyGenericServlet implements Servlet{
private ServletConfig config;
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
System.out.println("初始化參數(shù)");
this.config = config;
}
@Override
public ServletConfig getServletConfig() {
// TODO Auto-generated method stub
return this.config;
}
@Override
public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
@Override
public String getServletInfo() {
// TODO Auto-generated method stub
return null;
}
@Override
public void destroy() {
// TODO Auto-generated method stub
System.out.println("desotry servlet");
}
}
- 之所以將service聲明為抽象方法,是因?yàn)槿绻贿@樣做.這很容易忘記要復(fù)寫該service方法,該方法主要負(fù)責(zé)請求的處理, 不同的servlet對請求的處理邏輯是不盡相同的, 所以將其聲明為抽象方法是比較合適的.
- 根據(jù)抽象方法約定, MyGenericServlet也必須為抽象類
4.現(xiàn)在考慮子類如何讀取初始化參數(shù)?
- 首先子類并沒有辦法直接訪問父類的config屬性,因?yàn)樵搶傩允莗rivate的, 比較好的方法是父類提供進(jìn)一步的封裝讓我們能根據(jù)key來讀取初始化參數(shù)值.
- 考慮到ServletConfig對象中擁有兩個(gè)常用方法,我們可以在父類中實(shí)現(xiàn)這兩個(gè)常用方法, 而Servlet規(guī)范中,恰好也提供了ServletConfig接口生巡,所以我們可以讓MyGenericServlet實(shí)現(xiàn)該接口.
public abstract class MyGenericServlet implements Servlet, ServletConfig{
private ServletConfig config;
@Override
public String getInitParameter(String name) {
// TODO Auto-generated method stub
return config.getInitParameter(name);
}
@Override
public Enumeration<String> getInitParameterNames() {
// TODO Auto-generated method stub
return config.getInitParameterNames();
}
.......// 省略后面代碼
}
5.需要定制專門處理Http的Servlet
經(jīng)過1--4 我們已經(jīng)抽取了MyGenericServlet, 進(jìn)一步讓代碼重用性得到提高.現(xiàn)在的問題是, MyGenericServlet是處理一般的資源的Servlet耙蔑。其service方法中的request和response對象并不是HttpRequest和HttpResponse對象.也就是說MyGenericServlet并不適合處理Http類型的請求,它是一個(gè)處理通用的請求,子類還需要繼承MyGenericServlet做進(jìn)一步訂制.
- 我們需要實(shí)現(xiàn)MyHttpServlet,讓其繼承MyGenericServlet.并復(fù)寫其service方法.在該方法中我們對ServletRequest和ServletResponse進(jìn)行強(qiáng)制類型轉(zhuǎn)換.并提供一個(gè)重載的service方法孤荣。在該重載service方法中我們進(jìn)行方法的分發(fā)甸陌。具體代碼如下
package com.sweetcs.web.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyHttpServlet extends MyGenericServlet{
@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);
}
protected void service(HttpServletRequest req, HttpServletResponse resp) {
String method = req.getMethod();
if ("GET".equalsIgnoreCase(method)) {
doGet();
}else if ("POST".equalsIgnoreCase(method)) {
doPost();
}else {
}
}
private void doPost() {
// TODO Auto-generated method stub
}
private void doGet() {
// TODO Auto-generated method stub
doPost();
}
}
繼承體系圖
通過上述代碼,我們可以可以對比下我們實(shí)現(xiàn)的繼承體系
和HttpServlet的繼承體系
盐股。(按command + t
查看類的繼承結(jié)構(gòu))
其之所以這樣設(shè)計(jì),就是為了消除代碼重復(fù),為了提供專門處理Http請求的Servlet
總結(jié)Servlet繼承結(jié)構(gòu)
-
GenericServlet是一個(gè)抽象類
,實(shí)現(xiàn)
了Sevlet接口, 并實(shí)現(xiàn)了大多數(shù)的Servlet接口
方法, 并實(shí)現(xiàn)了ServletConfig接口
用來讀取初始化參數(shù).(還實(shí)現(xiàn)了java.io.Serializable接口支持網(wǎng)絡(luò)序列化傳輸) -
HttpServlet
繼承自GeneircServlet
是對其進(jìn)一步的擴(kuò)展,專門用來處理Http類型的請求.
7. Servlet請求和相應(yīng)
我們了解了整個(gè)Servlet的請求流程和其體系結(jié)構(gòu),其實(shí)現(xiàn)在我們就可以進(jìn)行更多復(fù)雜的業(yè)務(wù)邏輯開發(fā)钱豁。在這之前我們需要了了解下HttpServletRequest和HttpServletResponse的常用API.
由于是API的使用, 我們將簡要的介紹完API功能后, 使用代碼演示一個(gè)注冊用戶的功能.
HttpServletRequest
是什么:HttpServletRequest是ServletRequest的子類, 主要用于處理Http請求, 其表示一個(gè)Http請求對象.
常用API
- getMethod(). 獲取請求對象的方式,是GET還是POST等等
- getRequestURI(). 獲取請求的資源路徑(contextPath+resouceName)
- getRequestURL(). 獲取整個(gè)URL地址
- getHeader(String name) 根據(jù)name獲取請求頭中的字段信息.
獲取請求參數(shù)的方法
- getParameter(String name);
- getParameterValues(String name);
- getParameterNames();
- getParameterMap();
request的編碼問題
- 如果是post請求, 記得設(shè)置為UTF-8編碼
req.setCharacterEncoding("UTF-8");
- 如果是GET請求, 可以先進(jìn)行轉(zhuǎn)碼, 先轉(zhuǎn)成字節(jié)數(shù)組,再轉(zhuǎn)換成UTF-8格式的字符編碼(tomcat中請求對象,默認(rèn)是ISO-8859-1編碼疯汁,不兼容中文.)
byte[] data = username.getBytes("ISO-8859-1");
username = new String(data, "UTF-8"); // 這時(shí)候就可以正確的輸出
HttpServletResponse
常用API
- getOuputStream(); 獲取字節(jié)輸出流.
常用在文件的下載
- getWriter(); 獲取字符輸出流.
用在像網(wǎng)頁輸出字符
注意
- 記得設(shè)置MIME類型和charset.
resp.setContentType("text/html; charset=UTF-8")
需求,寫代碼
我們需要完成這樣一個(gè)需求, 通過servlet完成一個(gè)網(wǎng)頁版的計(jì)算器牲尺。具體頁面如下, 因?yàn)槲覀冞€沒介紹jsp, 所以需要在servlet中完成網(wǎng)頁頁面的繪制.
頁面
代碼
package com.sweetcs.calc.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/calc")
public class CalcServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8"); // 只針對post請求有效
resp.setContentType("text/html; charset=UTF-8"); // 設(shè)置輸出的類型和編碼
String op = req.getParameter("op");
String leftNum = req.getParameter("leftNum");
String rightNum = req.getParameter("rightNum");
if (leftNum == null || "".equals(leftNum)) leftNum = "0";
if (rightNum == null || "".equals(rightNum)) rightNum = "0";
String result = "0";
System.out.println(op);
System.out.println(leftNum + "," + rightNum);
if (op != null) {
switch (op) {
case "+":
result = (Double.parseDouble(leftNum) + Double.parseDouble(rightNum))+"";
break;
case "-":
result = (Double.parseDouble(leftNum) - Double.parseDouble(rightNum))+"";
break;
case "*":
result = (Double.parseDouble(leftNum) * Double.parseDouble(rightNum))+"";
break;
case "/":
result = (Double.parseDouble(leftNum) / Double.parseDouble(rightNum))+"";
break;
default:
break;
}
}
PrintWriter pw = resp.getWriter();
pw.write("<!DOCTYPE html> <html>"
+ " <head> "
+ "<meta charset='UTF-8'> "
+ "<title>Insert title here</title> "
+ "</head> "
+ "<body> " + "<form action='/calc' method='GET'>"
+ "<input type='text' name='leftNum' /> "
+ "<select name = 'op'> "
+ "<option value='+'>+</option> "
+ "<option value='-'>-</option> "
+ "<option value='*'>*</option> "
+ "<option value='/'>/</option> "
+ "</select> "
+ "<input type='text' name='rightNum' /> "
+ "<input type='submit' value='=' /> "
+ "<input type='text' name='result' value="+ result +" /> "
+ "</form> "
+ "</body> "
+ "</html>");
pw.close();
}
}
后續(xù)
JavaWeb基礎(chǔ)(六)中我將分享Web開發(fā)中的Cookie和Session.