JavaWeb 多個Servlet整合優化
由于一個Servlet只能接收一個地址的http請求,如果系統復雜度提高,就會有很多Servlet類,例如,對銷售系統來說,可能會有OederInsertServlet, OrderUpdateServlet, OrderDeleteSerlvet, OrderQueryServlet等多個OrderServlet來處理訂單這一種業務,看著就會很雜,如下圖,同時如果請求前或請求后有一些處理的話,對應的方法就需要寫很多次,維護難度也會提升


優化-同一個模塊多個操作
可以只用一個Servlet接收Order這一種業務所有的介面,通過在介面添加類似operate的標志引數對不同的操作進行區分,

代碼示例
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String operate = req.getParameter("operate");
if (null == operate){
doRequireOperate(req, resp);
}
SUtils.logInfo("呼叫前操作");
System.out.println("獲取到的操作名為:" + operate);
switch (operate){
case "insert":{
System.out.println("do insert");
doInsertOperate(req, resp);
break;
}
case "update":{
System.out.println("do update");
doUpdateOperate(req, resp);
break;
}
case "delete":{
System.out.println("do delete");
doDeleteOperate(req, resp);
break;
}
case "query":{
System.out.println("do query");
doQueryOperate(req, resp);
break;
}
default:{
System.out.println("error");
}
SUtils.logInfo("呼叫后操作");
}
}
測驗
本地訪問 http://localhost:8080/mvc/ver1?operate=insert
服務器日志輸出如下

優化-使用反射
目前,對業務的操作是通過switch-case進行匹配處理的,如果運算元量增多則需要多增加case陳述句,代碼就會顯得臃腫,可以考慮通過反射呼叫具體的執行方法
示例代碼
下面展示的是核心代碼
String operate = req.getParameter("operate");
System.out.println("獲取到的操作名為:" + operate);
// 通過反射獲取對應的方法
// 假定方法名均為do+${operate}+operate,駝峰,如operate為insert時,要呼叫的方法就是doInsertOperate
// Method[] methods = this.getClass().getMethods();
char[] chars = operate.toCharArray();
chars[0] -= 32;
String methodName = "do" + String.valueOf(chars) + "Operate";
// Optional<Method> targetMethod = Arrays.stream(methods).filter(m -> m.getName().equals(methodName)).findFirst();
try {
Method taragetMethod = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
taragetMethod.setAccessible(true);
taragetMethod.invoke(this, req, resp);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
優化-多個業務模塊引入組態檔
當業務增多時,需要在每個業務里面單獨寫反射呼叫方法較為復雜,可以也通過反射來呼叫業務模塊,再執行對應的方法,同時可以引入xml組態檔,來匹配對應的業務模塊

代碼示例
@WebServlet("/mvc/ver3/*")
public class Ver3Servlet extends HttpServlet {
private Map<String, Object> beanControllerMap = new HashMap<>();
// 初始化,讀取xml檔案配置controller
@Override
public void init() throws ServletException {
// super.init();
System.out.println("aaa");
try (InputStream beanConfigs = this.getClass().getClassLoader().getResourceAsStream("MvcVer3Config.xml")) {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document beanDocument = documentBuilder.parse(beanConfigs);
Element documentElement = beanDocument.getDocumentElement();
NodeList nodeList = beanDocument.getDocumentElement().getElementsByTagName("bean");
for (int i = 0; i < nodeList.getLength(); i++) {
if (Node.ELEMENT_NODE == nodeList.item(i).getNodeType()){
Element item = (Element) nodeList.item(i);
String beanName = item.getAttribute("id");
String className = item.getAttribute("class");
Class<?> beanClass = Class.forName(className);
Object bean = beanClass.getDeclaredConstructors()[0].newInstance();
beanControllerMap.put(beanName, bean);
}
}
// documentElement.get
} catch (IOException | ParserConfigurationException | SAXException | ClassNotFoundException |
InvocationTargetException | InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
System.out.println("aaa");
}
// 讀取路徑值,獲取對應的controller物件,反射呼叫對應方法
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String servletPath = req.getPathInfo();
System.out.println(servletPath);
String controllerName = servletPath.split("/")[1];
String operateName = servletPath.split("/")[2];
operateName = "do" + getFirstUpper(operateName) + "Operate";
Object targetController = beanControllerMap.get(getFirstUpper(controllerName));
Method targetMethod;
try {
targetMethod = targetController.getClass().getDeclaredMethod(operateName, HttpServletRequest.class, HttpServletResponse.class);
} catch (NoSuchMethodException e) {
ErrorResponse(req, resp, e.getMessage());
e.printStackTrace();
return;
}
try {
targetMethod.invoke(targetController, req, resp);
} catch (IllegalAccessException | InvocationTargetException e) {
ErrorResponse(req, resp, e.getMessage());
e.printStackTrace();
return;
}
System.out.println("呼叫結束");
}
private void ErrorResponse(HttpServletRequest req, HttpServletResponse resp, String errorString) throws IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
out.println("<HTML lang=\"ch\">");
out.println(" <HEAD><TITLE>delete Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print("所訪問的模塊不存在<br>");
out.print(errorString);
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
System.out.println("所訪問的模塊不存在");
}
private String getFirstUpper(String s){
char[] chars = s.toCharArray();
chars[0] -= 32;
return String.valueOf(chars);
}
}
解決多個業務配置問題,通過讀取組態檔初始化Servlet,在收到請求時,取到對應的Servlet進行處理
組態檔示例
<?xml version="1.0" encoding="utf-8" ?>
<beans>
<bean id="A" />
<bean id="B" />
<bean id="C" />
<bean id="D" />
</beans>
測驗
啟動專案,訪問對應路徑
http://localhost:8080/mvc/ver3/a/query

頁面回應

呼叫成功
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/500295.html
標籤:Java
上一篇:fastjson 使用方法大全
