Struts2開發前奏
我們在學習Struts之前,先來復習一下Servlet,眾所周知Servlet是JavaWeb的三大組件。我們發送一個請求,這個請求交給Servlet處理,Servlet將處理的結果返還給瀏覽器。每個Servlet對應一個URL-pattern。那麽有沒有這麽一種情況呢?我們訪問多個URL-pattern,這些URL-pattern具有共同的功能,那就是轉發到其它頁面,但是又不想寫那麽多Servlet,Servlet雖然是單例的,但是能少一個對象,對於JVM也是一種優化不是嗎,那麽有什麽辦法可以做到呢?如下圖
熟悉Servlet的前輩,可能一看就會知道只是不可能的,一個Servlet
- 創建Web項目struts2_1
- 創建test.jsp頁面,在頁面中建立三個URL請求鏈接
<body> <h3>入門路徑:</h3><br> <a href="${pageContext.request.contextPath }/UserServlet">userWorld</a><br> <a href="${pageContext.request.contextPath }/HelloServlet">helloWorld</a><br> <a href="${pageContext.request.contextPath }/CustomerServlet">addWorld</a><br> </body>
- 我們首先通過傳統的Servlet來實現:
UserServlet
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter pw = response.getWriter(); System.out.println("歡迎訪問UserServlet"); //pw.println("訪問一次,我就得寫一個Servlet!!!");請求轉發會將response攜帶的數據丟失 request.getRequestDispatcher("/success.jsp").forward(request, response); pw.flush(); pw.close(); }
Web.xml <servlet> <servlet-name>UserServlet</servlet-name> <servlet-class>cn.web.UserServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>UserServlet</servlet-name> <url-pattern>/UserServlet</url-pattern> </servlet-mapping>
@WebServlet("/HelloServlet") public class HelloServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter pw = response.getWriter(); System.out.println("歡迎訪問HelloServlet"); pw.println("訪問一次,我就得寫一個Servlet!!!!"); request.getRequestDispatcher("/error.jsp").forward(request, response); pw.flush(); pw.close(); }
@WebServlet("/CustomerServlet") public class CustomerServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter pw = response.getWriter(); System.out.println("歡迎訪問CustomerServlet"); pw.println("訪問一次,我就得寫一個Servlet!!!!!"); request.getRequestDispatcher("/add.jsp").forward(request, response); pw.flush(); pw.close(); }
Success.jsp <body> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx </body>
Error.jsp <body> 錯誤頁面 </body>
Add.jsp <body> 添加 </body>
我們在瀏覽器訪問test.jsp,然後可以訪問到這些Servlet,但是我們也註意到了,每一個URLpattern對應一個Servlet,這麽多請求造成了我們寫了很多Servlet,並且需要很多web.xml中的配置(Servlet3.0以後支持註解)。 那麽能否實現在web容器中只配置一次,就可以實現以上3個URL都可以跳轉到指定的頁面呢?
結論:可以使用過濾器實現:我們在過濾器中過濾所有的請求,進行判斷,如果是test.jsp那麽放行,否則就全部過濾操作。實際上根據上圖我們知道這樣一個對應關系,那就是一個請求對應一個Servlet,然後一個Servlet對應一個頁面,那麽我們創建兩個Map集合,一個放請求和類的對應,一個放返回值和頁面的對應.
- 創建一個Action接口,作為請求對應的類,它有三個實現類對應三個Servlet
package cn.filter;
public interface Action {
public String excute();
}
package cn.filter; public class HelloAction implements Action{ @Override public String excute() { System.out.println("訪問HelloAction!"); return "error"; } }
package cn.filter; public class UserAction implements Action { @Override public String excute() { System.out.println("訪問UserAction!"); return "success";//對應請求轉發的頁面名稱 } }
package cn.filter; public class CustomerAction implements Action { @Override public String excute() { System.out.println("訪問CustomerAction!"); return "add"; } }
- 創建Filter,然後對過濾進行操作
package cn.filter; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.DispatcherType; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebFilter( dispatcherTypes = {DispatcherType.REQUEST } , urlPatterns = { "/TestFilter", "/*" }) public class TestFilter implements Filter { //使頁面的訪問路徑對應Action類 Map<String, String> actionMap = new HashMap<>(); //使對應的action返回值對應相應的jsp頁面 Map<String, String> returnMap = new HashMap<>(); //web容器啟動時執行 public void init(FilterConfig fConfig) throws ServletException { actionMap.put("/UserServlet", "cn.filter.UserAction"); actionMap.put("/HelloServlet", "cn.filter.HelloAction"); actionMap.put("/CustomerServlet", "cn.filter.CustomerAction"); returnMap.put("success", "/success.jsp"); returnMap.put("add", "/add.jsp"); returnMap.put("error", "/error.jsp"); } public void destroy() { // TODO Auto-generated method stub } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request= (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; //獲取請求Servlet路徑 String path = request.getServletPath(); if(path != null && path.equals("/test.jsp")){ chain.doFilter(request, response); return; }//如果是test.jsp那麽放行 //如果不是test.jsp頁面,那就進行過濾操作 //獲取訪問的action路徑 String actionClass = actionMap.get(path); try { //通過反射獲取Action類的對象 Action action = (Action) Class.forName(actionClass).newInstance(); //獲取返回的頁面名稱 String returnValue = action.excute(); //利用Action類的返回值,獲取所對應的頁面 String page = returnMap.get(returnValue); //轉發到相應頁面 request.getRequestDispatcher(page).forward(request, response); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
我們使用瀏覽器進行測試,發現,這次我們的請求沒有經過Servlet,而是通過Action類處理了(對比前後兩次控制臺打印輸出可以看出),通過過濾器,我們簡單避免了web.xml中的反復配置.上面其實就是一個簡單的Struts2實現:
Struts2開發前奏