我看了API後,理解如下:
HttpServletResponse的sendRedirect
參數不是「/」開頭,為相對路徑
是「/」開頭,表示ServletContext路徑
如果resp已commit,會拋出IllegalStateException
1.瀏覽器req給servlet
2.servlet將設定的路徑回傳給瀏覽器
3.瀏覽器依這個路徑再req
4.servlet再回傳
所以有兩次的req
因為是resp,所以網址會改變
ServletRequest的getRequestDispatcher取得javax.servlet的RequestDispatcher
有以下兩個方法
1.forward(主控權是別人)
轉發給servlet、JSP、HTML
如果resp已commit,會拋出IllegalStateException
2.include(主控權是自己)
將servlet、JSP、HTML包括到自己的servlet
所包含的servlet不能改變resp狀態碼或設定header,如果有改變將被忽略。
這兩個方法都是req,所以網址不會改變
※web.xml
<filter> <filter-name>zzz</filter-name> <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>zzz</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
※LoginServlet.java
@WebServlet(urlPatterns = { "/xxx" })
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String enc = super.getServletConfig().getInitParameter("encoding");
resp.setContentType("text/html; charset=" + enc);
String username = req.getParameter("username");
String password = req.getParameter("password");
if (username.trim().equals("aaa") && password.trim().equals("bbb")) {
String fruit = req.getParameter("ooo");
String[] xxx = req.getParameterValues("xxx");
List<String> tl = Arrays.asList("ttt", "lll");
if (xxx != null) {
for (String s : req.getParameterValues("xxx")) {
// 老虎獅子吃香蕉
if (tl.contains(s) && "bbb".equals(fruit)) {
// forward 轉發給設定的servlet、jsp、HTML,主導權也送出去
System.out.println("before:" + req.getServletPath());
req.getRequestDispatcher("/abc").forward(req, resp);
// req.getRequestDispatcher("/WEB-INF/success.jsp").forward(req,
// resp);
System.out.println("after:" + req.getServletPath());
// include包含設定的servlet、jsp、HTML,主導權並沒有送出去
// System.out.println("before:" + req.getServletPath());
// req.getRequestDispatcher("/abc").include(req, resp);
// req.getRequestDispatcher("/WEB-INF/success.jsp").include(req,
// resp);
// System.out.println("after:" + req.getServletPath());
break;
} else {
if ("rrr".equals(s)) {
resp.sendRedirect(req.getContextPath() + "/fail.jsp");
System.out.println("456");// 有執行到
} else {
continue;
}
}
}
} else {
resp.sendRedirect("http://www.google.com");
}
} else {
// sendRedirect是兩次的request,所以req.setAttribute抓不到
// req.setAttribute("fail", "帳密錯誤");
req.getSession().setAttribute("fail", "帳密錯誤");
resp.sendRedirect(req.getContextPath() + "/login.jsp");
}
}
}
※sendRedirect也可以直接呼叫一般的網址,而WEB-INF是特殊的資料夾,resp當然不能拿來用
※include、forward 差在 getRequestDispatcher 是另一個 servlet 時
forward 後,主導權不在,include 還在
所以 forward 的 response 不會執行;而 include 跳轉的頁面返回後,繼續執行 response
假設有 ServletA 和 ServletB
使用 forward 跳頁後就不管了
使用 include 跳頁執行完後,會再回來繼續執行其他的部分
※TestAaa.java
@WebServlet(urlPatterns = { "/abc" })
public class TestAaa extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("in:" + req.getServletPath());// include進來是xxx,forward進來是abc
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get接收");
}
}
※include和forward呼叫這支servlet時,會發現不一樣的地方
※如果login.jsp呼叫doGet,那abc也會呼叫doGet
※login.jsp
<form action="xxx" method="post">
<font color="red">${fail}</font><br />
使用者:<input type="text" name="username" value="user" /><br />
密碼:<input type="password" name="password" value="pass" /><br />
登入密語:
<input type="checkbox" name="xxx" value="ttt" />tiger
<input type="checkbox" name="xxx" value="rrr" />rabit
<input type="checkbox" name="xxx" value="lll" />lion<br />
<input type="radio" name="ooo" value="aaa" />apple
<input type="radio" name="ooo" value="bbb" />banana
<input type="radio" name="ooo" value="ppp" />pineapple<br />
<input type="reset" />
<input type="submit" />
</form>
※fail.jsp和success.jsp自己隨便寫
※有些書用servlet寫jsp,可是現在工作時都在用MVC,所以現在應該很少人這樣寫了,檢核使用者輸入的值也都是前端用jQuery、ajax了,所以我全部沒寫
沒有留言:
張貼留言