我看了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了,所以我全部沒寫
沒有留言:
張貼留言