JavaEE之WEB專案開發(使用Servlet+Tomcat)
阿新 • • 發佈:2019-02-13
一、WEB專案的演變
1.發展規律
- 由單機向網路發展
- 由CS向BS發展
2.CS和BS的區別
1)CS
- Client Server
- 客服端伺服器程式
- 客戶端需要單獨開發,使用者需要單獨下載並安裝
2)BS
- Browser Server
- 瀏覽器伺服器程式
- 客戶端不用單獨開發,使用者不用單獨安裝
二、Servlet介紹(*)
1.伺服器如何儲存並返回一個網頁?
1)靜態網頁
- 無論誰看其內容都一樣
- 百科、新聞
- 伺服器直接存HTML,直接返回HTML即可
2)動態網頁
- 不同人看到的內容有差異
- 淘寶、微博
- 伺服器儲存一個元件,動態給每個使用者拼一個網頁
- 在Java語言中這個元件就是Servlet
元件:滿足規範的物件
2.Servlet的特點
- 是伺服器端的元件
- 滿足sun的規範
- 可以動態拼資源(HTML/IMG等)
術語:處理HTTP協議
3.什麼是Servlet?
- 是sun推出的用於在伺服器端處理HTTP協議的元件
三、伺服器
1.名稱
- Java伺服器
- WEB伺服器
- Java WEB伺服器
- Servlet容器
2.本質
- 是一個軟體
- 它和瀏覽器是平級的關係
3.舉例
- Tomcat(Apache)
- JBoss
- WebLogic
- WebSphere
四、Tomcat的使用方式
1.單獨使用(專案上線時)
1)配置好JAVA_HOME
2)下載及安裝
- 去Apache官網
- 安裝配置自行百度
3)啟動tomcat
- Linux:開啟/tomcat/bin,在終端輸入chmod +x *sh
- Linux:開啟/tomcat/bin,在終端輸入./startup.sh
- windows:開啟/tomcat/bin,雙擊startup.bat
4)訪問tomcat
5)關閉tomcat
- Linux:開啟/tomcat/bin,在終端輸入./shutdown.sh
- windows:開啟/tomcat/bin,雙擊shutdown.bat
2.通過Eclipse呼叫(開發時)
- 點選window -> preferences -> server -> Runtime Environments -> add …
- 在Eclipse中將自動生成Servers專案
補充
1.tomcat常見使用問題
1)問題描述
- 在啟tomcat時看到如下錯誤
- adress already in use,JVM_BIND:8080
2)產生的原因
- 重複啟動tomcat造成8080埠衝突
- 可能其他軟體佔用了8080埠
3)解決方案
- 啟動原因:開啟/tomcat/bin目錄,通過命令強制關閉它
- 其它軟體:開啟server.xml,在65行修改tomcat埠
建議修改為8088/8089,修改後重啟tomcat才生效
五、Servlet開發步驟
1.建立WEB專案
- 必須具備標準的WEB目錄
- /webapp/WEB-INF/web.xml
2.匯入jar包
1)使用maven
- 使用maven搜尋javaee
- 在結果中選擇javaee-api
2)使用tomcat自帶的包(一般使用這個)
- 選擇專案右鍵點選properties
- 彈出框裡在左側選擇Targeted Runtimes
- 在右側勾選Apache Tomcat
- Apply
3.開發Servlet
1)編寫Servlet
- 建立package
- 建立一個類,名為XxxServlet
- 繼承HttpServlet,從而間接的實現了Servlet介面
- 重寫父類的service()
2)配置Servlet
- 先宣告類,並給它去別名
- 在通過別名引用此類,給他取一個訪問路徑
4.部署(拷貝)
- 在Servers檢視下,選擇tomcat7
- 右鍵點選Add and Remove
- 在彈出框內將左邊的待部署專案移動到右側
- 啟動tomcat即可
5.訪問
六、案例(瀏覽器顯示系統時間)
目錄結構
TimeServlet程式碼
package web;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TimeServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
//1.使用request接收請求資料
//1)請求行(3)
System.out.println("協議型別:"+req.getProtocol());
System.out.println("訪問路徑:"+req.getServletPath());
System.out.println("請求方式:"+req.getMethod());
//2)訊息頭(鍵值對)
//該資料是按照鍵值對的方式儲存的
//Enumeration是一個古老的迭代器,
//其用法和Iterator相似.
Enumeration<String> e = req.getHeaderNames();
while(e.hasMoreElements()) {
String key = e.nextElement();
String value = req.getHeader(key);
System.out.println(key + ":" + value);
}
//3)實體內容
//本案例沒有傳遞具體的業務資料
//2.使用response傳送響應資料
//1)狀態行
//該資料由伺服器自動填充
//2)訊息頭
//訊息頭中的大部分資料由伺服器填充,但返回的內容格式需要程式設計師指定
//告訴瀏覽器向它傳送的是什麼型別的內容
res.setContentType("text/html");
//獲取輸出流,該流指向的目標是瀏覽器
PrintWriter pw = res.getWriter();
//獲取伺服器的時間
//將時間拼到一個網頁裡給瀏覽器返回
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String now = sdf.format(date);
//3)實體內容
//我們輸出的網頁就是實體內容
//此處偷懶,拼一個簡化版的網頁
pw.println("<p>" + now + "</p>");
//關閉輸出流
pw.close();
}
}
web.xml配置檔案程式碼
<!-- 配置Servlet -->
<!-- 1.宣告Servlet,並給它取個別名 -->
<servlet>
<servlet-name>time</servlet-name>
<servlet-class>web.TimeServlet</servlet-class>
</servlet>
<!-- 2.通過別名引用Servlet,並給它取個網名(網路訪問路徑) -->
<servlet-mapping>
<servlet-name>time</servlet-name>
<!-- 網名必須以/開頭 -->
<url-pattern>/ts</url-pattern>
</servlet-mapping>
七、HTTP協議
1.什麼是HTTP
- 就是一個規範(w3c)
- 規定了瀏覽器和伺服器如何通訊以及通訊的資料格式
2.如何通訊
- 瀏覽器和伺服器建立連線
- 瀏覽器向伺服器傳送請求
- 瀏覽器接受響應
- 斷開連線
一次請求一次連結,降低伺服器的壓力
3.資料格式
1)請求資料
- 請求行:請求的基本資訊
- 訊息頭:請求資料的描述
- 實體內容:具體的業務資料
2)響應資料
- 狀態行:響應的基本資訊
- 訊息頭:響應資料的描述
- 實體內容:具體的返回資料
程式碼實現,見上一個案例的程式碼註釋
4.HTTP對開發者的要求
1)不用開發者處理的地方
- 瀏覽器自動打包傳送請求資料
- 伺服器自動打包傳送響應資料
2)需要開發者處理的地方
- 提供具體的請求中的業務資料
- 提供具體的響應中的返回資料
- 通過request處理請求資料,通過response處理響應資料
要求開發者會使用request和response就行了
八、註冊案例
![這裡寫圖片描述](https://img-blog.csdn.net/20180330224221243?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RheWN5bQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)1. 以下涉及的亂碼問題的解決方法(三種)
![這裡寫圖片描述](https://img-blog.csdn.net/20180330224243643?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RheWN5bQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)2. RegServlet.java程式碼
package web;
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 RegServlet extends HttpServlet {
@Override
protected void service(
HttpServletRequest req,
HttpServletResponse res) throws ServletException, IOException {
//採用方案三解決POST請求亂碼問題(在接受資料之前)
req.setCharacterEncoding("utf-8");
//處理請求的一般流程
//1.接收引數
String name = req.getParameter("userName");
String pwd = req.getParameter("pwd");
String sex = req.getParameter("sex");
String[] interests = req.getParameterValues("interest");
//採用方案一解決亂碼問題
//byte[] bs = name.getBytes("iso8859-1");
//name = new String(bs,"utf-8");
//2.處理業務
//常規的註冊業務應該儲存這些資料,此處就輸出下
System.out.println(name);
System.out.println(pwd);
System.out.println(sex);
if(interests != null) {
for(String interest : interests) {
System.out.println(interest);
}
}
//3.傳送響應
res.setContentType("text/html;charset=utf-8");
PrintWriter w = res.getWriter();
w.println("<p>ok,"+name+"</p>");
w.close();
}
}
3. register.heml程式碼
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>註冊</title>
</head>
<body>
<!--
1.完整路徑
http://ip:port/專案名/網名
2.絕對路徑
格式: /專案名/網名
舉例: /servlet2/reg
3.相對路徑(*)
當前: /servlet2/reg.html
目標: /servlet2/reg
二者平級,相對路徑: reg
-->
<form action="reg" method="post">
<p>
賬號:<input type="text" name="userName"/>
</p>
<p>
密碼:<input type="password" name="pwd"/>
</p>
<p>
性別:
<input type="radio" name="sex" value="M"/>男
<input type="radio" name="sex" value="F"/>女
</p>
<p>
興趣:
<input type="checkbox" name="interest" value="food"/>美食
<input type="checkbox" name="interest" value="game"/>競技
<input type="checkbox" name="interest" value="friend"/>社交
</p>
<p>
<input type="submit" value="註冊"/>
</p>
</form>
</body>
</html>
4. 配置檔案程式碼
<servlet>
<servlet-name>reg</servlet-name>
<servlet-class>web.RegServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>reg</servlet-name>
<url-pattern>/reg</url-pattern>
</servlet-mapping>
![這裡寫圖片描述](https://img-blog.csdn.net/20180330224325310?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RheWN5bQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![這裡寫圖片描述](https://img-blog.csdn.net/20180330224340919?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RheWN5bQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![這裡寫圖片描述](https://img-blog.csdn.net/20180330224402452?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RheWN5bQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
九、Servlet執行原理
![這裡寫圖片描述](https://img-blog.csdn.net/20180330224420977?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RheWN5bQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)十、請求方式
1.什麼是起你去方式?
- 就是瀏覽器向伺服器傳送資料的方式
- 我們需要掌握眾多方式中的2種:GET+POST
2.GET
- 採用請求路徑傳參
- 引數在傳遞過程中可見,導致隱私性差
- 路徑可以容納的資料有限,只能傳少量資料
所有的請求預設都是GET請求
3.POST
- 採用實體內容傳參
- 引數在傳遞過程中不可見,隱私性好
- 實體內容專門用來傳資料,大小沒有限制
在form上加method=”post”
4.觀察GET和POST請求
- 在瀏覽器上按快捷鍵F12
- 看NetWork選項
5.GET和POST使用場景(建議)
- 查詢資料時用GET,因為通常查詢條件較少
- 提交資料(表單)時用POST,因為通常提交的資料較多。
十一、亂碼解決方案
補充:
JavaBean
滿足如下規範的類
- 有包
- 有預設的構造器
- 實現序列化介面
- 有get/set方法
十二、模擬查詢員工案例
1. Emp.java實體類
package entity;
import java.io.Serializable;
/**
* 建議:
* 1.儘量使用封裝型別,因為它比基本型別多了null
* 2.使用java.sql包下的日期,因為JDBC支援這樣的日期型別
*
*/
public class Emp implements Serializable {
private Integer empno;
private String ename;
private String job;
private Double sal;
public Integer getEmpno() {
return empno;
}
public void setEmpno(Integer empno) {
this.empno = empno;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public Double getSal() {
return sal;
}
public void setSal(Double sal) {
this.sal = sal;
}
}
2. EmpDao.java介面
package dao;
import java.util.List;
import entity.Emp;
public interface EmpDao {
List<Emp> findAll();
void save(Emp e);
}
3. EmpDaoImpl.java
package dao;
import java.util.ArrayList;
import java.util.List;
import entity.Emp;
public class EmpDaoImpl implements EmpDao {
public List<Emp> findAll() {
//模擬查詢所有的員工
List<Emp> list = new ArrayList<Emp>();
Emp e1 = new Emp();
e1.setEmpno(1);
e1.setEname("唐僧");
e1.setJob("領導");
e1.setSal(9000.0);
list.add(e1);
Emp e2 = new Emp();
e2.setEmpno(2);
e2.setEname("悟空");
e2.setJob("職員");
e2.setSal(5000.0);
list.add(e2);
Emp e3 = new Emp();
e3.setEmpno(3);
e3.setEname("八戒");
e3.setJob("職員");
e3.setSal(6000.0);
list.add(e3);
return list;
}
//模擬增加一個員工(此用於後面增加員工案例)
public void save(Emp e) {
System.out.println("增加了員工: " + e.getEname());
}
}
4. FindEmpServlet.java
package web;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import dao.EmpDao;
import dao.EmpDaoImpl;
import entity.Emp;
public class FindEmpServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {
//1.接收引數
//2.處理業務(查詢)
EmpDao dao = new EmpDaoImpl();
List<Emp> list = dao.findAll();
//3.輸出響應(表格)
res.setContentType("text/html;charset=utf-8");
PrintWriter w = res.getWriter();
//當前: /EmpManager/findEmp
//目標: /EmpManager/add_emp.html
w.println("<a href='add_emp.html'>增加</a>");
//上面一行用於後面增加員工案例
w.println("<table border='1' cellspacing='0' width='40%'>");
w.println(" <tr>");
w.println(" <td>編號</td>");
w.println(" <td>姓名</td>");
w.println(" <td>職位</td>");
w.println(" <td>薪資</td>");
w.println(" </tr>");
//以下是表格資料
if(list != null) {
for(Emp e : list) {
w.println("<tr>");
w.println(" <td>"+e.getEmpno()+"</td>");
w.println(" <td>"+e.getEname()+"</td>");
w.println(" <td>"+e.getJob()+"</td>");
w.println(" <td>"+e.getSal()+"</td>");
w.println("</tr>");
}
}
w.println("</table>");
w.close();
}
}
5. web.xml
<servlet>
<servlet-name>findEmp</servlet-name>
<servlet-class>web.FindEmpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>findEmp</servlet-name>
<url-pattern>/findEmp</url-pattern>
</servlet-mapping>
十二、模擬增加員工案例
1. AddEmpServlet.java
package web;
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 dao.EmpDao;
import dao.EmpDaoImpl;
import entity.Emp;
public class AddEmpServlet extends HttpServlet {
@Override
protected void service(
HttpServletRequest req,
HttpServletResponse res) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
//1.接收引數
String ename = req.getParameter("ename");
String job = req.getParameter("job");
String sal = req.getParameter("sal");
//2.處理業務:儲存員工資料
Emp e = new Emp();
e.setEname(ename);
e.setJob(job);
if(sal != null && sal.equals("")) {
e.setSal(new Double(sal));
}
EmpDao dao = new EmpDaoImpl();
dao.save(e);
//3.傳送響應
res.setContentType("text/html;charset=utf-8");
PrintWriter w = res.getWriter();
w.println("<p>儲存成功</p>");
w.close();
}
}
2. add_emp.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>增加員工</title>
</head>
<body>
<!--
當前: /EmpManager/add_emp.html
目標: /EmpManager/addEmp.do
-->
<form action="addEmp" method="post">
<p>
姓名:<input type="text" name="ename"/>
</p>
<p>
職位:<input type="text" name="job"/>
</p>
<p>
薪資:<input type="text" name="sal"/>
</p>
<p>
<input type="submit" value="儲存"/>
</p>
</form>
</body>
</html>
3. web.xml 配置檔案在加上一下程式碼
<servlet>
<servlet-name>addEmp</servlet-name>
<servlet-class>web.AddEmpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>addEmp</servlet-name>
<url-pattern>/addEmp</url-pattern>
</servlet-mapping>
注:此案例沒連資料庫,儲存成功並不能真正的增加
十三、重定向
1. 修改AddEmpServlet.java
package web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import dao.EmpDao;
import dao.EmpDaoImpl;
import entity.Emp;
public class AddEmpServlet extends HttpServlet {
@Override
protected void service(
HttpServletRequest req,
HttpServletResponse res) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
//1.接收引數
String ename = req.getParameter("ename");
String job = req.getParameter("job");
String sal = req.getParameter("sal");
//2.儲存員工資料
Emp e = new Emp();
e.setEname(ename);
e.setJob(job);
if(sal != null && sal.equals("")) {
e.setSal(new Double(sal));
}
EmpDao dao = new EmpDaoImpl();
dao.save(e);
//3.傳送響應
// res.setContentType("text/html;charset=utf-8");
// PrintWriter w = res.getWriter();
// w.println("<p>儲存成功</p>");
// w.close();
//重定向到查詢頁面,即
//建議瀏覽器自己去訪問查詢頁面.
//當前: /EmpManager/addEmp
//目標: /EmpManager/findEmp
res.sendRedirect("findEmp");
}
}
增加員工提交後,會重定向到查詢介面
十四、路徑
1.什麼是路徑
2.URI和URL的區別
1)俠義的理解
- 只在Java專案中理解URI和URL
- URI:絕對路徑
- URL:完整路徑
從表面上看URI包含了URL
2)廣義的理解
- 在任意的WEB專案中理解URI和URL
- URI:資源的名稱
- URL:資源的真名
URI包含了URL
3.如何配置Servlet訪問路徑
1)精確匹配
- 舉例: /abc
- 只有/abc才能訪問此Servlet
- 此Servlet只能處理這一個請求
適合規模很小的專案
2)萬用字元
- 舉例: /*
- 所有的路徑的都能訪問此Servlet
- 此Servlet能處理所有請求
適合一個專案只寫一個Servlet
3)字尾
- 舉例: *.hi
- 表示所有以hi為字尾的請求都能訪問此Servlet
- 此Servlet能處理多個請求
適合一個專案寫少量的幾個Servlet
4)配置檔案web.xml
<servlet>
<servlet-name>abc</servlet-name>
<servlet-class>web.AbcServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>abc</servlet-name>
<!-- 1.精確定位 -->
<!-- <url-pattern>/abc</url-pattern> -->
<!-- 2.萬用字元 -->
<!-- <url-pattern>/*</url-pattern> -->
<!-- 3.字尾,不能以斜線開頭-->
<url-pattern>*.dung</url-pattern>
</servlet-mapping>
![這裡寫圖片描述](https://img-blog.csdn.net/20180330225031212?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RheWN5bQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
4. 按規範處理路徑修改員工查詢、增加案例
![這裡寫圖片描述](https://img-blog.csdn.net/20180330225043741?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RheWN5bQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)新增MianServlet.java
package web;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import dao.EmpDao;
import dao.EmpDaoImpl;
import entity.Emp;
/**
* 路徑規範:
* 查詢員工:/findEmp.do
* 增加員工:/addEmp.do
*
*/
public class MainServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {
//獲取請求路徑
String path = req.getServletPath();
//根據規範處理路徑
if("/findEmp.do".equals(path)) {
findEmp(req,res);
}else if("/addEmp.do".equals(path)) {
addEmp(req,res);
}else {
//該異常拋給伺服器,伺服器可以統一處理
throw new RuntimeException("查無此頁");
}
}
protected void findEmp(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {
//1.接收引數
//2.處理業務(查詢)
EmpDao dao = new EmpDaoImpl();
List<Emp> list = dao.findAll();
//3.輸出響應(表格)
res.setContentType("text/html;charset=utf-8");
PrintWriter w = res.getWriter();
//當前: /EmpManager/findEmp
//目標: /EmpManager/add_emp.html
w.println("<a href='add_emp.html'>增加</a>");
w.println("<table border='1' cellspacing='0' width='40%'>");
w.println(" <tr>");
w.println(" <td>編號</td>");
w.println(" <td>姓名</td>");
w.println(" <td>職位</td>");
w.println(" <td>薪資</td>");
w.println(" </tr>");
//以下是表格資料
if(list != null) {
for(Emp e : list) {
w.println("<tr>");
w.println(" <td>"+e.getEmpno()+"</td>");
w.println(" <td>"+e.getEname()+"</td>");
w.println(" <td>"+e.getJob()+"</td>");
w.println(" <td>"+e.getSal()+"</td>");
w.println("</tr>");
}
}
w.println("</table>");
w.close();
}
protected void addEmp(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
//1.接收引數
String ename = req.getParameter("ename");
String job = req.getParameter("job");
String sal = req.getParameter("sal");
//2.儲存員工資料
Emp e = new Emp();
e.setEname(ename);
e.setJob(job);
if(sal != null && sal.equals("")) {
e.setSal(new Double(sal));
}
EmpDao dao = new EmpDaoImpl();
dao.save(e);
//3.傳送響應
// res.setContentType("text/html;charset=utf-8");
// PrintWriter w = res.getWriter();
// w.println("<p>儲存成功</p>");
// w.close();
//重定向到查詢頁面,即
//建議瀏覽器自己去訪問查詢頁面.
//當前: /EmpManager/addEmp.do
//目標: /EmpManager/findEmp.do
res.sendRedirect("findEmp.do");
}
}
修改web.xml配置檔案(之前的註釋掉)
<servlet>
<servlet-name>main</servlet-name>
<servlet-class>web.MainServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
![這裡寫圖片描述](https://img-blog.csdn.net/20180330225108915?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RheWN5bQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
將add_emp.html中的action=”addEmp” 改成 action=”addEmp.do”
![這裡寫圖片描述](https://img-blog.csdn.net/20180330225124210?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RheWN5bQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ![這裡寫圖片描述](https://img-blog.csdn.net/2018033022513888?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RheWN5bQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)十五、Servlet生命週期
![這裡寫圖片描述](https://img-blog.csdn.net/20180330225151613?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RheWN5bQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)示例
以下幾個案例都寫在了Servlet3專案裡了,目錄結構如下
![這裡寫圖片描述](https://img-blog.csdn.net/20180330225206161?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RheWN5bQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)HiServlet.java
package web;
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 HiServlet extends HttpServlet {
public HiServlet() {
System.out.println("例項化HiServlet");
}
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
System.out.println("初始化HiServlet");
}
@Override
protected void service(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {
System.out.println("呼叫HiServlet處理請求");
}
@Override
public void destroy() {
super.destroy();
System.out.println("銷燬HiServlet");
}
}
web.xml配置檔案
<servlet>
<servlet-name>hi</servlet-name>
<servlet-class>web.HiServlet</servlet-class>
<!-- 啟動時載入此servlet,中間的數字是載入的順序。 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hi</servlet-name>
<url-pattern>/hi</url-pattern>
</servlet-mapping>
十六、ServletConfig和ServletContext
1.它們的作用
- 都能夠讀取web.xml中為Servlet預置的引數
2.它們的區別
1)config
- config和Servlet是1對1的關係
- Tomcat在初始化每個Servlet前會給它建立一個config
- 呼叫HiServelt.init()前給他建立1個config
- 呼叫HelloServlet.init()前給它建立1個config
- 如果先給某個Servlet預置資料,使用config
2)context
- context和Servlet是1對多的關係
- Tomact在啟動前就建立唯一的一個context
- 所有的Servlet都可以共享這個物件中的資料
- 如果想給多個Servlet預置資料,使用context
3.它們的應用
1)config(預置引數)
- 假設要開發一個網頁遊戲,若超過人數上限則要排隊
- 登入時判斷是否達到最大人數
- 開發登入功能LoginServlet
- 人數上限應該是一個可配置的引數maxOnline
- 該引數由LoginServlet使用
由於該引數只是LoginServlet使用,由config讀取即可
示例(登入上限)
LoginServlet.java
package web;
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 LoginServlet extends HttpServlet {
//Tomcat建立Servlet的過程:
//LoginServlet ls = new LoginServlet();
//ServletConfig cfg = new ServletConfig();
//ls.init(cfg);
//ls.service();
@Override
public void init(ServletConfig config)throws ServletException {
super.init(config);
String maxOnline = config.getInitParameter("maxOnline");
System.out.println(maxOnline);
}
@Override
protected void service(
HttpServletRequest req,
HttpServletResponse res) throws ServletException, IOException {
//此config就是init()傳入的那個
ServletConfig cfg = getServletConfig();
String maxOnline = cfg.getInitParameter("maxOnline");
System.out.println(maxOnline);
System.out.println("正在登入...");
}
}
web.xml
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>web.LoginServlet</servlet-class>
<!-- 給此servlet預置引數 -->
<init-param>
<param-name>maxOnline</param-name>
<param-value>3000</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
![這裡寫圖片描述](https://img-blog.csdn.net/20180330225248114?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RheWN5bQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![這裡寫圖片描述](https://img-blog.csdn.net/20180330225302147?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RheWN5bQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
2)context(分頁)
- 軟體內有很多查詢功能,都帶有分頁功能
- 每頁顯示的行數size是常量,並且可配置
- 該資料在多個查詢功能之間共用,使用context讀取
示例
FindDeptServlet.java
package web;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FindDeptServlet extends HttpServlet {
@Override
protected void service(
HttpServletRequest req,
HttpServletResponse res) throws ServletException, IOException {
//tomcat啟動時就會建立唯一的context,並且會呼叫它的方法
//載入web.xml中的公用引數,context是全域性的,任何servlet都可以使用
ServletContext ctx = getServletContext();
String size = ctx.getInitParameter("size");
System.out.println(size);
System.out.println("分頁查詢部門資料");
//統計流量
//Integer count = (Integer)ctx.getAttribute("count");
//ctx.setAttribute("count", ++count);
//System.out.println(count);
}
}
FindEmpServlet.java
package web;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FindEmpServlet extends HttpServlet {
@Override
protected void service(
HttpServletRequest req,
HttpServletResponse res) throws ServletException, IOException {
ServletContext ctx = getServletContext();
String size = ctx.getInitParameter("size");
System.out.println(size);
System.out.println("分頁查詢員工資料");
//統計流量
//Integer count = (Integer)ctx.getAttribute("count");
//ctx.setAttribute("count", ++count);
//System.out.println(count);
}
}
web.xml
<servlet>
<servlet-name>findDept</servlet-name>
<servlet-class>web.FindDeptServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>findDept</servlet-name>
<url-pattern>/findDept</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>findEmp</servlet-name>
<servlet-class>web.FindEmpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>findEmp</servlet-name>
<url-pattern>/findEmp</url-pattern>
</servlet-mapping>
<!-- 在標籤外配置的引數是給所有Servlet公用的引數,它們都可以通過context讀取該資料 -->
<context-param>
<param-name>size</param-name>
<param-value>20</param-value>
</context-param>
4.context的特殊用法(context可以存取變數)
- 前提:之前使用config和context讀取的是常量
- 而context還有能力讀寫變數
- 用該物件讀寫的變數是可以被所有Servelt共用的
- setAttribute()/getAttribute()
- 案例:開發流量統計功能,無論訪問哪個功能,流量+1
- 由於流量是變數,並且在多功能間共用,所以用context
示例
InitServlet.java
package web;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
/**
* 此類僅僅是在伺服器啟動時初始化引數的,
* 不負責處理任何具體的請求.
* 一般web專案都要1-2個這樣的servlet
*/
public class InitServlet extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
//tomcat啟動時會優先建立context,然後在建立Servlet
ServletContext ctx = getServletContext();
//流量預設為0
ctx.setAttribute("count", 0);
}
}
將FindDeptServlet.java和FindEmpServlet.java中統計流量的註釋去掉
web.xml
<!-- 沒人呼叫可以只寫一半 -->
<servlet>
<servlet-name>init</servlet-name>
<servlet-class>web.InitServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
5.總結
- 當需要給Servlet預置引數時使用這樣的物件
- 若引數只給一個Servlet使用,用config
- 若引數給多個Servlet使用,用context
十七、Servlet層次結構
1.整體結構
2.HttpServlet(我們一般重寫黃色的service)
十八、Servlet執行緒安全問題
1.同時修改區域性變數
- 區域性變數存於棧內
- 每個執行緒有自己的棧幀
此時沒有執行緒安全問題
2.同時修改成員變數
- 成員變數存於堆內
- 所有執行緒共享這樣的資料
此時存線上程安全問題
3.解決方案
- 加鎖
4.案例
UpServlet.java
package web;
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 UpServlet extends HttpServlet {
double salary = 2000.0;
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
//synchronized(this) {
//模擬漲薪
salary += 100.0;
//網路延遲
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//顯示資料
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println(salary);
out.close();
//}
}
}
web.xml
<servlet>
<servlet-name>up</servlet-name>
<servlet-class>web.UpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>up</servlet-name>
<url-pattern>/up</url-pattern>
</servlet-mapping>