一、HttpServletRequest
1、概述:
我們在創建Servlet時會覆蓋service()方法,或doGet()/doPost(),這些方法都有兩個參數,一個為代表請求的request和代表的響應response。
service方法中的request的類型是ServletRequest,而doGet/doPost方法的request的類型是HttpServletRequest,HttpServletRequest是ServletRequest的子接口,功能和方法更加強大,今天我們學習HttpServletRequest。
2、request的運行流程
3、通過抓包工具抓取Http請求
因為request代表請求,所以我們可以通過該對象分別獲得Http請求的請求行,請求頭和請求體
4、通過request獲得請求行
獲得客戶端的請求方式:String
getMethod()
獲得請求的資源:
String
getRequestURI()
獲得請求地址
StringBuffer
getRequestURL()
獲得網絡地址
String
getContextPath()
---
獲得
web
應用的名稱
String
getQueryString()
----
只能獲得
get
方式
提交
url
地址后的參數字符串 如:username=zhangsan&password=123
注意:request獲得客戶機(客戶端)的一些信息
request.getRemoteAddr() --- 獲得訪問的客戶端IP地址
5、通過request獲得請求頭
long
getDateHeader(
String name)
String
getHeader(
String name)
Enumeration
getHeaderNames()
Enumeration
getHeaders(
String name)
int
getIntHeader(
String name)
referer頭的作用:執行該此訪問的的來源,做防盜鏈 (referer的內容為訪問的網絡地址)
package com.oracle.demo01; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class RefererServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //獲取referer請求頭 String referer=request.getHeader("referer"); //對該訪問的來源進行判斷 //如果判斷成功,代表我自己的域名,就可以訪問 if(referer!=null&&referer.startsWith("http://localhost:8080")){ response.setContentType("text/html;charset=utf-8"); response.getWriter().write("習大大擘畫新時代黨的組織路線圖"); }else{ response.setContentType("text/html;charset=utf-8"); response.getWriter().write("你是盜鏈者,丟不丟人"); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
Jsp代碼:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <a href="/WEB04/RefererServlet">習大大說新時代</a> <form action="/WEB04/LoginServlet" method="get"> 用戶名:<input type="text" name="username"><br> 密碼:<input type="password" name="pwd"><br> <input type="submit" value="登陸"><br> <input type="reset" value="重置"> </form> </body> </html>
代碼演示:
package com.oracle.demo01; import java.io.IOException; 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 LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //獲取請求行里信息的方法 //獲取請求方式 String method=request.getMethod(); System.out.println(method); //獲取請求資源的相關內容 String requestURI=request.getRequestURI(); StringBuffer requestURL=request.getRequestURL(); System.out.println("requestURI:"+requestURI); System.out.println("requestURL:"+requestURL); //獲取WEB應用的名稱 String name=request.getContextPath(); System.out.println(name); //獲取get方式提交后url地址后的字符串 String queryString=request.getQueryString(); System.out.println(queryString); //獲取客戶機的信息----獲取訪問者的IP地址 String ip=request.getRemoteAddr(); System.out.println(ip); //獲取請求頭中的內容 //獲取指定頭 String header=request.getHeader("User-Agent"); System.out.println(header); //獲得所有頭的名稱 Enumeration<String> en=request.getHeaderNames(); //以鍵值對的形式獲得,並保存在集合中 while(en.hasMoreElements()){ //遍歷,獲得鍵和值 String headerName=en.nextElement(); String headerValue=request.getHeader(headerName); System.out.println(headerName+":"+headerValue); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
6、通過request獲取請求體
String
getParameter(
String name)
String[]
getParameterValues(
String name)
Enumeration
getParameterNames()
Map<String,String[]>
getParameterMap()
注意:get請求方式的請求參數 上述的方法一樣可以獲得
解決post提交方式的亂碼:request.setCharacterEncoding("UTF-8");
解決get提交的方式的亂碼: parameter = new String(parameter.getbytes("iso8859-1"),"utf-8");
7、request的其他功能
(1)request是一個域對象
request對象也是一個存儲數據的區域對象,所以也具有如下方法:
setAttribute(
String name,
Object o)
getAttribute(
String name)
removeAttribute(
String name)
注意:request域的作用范圍:一次請求中
(2)request完成請求轉發
獲得請求轉發器----path
是轉發的地址
RequestDispatcher
getRequestDispatcher(
String path)
通過轉發器對象轉發
requestDispathcer.forward(
ServletRequest request,
ServletResponse response)
注意:
ServletContext
域與
Request
域的生命周期比較?
ServletContext
:
創建:服務器啟動
銷毀:服務器關閉
域的作用范圍:整個
web
應用
request
:
創建:訪問時創建
request
銷毀:響應結束
request
銷毀
域的作用范圍:一次請求中
注意:轉發與重定向的區別?
1
)重定向兩次請求,轉發一次請求
2
)重定向地址欄的地址變化,轉發地址不變
3
)重新定向可以訪問外部網站
轉發只能訪問內部資源
4
)轉發的性能要優於重定向
代碼演示:
package com.oracle.demo02; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet01 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //向request域中存值 request.setAttribute("name", "wang"); //請求轉發 //獲得轉發器對象,並調用轉發方法 request.getRequestDispatcher("/Servlet02").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
總結:
request
獲得行的內容
request.getMethod()
request.getRequestURI()
request.getRequestURL()
request.getContextPath()
request.getRemoteAddr()
request
獲得頭的內容
request.getHeader(name)
request
獲得體(請求參數)
String request.getParameter(name)
Map<String,String[]> request.getParameterMap();
String[] request.getParameterValues(name);
注意:客戶端發送的參數
到服務器端都是字符串
獲得中文亂碼的解決:
post:request.setCharacterEncoding(“UTF-8”);
get:parameter = new String(parameter.getBytes(“iso8859-1”),”UTF-8”);
request
轉發和域
request.getRequestDispatcher(
轉發的地址
).forward(req,resp);
request.setAttribute(name,value)
request.getAttribute(name)
二、HttpServletResponse
1.HttpServletResponse概述
我們在創建Servlet時會覆蓋service()方法,或doGet()/doPost(),這些方法都有兩個參數,一個為代表請求的request和代表響應response。
service方法中的response的類型是ServletResponse,而doGet/doPost方法的response的類型是HttpServletResponse,HttpServletResponse是ServletResponse的子接口,功能和方法更加強大,今天我們學習HttpServletResponse。
2. Response運行流程
3. 通過抓包工具獲取Http響應
因為response代表響應,所以我們可以通過該對象分別設置Http響應的響應行,響應頭和響應體
4.通過response設置響應行
設置響應行的狀態碼: setStatus(int sc)
代碼演示:
package com.oracle.demo01; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet01 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //設置響應行的狀態碼:response.setStatus(int類型的數值);當響應成功后的狀態碼就是你設置的 response.setStatus(404); response.getWriter().write("hello dandan..."); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
5.通過response設置響應頭
addHeader(
String name,
String value)
addIntHeader(
String name, int value)
addDateHeader(
String name, long date)
setHeader(
String name,
String value)
重定向
setDateHeader(
String name, long date)
setIntHeader(
String name, int value)
其中,add表示添加,而set表示設置
重定向需要:1.狀態碼:302
2.響應頭:location 代表重定向地址
重定向代碼演示:
package com.oracle.demo01; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet02 extends HttpServlet { //重定向: //1.服務器訪問兩次 //2.地址欄地址會有變化 //當訪問第一個Servletet02的時候,第一個沒有資源,但是會返回一個響應,告知客戶端Servlet03有資源 //客戶端就會自己跳轉到Servlet03的頁面 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // //1.設置狀態碼 // response.setStatus(302); // //2.設置響應頭Location,重定向 // response.setHeader("Location", "/WEB03/Servlet03"); //開發中上面的方法一般不用,會使用下面封裝好的方法 //開發中封裝好的 專門用於重定向的方法:response.sendRedirect(); response.sendRedirect("/WEB03/Servlet03"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
6.通過response設置響應體
(1)響應體設置文本
PrintWriter
getWriter()
流程:獲得字符流,通過字符流的write(
String s)
方法可以將字符串設置到response緩沖區中,隨后Tomcat會將response緩沖區中的內容組裝成Http響應返回給瀏覽器端。(必須會說)
關於設置中文的亂碼問題
原因:response緩沖區的默認編碼是iso8859-1,此碼表中沒有中文,可以通過response的setCharacterEncoding(
String charset)
設置response的編碼
但我們發現客戶端還是不能正常顯示文字
原因:我們將response緩沖區的編碼設置成UTF-8,但瀏覽器的默認編碼是本地系統的編碼,因為我們都是中文系統,所以客戶端瀏覽器的默認編碼是GBK,我們可以手動修改瀏覽器的編碼是UTF-8。
我們還可以在代碼中指定瀏覽器解析頁面的編碼方式,
通過response的setContentType(
String type)
方法指定頁面解析時的編碼是UTF-8
response.setContentType("text/html;charset=UTF-8");
上面的代碼不僅可以指定瀏覽器解析頁面時的編碼,同時也內含setCharacterEncoding的功能,所以在實際開發中只要編寫response.setContentType("text/html;charset=UTF-8");就可以解決頁面輸出中文亂碼問題。
解決中文亂碼代碼演示:
package com.oracle.demo01; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet04 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //解決中文亂碼的問題 //設置緩沖區的編碼為UTF-8 // response.setCharacterEncoding("UTF-8"); // //告知客戶端給我用UTF-8解碼 // response.setHeader("Content-Type", "text/html;charset=UTF-8"); response.setContentType("text/html;charset=UTF-8"); response.getWriter().write("中國"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
(2)響應頭設置字節
ServletOutputStream
getOutputStream()
在瀏覽器上輸出一個文件,前提是瀏覽器可以解析,不能解析就是提供下載
獲得字節流,通過該字節流的write(byte[] bytes)可以向response緩沖區中寫入字 節,在由Tomcat服務器將字節內容組成Http響應返回給瀏覽器。
響應頭設置時間自動跳轉:
package com.oracle.demo01; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet03 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //定時刷新的響應頭:定時刷新跳轉到另一個網頁 response.setHeader("refresh", "5;url=http:///www.baidu.com"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
Jsp代碼:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script type="text/javascript"> var time=5; //全局函數,當全部頁面加載完成后才會執行的函數 window.onload=function(){ var second=document.getElementById("second"); timer=setInterval(function(){ //定時器函數 second.innerHTML=time; time--; if(time==0){ clearInterval(timer); //清除定時器 location.href="http://www.baidu.com"; } }, 1000); } </script> </head> <body> 恭喜你,注冊成功,<span style="color:red" id="second">5</span> 秒后跳轉,如不跳轉,請點擊<a href="http://www.baidu.com">這里</a> </body> </html>
練習題:
1. 文件的下載:
package com.oracle.demo02; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //import sun.misc.BASE64Encoder; public class DownloadServlet extends HttpServlet { //服務器提供文件下載的方法 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.獲得下載的文件的名稱 String filename=request.getParameter("filename"); //解決中文亂碼的問題 filename=new String(filename.getBytes("ISO8859-1"),"UTF-8"); //獲取瀏覽器的請求頭User-Agent String agent=request.getHeader("User-Agent"); String filenameEncoding=""; //根據不同的瀏覽器進行編碼(模板代碼復制即可,不需要記憶) if (agent.contains("MSIE")) { // IE瀏覽器 filenameEncoding = URLEncoder.encode(filename, "utf-8"); filenameEncoding = filename.replace("+", " "); } // else if (agent.contains("Firefox")) { // // 火狐瀏覽器 // BASE64Encoder base64Encoder = new BASE64Encoder(); // filenameEncoding = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; // } else { // 其它瀏覽器 filenameEncoding = URLEncoder.encode(filename, "utf-8"); } //2.設置要下載的文件的類型----客戶端通過文件的MIME類型區分文件的類型 response.setContentType(this.getServletContext().getMimeType(filename)); //3.告訴你的客戶端該文件不能直接解析,而是以附件的形式打開(下載) response.setHeader("Content-Disposition", "attachment;filename="+filenameEncoding); //4.獲取文件的絕對路徑 String path=this.getServletContext().getRealPath("download/"+filename); //5.創建輸入流 InputStream in=new FileInputStream(path); //6.獲取輸出流--通過response獲得輸出流 ServletOutputStream out=response.getOutputStream(); //7.文件復制的模板代碼 int len=0; byte[] bytes=new byte[1024]; while((len=in.read(bytes))!=-1){ out.write(bytes,0,len); //輸出到瀏覽器上 } //8.釋放資源 in.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
Jsp代碼:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<h1>使用a標簽直接指向服務器上的資源提供下載功能</h1>
<a href="/WEB03/download/中國.txt">中國.txt</a>
<a href="/WEB03/download/commons.zip">commons.zip</a>
<a href="/WEB03/download/dameinv.jpg">dameinv.jpg</a>
<h1>使用服務器端編碼的方式實現下載功能</h1>
<a href="/WEB03/DownloadServlet?filename=中國.txt">中國.txt</a>
<a href="/WEB03/DownloadServlet?filename=commons.zip">commons.zip</a>
<a href="/WEB03/DownloadServlet?filename=dameinv.jpg">dameinv.jpg</a>
</body>
</html>
2. 將圖片輸出到頁面:
package com.oracle.demo02; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyServlet01 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //使用response獲取字節輸出流,負責寫給客戶端的 ServletOutputStream out=response.getOutputStream(); //確定數據源,將圖片讀到程序中 String realPath=this.getServletContext().getRealPath("dameinv.jpg"); //獲取圖片路徑 InputStream in=new FileInputStream(realPath); int len=0; byte[] bytes=new byte[1024]; while((len=in.read(bytes))!=-1){ //將程序中的字節數組寫到客戶端 out.write(bytes,0,len); } //釋放資源 in.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
3. 注冊到數據庫:
dao層代碼:
package com.oracle.demo02; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class Dao { public int dao(String username,String pwd) throws SQLException{ Connection conn=JDBCUtils.getConnection(); String sql="insert into user (username,password) values(?,?)"; PreparedStatement pst=conn.prepareStatement(sql); pst.setString(1, username); pst.setString(2, pwd); int row=pst.executeUpdate(); JDBCUtils.close(pst, conn); return row; } }
service層代碼:
package com.oracle.demo02; import java.sql.SQLException; public class Service { public String service(String username,String pwd) throws SQLException{ Dao d=new Dao(); int count=d.dao(username, pwd); String mes=""; if(count>0){ mes="注冊成功"; }else{ mes="注冊失敗"; } return mes; } }
servlet層代碼:
package com.oracle.demo02; import java.io.IOException; import java.sql.SQLException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class InsertServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); String username=request.getParameter("username"); String pwd=request.getParameter("pwd"); Service s=new Service(); try { String mes=s.service(username, pwd); response.getWriter().write(mes); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
JDButils代碼:
package com.oracle.demo02; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JDBCUtils { public static Connection getConnection(){ try{ //注冊驅動 Class.forName("com.mysql.jdbc.Driver"); String username="root"; String password="123456"; String url="jdbc:mysql://localhost:3306/goods?characterEncoding=utf-8"; //獲得連接 Connection conn=DriverManager.getConnection(url,username,password); return conn; }catch(Exception ex){ throw new RuntimeException(ex+"數據庫連接失敗"); } } //關閉數據庫的方法 public static void close(ResultSet rs,Statement sta,Connection conn){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(sta!=null){ try { sta.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void close(Statement sta,Connection conn){ if(sta!=null){ try { sta.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
Jsp代碼:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script type="text/javascript"> function changeImg(obj){ obj.src="/WEB03/CheckImgServlet?time="+new Date().getTime(); } </script> </head> <body> <div><%=request.getAttribute("loginInfo")==null?"":request.getAttribute("loginInfo") %></div> <form action="/WEB03/LoginServlet" method="post"> 驗證碼:<input type="text" name="checkcode"> <img src="/WEB03/CheckImgServlet" onclick="changeImg(this)"> <input type="submit" value="登陸"> </form> </body> </html>