天天看點

對 Servlet 的改進--------Struts2 引入

改進 Servlet

  通過上一篇部落格:Servlet 的詳解 http://www.cnblogs.com/ysocean/p/6912191.html,我們大緻知道了 Servlet 的基本用法。但是稍微分析一下 Servlet 的用法,我們還是發現其存在很多缺點:

  ①、一個請求對應一個 Servlet,即每一個請求我們都需要在 web.xml 檔案中配置映射。如果項目大,請求很多,那麼會造成 web.xml 很大,很難維護。

  ②、即便在好幾個請求對應一個 Servlet,即在 service() 方法中,通過 if--else 語句來判斷執行的代碼塊。那這樣就會造成 service() 方法很擁擠。

  ③、一個項目隻存在一個 web.xml 檔案,如果一個項目是多人開發,那麼整合代碼開發過程中會有很多問題。不适合團隊開發。

  ④、Servlet中doGet方法和doPost方法中的兩個參數reqeust,response擁有嚴重的容器依賴性。

  ⑤、如果頁面上表單中的元素比較複雜,則在Servlet的方法中擷取表單元素的資料比較繁瑣。

  ⑥、Servlet是單線程的,隻要在Servlet中的聲明一個執行個體變量,那麼該變量在多線程通路時就會有線程安全問題。

  ⑦、在Servlet中處理異常,如果Servlet中有N個方法,則這N個方法必須都要try--catch。因為子類抛的異常不能大于父類。

那麼接下來我們用一個例子來解決上面的問題。

  1、建立一個 Web 工程,名為 ServletIncreased。并在 web.xml 中配置一個過濾器 ServletFilter,這個過濾器會過濾所有以 .do 結尾的 URL 連結

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
  http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id="WebApp_ID" version="3.0">
   
  <filter>
    <filter-name>ServletFilter</filter-name>
    <filter-class>com.ys.filter.ServletFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>ServletFilter</filter-name>
    <url-pattern>*.do</url-pattern>
  </filter-mapping>
  
</web-app>
      

  2、建立一個 UserServlet,裡面有兩個方法,insert()和update()方法,調用 insert() 方法會跳轉到 insert.jsp 頁面,調用 update() 方法會調轉到 update.jsp 頁面

package com.ys.servlet;

import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class UserServlet {
	//使用者插入方法
	public void insert(HttpServletRequest req,HttpServletResponse resp) throws Exception, IOException{
		req.getRequestDispatcher("insert.jsp").forward(req, resp);
	}
	
	//使用者更新方法
	public void update(HttpServletRequest req,HttpServletResponse resp) throws Exception, IOException{
		req.getRequestDispatcher("update.jsp").forward(req, resp);
	}
	
}
      

  3、建立一個配置檔案類,裡面存放配置檔案的關系,通過一個 Map 集合,儲存 Servlet 的類名和全類名

package com.ys.config;

import java.util.HashMap;
import java.util.Map;

public class ServletNameConfig {
	//定義一個 Servlet 配置檔案,Map<key,value>
	//key:表示 Servlet 的類名
	//value:表示 Servlet 類名的全稱
	public static Map<String, String> servletMap = new HashMap<>();
	
	static {
		servletMap.put("UserServlet", "com.ys.servlet.UserServlet");
	}

}
      

  4、回頭看我們配置的過濾器,ServletFilter

package com.ys.filter;

import java.io.IOException;
import java.lang.reflect.Method;

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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ys.config.ServletNameConfig;

public class ServletFilter implements Filter{
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse resp = (HttpServletResponse) response;
		
		String reqURL = req.getRequestURI(); //  /ServletIncreased/UserServlet.do
		String[] strs = reqURL.split("/");
		//定義 Servlet 的全類名
		String servletAllName = null;
		if(strs[2] != null){
			//得到 請求路徑的 servlet 類名
			String servletName = strs[2].substring(0, strs[2].indexOf("."));
			//根據擷取的 Servlet 類名,由配置檔案 ServletNameConfig 裡面的map 得到 全類名
			servletAllName = ServletNameConfig.servletMap.get(servletName);
		}
		//擷取請求方法名
		String methodName = req.getParameter("method");
		System.out.println(servletAllName+"---"+methodName);
		try {
			//通過反射調用執行方法
			Class obj = Class.forName(servletAllName);
			Method method = obj.getDeclaredMethod
					(methodName, HttpServletRequest.class,HttpServletResponse.class);
			method.invoke(obj.newInstance(), req,resp);
		} catch (Exception e) {
			e.printStackTrace();
		}		
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}
	@Override
	public void destroy() {
	}

}
      

  整體的項目結構如下:

  

對 Servlet 的改進--------Struts2 引入

然後将整個項目釋出到 tomcat 伺服器運作,釋出的方法可以如下:

  http://www.cnblogs.com/ysocean/p/6893446.html

然後我們在浏覽器輸入如下連結:http://localhost:8080/ServletIncreased/UserServlet.do?method=insert

  那麼就會調用 UserServlet 的 insert 方法,進而跳轉到 insert.jsp 頁面

對 Servlet 的改進--------Struts2 引入

如果我們在浏覽器輸入如下連結:将 insert 改為 update

   http://localhost:8080/ServletIncreased/UserServlet.do?method=update

那麼就會調用 UserServlet 的update 方法,進而調轉到 update.jsp 頁面

對 Servlet 的改進--------Struts2 引入

分析:這個改進主要是配置了一個過濾器,然後通過過濾器的 doFilter() 方法,我們可以通過請求路徑獲得請求URL,然後通過字元串的截取方法得到 Servlet 的名稱。通過配置檔案儲存的 Servlet類名和全類名的對應關系得到全類名;然後利用反射的原理,通過 invoke() 方法來動态調用方法。這裡我們并沒有解決上面所有的問題,比如嚴重的容器依賴性我們這裡還有。如果想真正解決,請看下一篇部落格:Struts2 詳解

作者:IT可樂

出處:http://www.cnblogs.com/ysocean/

資源:微信搜【IT可樂】關注我,回複 【電子書】有我特别篩選的免費電子書。

本文版權歸作者所有,歡迎轉載,但未經作者同意不能轉載,否則保留追究法律責任的權利。