讓Servlet支持REST風格的url

前言

Servlet自從上了3.0版本以後,用起來已是至關舒服了。註解的加入,讓你基本能夠拋棄web.xml,零配置寫web。 java

不過,用了以後,仍是有些遺憾。就是REST風格URL的支持。好久以前用過SpringMVC以後,對於REST風格的URL就喜歡得不得了。上網查了下,發現了個項目servletrest,項目託管在google code上:http://code.google.com/p/servletrest/ git

源碼就幾個類,很快就看完了,也試用了一下。確實是能夠支持,可是bug也比較明顯。最明顯的一個就是,支持了REST的servlet,是沒法獲取到ServletContext。緣由是servletrest在初始化servlet的時候,沒有調用servlet的init方法,即沒有初始化ServletConfig。還有一個問題,就是獲取URI中的參數時,太過繁瑣。並且基於第一個問題,參數實際上是獲取不到的。 web

花了點時間,從新寫了個新的實現,叫summer-restful。主要做用,就是讓普通的servlet支持rest風格的url,而且也修復中servletrest的明顯bug。 restful

實現原理

定義一個Filter。 app

init

在容器啓動的時候,對全部已經過註解標記的servlet進行掃描驗證。這裏提到的註解是咱們自定義的,叫@SummerServlet,參數有兩個,name,UrlPatterns。符合規則的servlet初始化,並用他們的urlPatterns做爲該servlet的key,存入一個Map中進行維護。說明下,咱們自定義的@SummerServlet中的urlPatterns,跟原生servlet的UrlPatterns有些區別。自定義的urlPatterns中,是支持相似這種格式的url:/*/detail/* 的,也經過這裏,讓普通的servlet支持了REST風格的url。 jsp

doFilter

過濾器攔截全部請求。分析請求的servletPath,跟Map中的key進行比對,若匹配,則返回key對應的servlet,而且會注入url中的參數到request;不然,執行默認的動做。 ide

使用

有兩個步驟。 google

配置全局的Filter

經過web.xml配置的話,例子以下 url

<filter>
	<filter-name>summerFilter</filter-name>
	<filter-class>cn._5iurl.restful.SummerFilter</filter-class>
	<init-param>
		<param-name>servletPackage</param-name>
		<param-value>cn._5iurl.test.servlet</param-value>
	</init-param>
</filter>
<filter-mapping>
	<filter-name>summerFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>
也能夠經過註解來配置。這時候須要新建一個Filter繼承SummerFilter,例子以下
@WebFilter(filterName="restFilter", initParams=@WebInitParam(name="servletPackage", value="cn._5iurl.test.servlet"), urlPatterns="/*")
public class CRestFilter extends SummerFilter{

}

配置Servlet

在須要Rest風格URL的servlet類中,再也不配置到xml或者用@WebServlet註解,而是改用@SummerServlet註解。例子以下 spa

@SummerServlet(name="detailServlet", urlPatterns="/*/detail/*")
public class DetailServlet extends HttpServlet{

	private static final long serialVersionUID = 8268477143225755822L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String category = (String)req.getAttribute("p0");
		String id = (String)req.getAttribute("p1");
		
		req.setAttribute("id", id);
		req.getRequestDispatcher("/WEB-INF/www/"+category+"/detail.jsp").forward(req, resp);
	}

}

獲取URL中的參數

獲取url中的參數。啥意思呢?仍是上面的例子。假設用戶訪問的是:http://localhost:8015/cms/user/detail/1,能夠看到,是符合咱們定義的url規則:

/*/detail/*
那咱們怎麼獲取中隱藏其中的參數值:user和1呢。仍是看例子
String category = (String)req.getAttribute("p0");
String id = (String)req.getAttribute("p1");

源碼

源碼已經放在Git@OSC上面,有興趣能夠看下:http://git.oschina.net/cevin15/summer-restful

相關文章
相關標籤/搜索