重定向的原理圖:
response是專門給用戶端響應資料的響應對象.
Http協定規定: 響應資料也要分成三部分:
響應行: 主要學習設定狀态碼.
響應頭: 主要學習重定向(重點) //掌握
//你找張三借錢, 張三沒錢, 張三找李四溝通, 借錢給你(請求轉發).
//你找張三借錢, 張三沒錢, 張三告訴你思聰有錢, 你去找他(重定向).
響應體: 主要是給用戶端響應頁面上要展示的資料(驗證碼).
功能:
public void setStatus(int sc); //200, 302, 404, 500
//: 請求成功.
//: 請求重定向.
//: 通路的資源不存在.
//: 伺服器内部錯誤.
public void setHeader(String name, Stirng value);
//設定響應頭資訊. name表示屬性名, value表示屬性值.
//響應重定向的路徑
//response.setHeader("location","http://www.itcast.cn");
重定向原理步驟:
) 浏覽器通路Servlet1, 但是該請求Servlet1實作不了, 想交給别的Servlet對象來實作.
) 在Servlet1中完成如下設定:
A: 設定狀态碼, 通知浏覽器找其他資源.
response.setStatus();
B: 設定響應頭, 告訴浏覽器通路新資源的路徑.
response.setHeader("location", "/項目名/servlet名");
) 浏覽器識别伺服器傳回的狀态碼.
馬上準備通路新資源.
//取出新資源的路徑, 馬上通路新資源.
) 浏覽器向新資源(新的Servlet對象)送出請求.
) 新的Servlet對象響應浏覽器的請求.
重定向的實作
需求: 使用浏覽器通路"/responseServlet1", 通過重定向跳轉到: 黑馬官網.
實作方式:
方式一: 分解式
//) 響應狀态碼.
response.setStatus();
//) 響應重定向的路徑
response.setHeader("location","http://www.itcast.cn");
方式二: 合并式
response.sendRedirect("http://www.itcast.cn");
重定向和請求轉發的差別:
相對于浏覽器而言, 是幾次請求幾次響應?
重定向: n次請求, n次響應.
請求轉發: 一次請求, 一次響應.
浏覽器位址和窗體内容是否一緻?
重定向: 一緻.
請求轉發: 不一緻.
頁面跳轉是在伺服器内部, 還是伺服器外部?
重定向: 可以是伺服器内部, 也可以是伺服器外部.
請求轉發: 隻能在伺服器内部. (思路: 把request對象當做容器)
關于是否可以跳轉項目外部的路徑.
重定向: response.sendRedirect("/項目名/servlet名");
請求轉發: request.getRequestDispatcher("/servlet名").forward(request,response);
如果需要将request當做容器使用, 誰合适?
重定向: 不合适.
請求轉發: 更合适.
頁面定時重新整理到新網頁
應用場景:
) 通路的資源不存在, s 後跳轉到首頁.
) 支付成功, s 後跳轉到首頁.
實作方式:
通過設定refresh響應頭資訊來完成這個功能.
格式:
response.setHeader("refresh","秒數;url=網址");
//注意: 路徑可以是外部路徑也可以是内部路徑.
例如:
response.setHeader("refresh","5;url=http://www.itcast.cn");
向浏覽器輸出中文
應用場景:
浏覽器顯示的内容, 下載下傳檔案等.
response: //以流的形式, 将内容輸出給浏覽器.
response.getWriter(); //擷取響應體的字元輸出流.
response.getOutputStream(); //擷取響應體的位元組輸出流.
注意:
) 字元流和位元組流不能同時使用.
) 複制檔案建議用: 位元組流.
手動生成響應内容建議用: 字元流.
) 不需要關流, tomcat會自動調用close(),flush()方法.
案例:
需求: 向浏覽器輸出: "你們真的很棒!"
//字元流實作
//方式一: 字元流, 合并式 //推薦使用
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("你們真的很棒!");
//方式二: 字元流 分解式
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
response.getWriter().println("你們真的很棒!");
//方式三:
response.getOutputStream().write("你們真的很棒!".getBytes("gbk"));
驗證碼代碼
作用: 防止暴力破解.
頁面上的驗證碼生成:
驗證碼一般是一個圖檔, 而這個圖檔是在Java程式中動态生成的.
需要使用Java中GUI的技術完成.
頁面顯示圖檔的原理:
) 浏覽器向伺服器發送請求, 例如請求: html
/*
文本A;
文本B;
圖檔C;
圖檔D:
*/
) 伺服器把該頁面響應給浏覽器.
) 浏覽器按照從上往下的順序解析頁面.
是文本, 就自動解析.
是圖檔, 會再次向伺服器發送請求, 加載該圖檔.
代碼實作:
//以後用到了, 直接複制即可.
//給浏覽器繪制一個: 帶驗證碼的圖檔即可.
int width = ;
int height = ;
// 建立一張圖紙(寬, 高, 顔色類型).
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 擷取畫筆.
Graphics g = bi.getGraphics();
// 設定圖檔的背景色.
// 標明顔色.
g.setColor(Color.white);
// 標明填充的大小
g.fillRect(, , width, height);
// 設定驗證碼的邊框
// 標明顔色
g.setColor(Color.red);
// 標明繪制的方式(大小)
g.drawRect(, , width - , height - );
// 擷取生成的驗證碼, 在控制台中輸出
String str = "";
// 生成随機的字元(生成個), 然後顯示在該圖檔上.
// 擷取資料源(數字, 字母)
String data = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
// 建立随機數對象.
Random r = new Random();
// 因為要生成個, 是以用循環改進.
for (int i = ; i < 4; i++) {
// 設定字型大小及随機字型顔色.
g.setFont(new Font("楷體", Font.BOLD, ));
g.setColor(new Color(r.nextInt(),r.nextInt(),r.nextInt()));
// 把字元繪制到頁面上.
String s = "" + data.charAt(r.nextInt(data.length()));
g.drawString(s, + i * , );
str += s;
}
// 繪制幹擾線
for (int i = ; i < 10; i++) {
g.setColor(new Color(r.nextInt(),r.nextInt(),r.nextInt()));
g.drawLine(r.nextInt(width),r.nextInt(height),r.nextInt(width),r.nextInt(height));
}
// 把圖紙顯示在浏覽器中(圖紙, 圖檔格式, 位元組輸出流(網頁面中寫資料的)).
ImageIO.write(bi, "jpg", response.getOutputStream());
System.out.println(str);
JSP簡介
需求: 使用servlet向浏覽器輸出一個百度超連結頁面.
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("<html>");
response.getWriter().println("<head><titile>百度超連結</title></head>");
response.getWriter().println("<body>");
response.getWriter().println("<a href='http://www.baidu.com'>百度</a>");
response.getWriter().println("</body>");
response.getWriter().println("</html>");
//缺點: 由于使用字元串拼接, 閱讀困難, 維護困難, 開發困難.
//可以通過: JSP解決該問題.
JSP概述:
Java Server Pages, Java伺服器頁面, 其本質就是一個Servlet.
//是一門動态語言, 裡邊既可以寫html代碼, 也可以寫css代碼,
//可以寫js代碼, 也可以寫Java代碼.
在JSP中嵌入Java代碼(JSP的快速入門)
//寫在.jsp檔案中即可, 例如: helloworld.jsp檔案中即可.
方式一: 腳本表達式, 向浏覽器輸出内容.
//類似于輸出語句.
格式:
<%=變量名或者值 %>
例如:
<%="hello world" %>
<%= %>
<%=true %>
方式二: 腳本片段, 類似于: 方法中一段代碼.
<%
for(int i=; i<=10; i++) {
%>
<h3><%=i %><h3>
<%
}
%>
方式三: 腳本聲明, 聲明目前類的成員變量, 成員方法, 内部類等.
<%!
int x = ;
public int add(int x,int y) {
return x + y;
}
class InnerClass{}
%>
成員變量: <%=x %><br>
成員方法: + = <%=add(,) %>
<%
request.setAttribute("money",);
%>
薪資: <%=request.getAttribute("money") %>
原理:
) 浏覽器通路伺服器上的.jsp檔案.
) .jsp檔案會被解析成.java檔案(存在tomcat\work檔案夾中)
) .java檔案會被編譯成.class檔案(虛拟機隻認識.class檔案)
) 浏覽器加載該.class檔案到記憶體, 将内容顯示到頁面上.
/*
C:\Users\使用者名\.IntelliJIdea2016.3\system\tomcat\項目名稱\work\Catalina\localhost\ROOT\org\apache\jsp
C:\Users\16055\.IntelliJIdea2017.2\system\tomcat\Unnamed_javaProject_big14_4\work\Catalina\localhost\day12\org\apache\jsp
*/
JSP中的内置對象
常見面試題: 請寫出JSP的内置對象.
page(目前頁面), request, session(目前會話), application,
pageContext, response, config, out, exception
四大域容器:
page, request, session, application
推理法:
response, config
聯想法:
out, exception, pageContext
/*
1. .jsp底層是一個Servlet類.
2. .jsp檔案有 9 大内置對象.
*/
EL表達式
EL: Expression Language(表達語言的意思), 是為了使JSP寫起來更加簡單.
//如果使用自定義類型的值, 需要導包:
//<%@page import="com.itheima.domain.Product"%>
作用:
快速擷取域容器中的資料(request容器, context容器).
格式:
${域對象.類名.屬性名}
例如:
${requestScope.product.name}
項目的準備工作
) 完成資料表的建立及表資料的添加動作.
) 把要使用的jar包拷貝到: web-inf\lib中.
) 把c3p-config.xml檔案複制到src檔案夾中.
) 建立包:
com.itheima.utils
com.itheima.domain
com.itheima.web
com.itheima.service
com.itheima.dao
) 把JDBCUtils工具類拷貝到:utils包中.
) 建立JavaBean類.
登陸案例的分析
優化的地方:
如果登陸失敗:
使用請求轉發跳轉到 login.jsp頁面, 顯示錯誤資訊.
如果登陸成功:
使用重定向跳轉到首頁: index.jsp
擷取參數封裝到JavaBean中.
BeanUtils的原理(作用):
将map中的資料複制到指定的JavaBean中.
) 登陸注冊案例
準備工作:
) 複制jar包.
) 建立檔案夾(分層)
) 拷貝c3p-config.xml檔案 和 JDBCUtils工具類.
) 建立實體類.
登陸案例:
) 建立index.jsp頁面, 裡邊寫一句話<h1>歡迎登陸本網站</h1>
) 建立login.jsp頁面, 關聯 /項目名/loginServlet 這個servlet對象.
//裡邊寫的是form表單, 包裹<table>, 表格裡邊是: 使用者名, 密碼, 送出按鈕(登陸)
) 在com.itheima.web包下建立LoginServet類, 并在其doGet()方法中完成如下功能:
A: 擷取使用者通過浏覽器送出過來的資料.
request.getParameter("參數名");
B: 将使用者送出過來的資料封裝成: User對象.
//可以通過BeanUtils工具類實作.
User user = new User();
BeanUtils.populate(user, request.getParameterMap());
C: 調用Service層的功能, 将該對象傳輸過去校驗, 并接收傳回結果.
UserService us = new UserService();
User loginUser = us.login(user);
D: 編寫Service層的代碼.
UserDao ud = new UserDao();
User loginUser = ud.login(user);
E: 編寫Dao層的代碼.
//建立QueryRunner對象, 去資料庫查找該資料, 并傳回.
//結果集的處理方式用: BeanHandler
F: 在LoginServlet類中, 根據Service層的傳回結果做校驗.
User使用者存在:
//重定向頁面到: 首頁(index.jsp)
response.sendRedirect("/項目名/index.jsp");
User使用者不存在:
//給頁面一個回報資訊: 使用者名或者密碼錯誤
//版本一: 請求跳轉頁面到: 登陸頁面(login.jsp), 讓使用者接着登陸
//版本二: 請求跳轉頁面到: 注冊頁面(register.jsp), 讓使用者新增賬號
注冊案例: