1. 程式人生 > >Servlet做Controller,實現一個類處理多個請求

Servlet做Controller,實現一個類處理多個請求

        傳統的Servlet都是一個請求對應一個Servlet。

        例子如下:

請求:http://localhost:8080/ServletTest/Login

web.xml配置:

	<servlet>
		<servlet-name>Regist</servlet-name>
		<servlet-class>cn.xiaol.web.servlet.before.RegistServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name
>
Regist</servlet-name> <url-pattern>/Regist</url-pattern> </servlet-mapping>

Servlet程式碼:

public class RegistServlet extends HttpServlet {
	@Override
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 重定向到regist頁面
response.sendRedirect(request.getContextPath() + "/regist.jsp"); } // 在url上面測試是用Get方法請求,所以需要重寫doGet()讓它呼叫doPost()。 // 也可以把doPost()中的程式碼直接寫在doGet() @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } }

        所以當web專案很大時,請求也就很多,web.xml的配置量也就跟著變大,各種Servlet類爆增。

        於是我們可以通過反射的方式,將一類方法放在一個Servlet類中。例如User的增刪改查請求可以放在一個UserServlet裡面處理。

        下面做一個例子,將login和regist請求放在一個TestServlet中處理。但是在此之前需要先寫一個父類BaseServlet,裡面有一個利用反射原理實現的通過方法名呼叫對應方法的方法。挺繞口的。意思是這個BaseServlet繼承HttpServlet,然後重寫service()方法,因為每一個請求Servlet都會呼叫一次service方法,而這個service方法通過反射和請求中帶的method引數可以呼叫自己類中對應的方法。

        一個完整的流程就是:

        第一步:請求http://localhost:8080/ServletTest/TestServlet?method=login

        第二步:子類TestServlet繼承了BaseServlet,所以也繼承了父類的service方法。一次請求觸發一次service方法,於是service方法通過反射呼叫了TestServlet中的login方法。

        第三步:login方法處理完返回處理結果。

下面是例子:

請求:http://localhost:8080/ServletTest/TestServlet?method=login

1、http://localhost:8080/ServletTest/TestServlet是我們要請求的Servlet

2、method=login是我們要請求的Servlet中的方法

web.xml配置:

	<servlet>
		<servlet-name>TestServlet</servlet-name>
		<servlet-class>cn.xiaol.web.servlet.after.TestServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>TestServlet</servlet-name>
		<url-pattern>/TestServlet</url-pattern>
	</servlet-mapping>

BaseServlet程式碼:

package cn.xiaol.web.servlet.after;

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

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class BaseServlet extends HttpServlet {

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 1、獲得方法名稱
		String methodName = request.getParameter("method");
		Method method = null;

		// 2、通過方法名和方法所需要的引數獲得Method物件
		try {
			method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
		} catch (Exception e) {
			throw new RuntimeException("呼叫的方法:" + methodName + "不存在", e);
		}

		// 3、通過Method物件呼叫方法
		try {
			String result = (String) method.invoke(this, request, response);
			if (result != null && result.trim().length() > 0) {// 如果返回的result不為空
				int index = result.indexOf(":");// 獲得第一個冒號的位置
				if (index == -1) {// 如果沒有冒號,就使用轉發
					request.getRequestDispatcher(result).forward(request, response);
				} else {// 如果有冒號
					String start = result.substring(0, index);// 擷取字首
					String path = result.substring(index + 1);// 擷取路徑
					if (start.equalsIgnoreCase("f")) {// 字首為f表示使用轉發
						request.getRequestDispatcher(path).forward(request, response);
					} else if (start.equalsIgnoreCase("r")) {// 字首為r表示使用重定向
						response.sendRedirect(request.getContextPath() + path);
					}
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

TestServlet程式碼:

package cn.xiaol.web.servlet.after;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @date 建立時間:2016年10月15日 上午11:59:25
 */
public class TestServlet extends BaseServlet {

	public String login(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("login");
		return "/login.jsp";
	}

	public String regist(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("regist");
		return "/regist.jsp";
	}
}

        當我們需要增加一個有關Test的請求時,我們可以直接在TestServlet中新增相關方法,而不比再寫一個Servlet類。但是請求的時候記得要帶上method方法引數。

        下面是Demo的完整程式碼