創建BaseServlet的必要性
如果不創建BaseServlet,現在我們只要實現一個功能,我們就需要創建一個servlet!
例如:用戶模塊(登錄,注冊,退出錄,激活,發送郵件等等功能) 也就是說,我們必須要創建一些系列的Servlet:UserLoginServlet - 登錄功能!? UserRegisterServlet ->注冊功能!
總之,只要你實現一個功能,你就得創建-個servlet!
這種情況會有兩個弊端!
1.創建大量的servlet!servet實例-> web容器(tomcat)管理!有大量的servlet實例必然會占有更大的
運行內存!會間接的拖慢web容器的速度!
2.servlet 他的service(dogel/dopost)方法是一個多線程方法!也就說理論上說!一個servlel可以處理很多次請求,也可以并發的 處理請求,一個servlel能力很強!? 但是只對應一個功能!你不覺得浪費么?
Baseservlet我們想解決的問題就是!簡化和優化servlet的創建和數量!
Baseservlet的實現思路
1.為什么一個servlet只對應一個功能!
一個serviet被訪問以后,只會有一個方法被調用,通常我們習慣一個方法中寫一個套業務邏輯!
一個servlet對應一個方法對應一個業務功能!
2.分析Baseservlet實現的思路
1.讓一個servet對應多個方法就好了!? 每個方法都實現一個業務邏輯!
2.具體的實現思路
步驟1:在一個servlel聲明多個處理業務邏方法!
步驟2:在每次訪問servlet的時候在路徑上添加一個標識!? 標識(method)用于判斷要訪問具體業務邏輯方法!
步驟3:當每次請求到 doget/dopost/service方法的時候,判斷參數的標識,調用對應的業務邏輯方
法即可!
Baseservlet的實現
1.實現基本的Baseservlet
步驟1:Baseservlet繼承httpservlet類,重寫其service方法
步驟2:在service方法中獲得具體要執行的方法如(登錄,注冊等),在執行
2.優化方法調用
利用標識符的字符串和方法名相同!
我們可以利用反射的技術!調用對應的執行方法!
避免了大量的if或switch判斷!
當有新的方法出現的時候!也不需要額外的添加判斷方法!
3.優化多Servlet實現
實現思路:
我們創建一個BascServlet類,讓他去繼承HttpServlet!BaseServlet中寫service方法!
在service寫 1.獲取標識 2.反射調用業務邏輯
每個模塊對應的Controller只需要集成Baseservlet即可!
HttpServlet->BaseServlet->模塊的Controller
4.優化返回值問題
每個方法都要進行響應
響應的方式固定: 轉發?重定向 返回字符串 返回字節流
如果在每個方法寫轉發和重定向和返回字符串的語法比較繁瑣!
我們可以統一在Baseservlet進行處理!
操作:
步驟1:將方法的返回值改成字符串即可!
步驟2: 根據約定的內容,添加特殊的標識!
例如:轉發“forward: 路徑”
步驟3:BaseServlet集中處理
執行方法!獲取返回值!進行非空判斷!
截取標識!進行轉發重定向或者寫回字符串處理!
好處:簡化方法的響應的操作!
注意:沒有管返回字節!
返回字節!我們只需要將方法的返回值改成void!
整體實現代碼樣例
BaseServlet代碼
package controller;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;import static utils.Constants.*;public class BaseServlet extends HttpServlet {@Overridepublic void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {try {//防止亂碼req.setCharacterEncoding("UTF-8");res.setCharacterEncoding("UTF-8");res.setContentType("text/html;charset=utf-8");//得到方法的名稱String m=req.getParameter(TAG);if(m==null||m.isEmpty()){m=INDEX;}Class<? extends BaseServlet>clazz=this.getClass();//獲取要執行的方法Method method = clazz.getDeclaredMethod(m, HttpServletRequest.class, HttpServletResponse.class);method.setAccessible(true);//得到返回值再進行判斷是什么操作:轉發 重定向 字符串(json)Object result = method.invoke(this, req, res);if(result!=null){String path=(String) result;if(path.startsWith(FORWARD)){ //轉發System.out.println("執行了轉發");path=path.replace(FORWARD,"");req.getRequestDispatcher(path).forward(req,res);}else if(path.startsWith(REDIRECT)){ //重定向System.out.println("執行了重定向");path=path.replace(REDIRECT,"");res.sendRedirect(path);}else{ //字符串(json)res.getWriter().println(path);}}} catch (Exception e) {e.printStackTrace();System.out.println("BaseServlet異常處理");}}//方法為空public String index(HttpServletRequest req, HttpServletResponse res){return FORWARD+"路徑";}
}
Usercontroller類代碼
package controller;import com.google.gson.Gson;
import pojo.Result;
import pojo.student;import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/Login")
public class UserController extends BaseServlet {//登錄功能public String login(HttpServletRequest req,HttpServletResponse res) throws IOException {String account = req.getParameter("account");String password = req.getParameter("password");System.out.println(account);System.out.println(password);//設置響應格式為jsonres.setContentType("application/json");// 創建一個示例對象Result dataObject = new Result(1,"json請求測試",new student("張三",14));// 將對象轉換為 JSON 字符串Gson gson = new Gson();String json = gson.toJson(dataObject);System.out.println(json);return json;}
}
工具類
package utils;public class Constants {public static final String TAG="method";public static final String FORWARD="forward:";public static final String REDIRECT="redirect:";public static final String INDEX="index";
}
測試
前端發送請求:
后端響應數據:
?前端響應數據:
json格式字符串