java學習day32---servlet(上)
Servlet
是伺服器端執行的java小程式,起到一個橋樑的作用,用於瀏覽器和應用程式之間進行溝通。
1. tomcat 的目錄結構
bin 可執行指令碼目錄
conf 配置檔案目錄
logs 日誌目錄
webapps 應用程式目錄
2. 啟動和停止
前提條件:安裝JDK並配置JAVA_HOME環境
啟動: bin/startup.bat (windows下)
停止: bin/shutdown.bat (windows下) 或者 在啟動的cmd黑視窗下 CTRL+C (停止程式,不是拷貝)
可以用瀏覽器檢查它是否真正啟動: 在瀏覽器位址列輸入 http://localhost:8080
http://127.0.0.1:8080
http://192.168.10.240:8080
當埠號為80時可以省略不寫
3.在IDEA中設定Tomcat
File---New---Project---Java Enterprise---選擇Project SDK,JavaEE version---選擇JBoss中的Web Application---起名建立成功---Run---Edit Configration...選擇Tomcat Servlet,然後啟動,如果自動跳轉一個$Title$頁面則為啟動成功
4. 修改埠號
在conf/server.xml 檔案中搜索8080 找到後修改為其它埠號即可
5. 編寫第一個servlet
* 1. 建立一個類繼承 HttpServlet父類
* 2. 使用註解 @WebServlet(urlPatterns = "/瀏覽器訪問路徑"),記得要有斜槓
* 3. 重寫父類中 service 方法
@WebServlet(urlPatterns = "/hello") //注意:在一個專案內,多個servlet的urlPatterns不能重複,要確保唯一
public class MyServlet extends HttpServlet {
@Override
// Request : 代表請求
// Response : 代表響應
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("你好,世界");
resp.setContentType("text/html;charset=utf-8"); // 對於中文,需要設定響應採用utf-8字符集,否則會有亂碼問題
// 向resp物件物件的字元輸出流中寫入的html程式碼都會返回給瀏覽器
resp.getWriter().println("<html><body>你好,世界</body></html>");
}
}
6. 瀏覽器傳送請求
語法:
http://ip地址:埠號/servlet地址?引數名1=引數值1&引數名2=引數值2...
例如: ?name=張三&pass=123 // name是引數名,張三是引數值, pass是引數名, 123 是引數值
伺服器要獲取請求引數:
String 請求引數的值 = request.getParameter("請求引數名");
注意:
如果某個引數沒有傳遞,使用request.getParameter()返回的是null值
request.getParameter()返回的總是字串,需要自己做資料型別轉換
package web;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
* 1. 繼承 HttpServlet父類
* 2. 使用註解 @WebServlet(urlPatterns = "瀏覽器訪問路徑")
* 3. 覆蓋父類中 service 方法
*/
@WebServlet(urlPatterns = "/hello")
public class MyServlet extends HttpServlet {
@Override
// Request : 代表請求
// Response : 代表響應
// %E4%B8%AD 中 %E6%96%87 文
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 手工進行解碼, 需要放在所有 req.getParameter方法之前呼叫
req.setCharacterEncoding("utf-8");
// 用req可以獲取瀏覽器發過來的請求引數
System.out.println(req.getParameter("name")); // 根據名稱獲取值
System.out.println(req.getParameter("pass"));
System.out.println("你好,世界");
// 用servlet可以返回一段html程式碼,給瀏覽器
// 對於中文,需要設定響應採用utf-8字符集,否則會使用英文字符集(iso-8859-1)返回響應,會有亂碼問題
resp.setContentType("text/html;charset=utf-8");
// 向resp物件物件的字元輸出流中寫入的html程式碼都會返回給瀏覽器
// 希望返回伺服器的時間
resp.getWriter().println("<html><body>你好,世界,現在時間是:" + new Date() + "</body></html>");
}
}
7. 請求型別
在HTML程式碼中,method後面跟的引數就是請求型別,不寫則預設為get請求
get 和 post(預設請求時get)
兩者的區別:
1) get請求會把所有請求引數跟在位址列之後,不適合傳送敏感資訊
而post請求不會把請求引數跟在位址列之後
2) 不要以為post請求是安全的,通過一些網路監測工具仍然可以看到post中的引數資訊
http 是不安全的,都是明文傳送給伺服器的
https 是安全的,會把資訊傳送給伺服器的過程中進行加密
https 和post結合可以保證向伺服器傳輸資料的安全性
3) get請求傳輸的資料有限制, post請求沒有限制(任意大小的資料都可以傳送給伺服器)
4) get 意味著獲取資訊(對應查詢操作)
post 意味著增,改,刪等操作
5) 對於post請求,會有中文亂碼問題,
要在 req.getParameter方法之前呼叫req.setCharacterEncoding("utf-8");進行手工解碼
預設請求引數(get)
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
@WebServlet(urlPatterns = "/ReqParaTest")
public class ReqParaTest extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("這是關於請求引數的測試");
System.out.println(req.getParameter("name")); //根據name引數得到對應的引數值
System.out.println(req.getParameter("pass")); //根據pass引數得到對應的引數值
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().println("<html><body>hello,world 現在時間" +new Date() + "</body></html>");
}
}
執行結果:根據網址中輸入的引數值列印到控制檯上
當請求引數是get時,會將一些敏感資訊直接暴露在位址列上,不安全,例子如下
請求引數的java程式碼同上,HTML程式碼如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="ReqParaTest" method="get"> <!--action後面跟的引數即為對應的Servlet程式碼,如果method不出現,則預設也是get請求-->
<input type="text" name="name">
<input type="submit" value="提交">
</form>
</body>
</html>
在位址列輸入HTML程式碼的地址
提交之後執行結果:會發現位址列上有輸入的使用者名稱及密碼資訊
而如果請求是post,則只會在列印臺輸出,而不會顯示在位址列上
執行結果:
> 注意: tomcat 8 已經對get請求中的中文按utf-8進行解碼了, 所以程式設計師不需要對get請求的中文進行額外處理
tomcat 7, tomcat 6 ... 對get請求中的中文還需要特殊處理
8.servlet 的生命週期
瀏覽器首次向此servlet傳送請求時,會建立它的例項物件;以後再發送請求使用的仍然是第一次建立的物件。
結論:整個生命週期中,servlet只有一個例項(單例的)
1) 構造方法首先執行(只執行一次)
2) 初始化方法init (只執行一次)
3) 服務方法 service (反覆被執行)來一次請求執行一次
4) 銷燬方法 destroy (只執行一次)在伺服器停止前,或重新部署時
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import java.io.IOException;
@WebServlet(urlPatterns = "/live")
public class ServletLive extends HttpServlet {
public ServletLive() {
System.out.println("Servlet構造方法執行");
}
@Override
public void init() throws ServletException {
System.out.println("Servlet初始化方法執行");
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("Servlet的服務方法執行");
}
@Override
public void destroy() {
System.out.println("Servlet銷燬方法執行");
}
}
開啟頁面localhost:8080/live,會發現構造方法,初始化方法,服務方法都被執行,但是不斷重新整理這個頁面,只會不斷執行服務方法,當停止伺服器時,執行銷燬方法
9.關於資料的頁面展示
一個java web專案:
|-
|-WEB-INF (受保護不能直接訪問)
|-classes 放自己編寫的java類
|-lib 放第三方的jar包
|-css 放樣式表
|-js 放js指令碼
|-jsp 放網頁檔案
|-index.jsp 首頁面 如果沒有寫具體的地址,會按 index.html, index.jsp
10.用servlet對資料庫中的資料進行操作
如以資料庫中的student為例,顯示student這張表格
import util.Utils; //這是JDBC中方便之後呼叫的工具類包,可以參考之前的程式碼
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;
@WebServlet(urlPatterns = "/OutputStuServletTest")
public class OutputStuServletTest extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("<html><body><table border = ''><tbody>");
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = Utils.getConnection();
stmt = conn.prepareStatement("select * from student");
rs = stmt.executeQuery();
while(rs.next()) {
int sid = rs.getInt("sid");
String sname = rs.getString("sname");
String birthday = rs.getString("birthday");
String sex = rs.getString("sex");
System.out.println(sid + "---" + sname + "---" + birthday + "---" + sex);
out.println(
"<tr><td>"+sid+"</td><td>"+sname+"</td><td>"+sname+"</td><td>"+sname+"</td></tr>"
//sid + "---" + sname + "---" + birthday + "---" + sex + "<br>"
);
}
out.println("</tbody></table></body></html>");
} catch (SQLException e) {
e.printStackTrace();
} finally {
Utils.close(rs, stmt, conn);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
執行結果: