Java web 中央控制器
mvc-servlet优化
beanMap相当于一个容器
http://localhost:8080/pro15/fruit.do?operate=edit&fid=2
在上面的链接中使用fruit.do找到Controller控制器.然后再通过
operate找到edit方法
在原本的方法之中我们发现在FruitController的各种方法比如update(),edit(),del(),add(),index()方法里面都有一个 response.sendRedirect("fruit.do");
重定向方法或者super.processTemplate("edit",request,response);
获取视图模板技术.所以我们打算将这两个方法抽离到DispatcherServlet当中去让中央控制器来实现跳转与实现.
这一节主要的优化就是将上面的两个方法抽离到中央控制器当中去
- 因为是中央控制器来调用这些方法所以我们可以将一个String返回给中央控制器.让中央控制器来接收.比如我们在update方法中返回redirect:fruit.do
private String update(HttpServletRequest request) throws ServletException {
//2.获取参数
String fidStr = request.getParameter("fid");
Integer fid = Integer.parseInt(fidStr);
String fname = request.getParameter("fname");
String priceStr = request.getParameter("price");
int price = Integer.parseInt(priceStr);
String fcountStr = request.getParameter("fcount");
Integer fcount = Integer.parseInt(fcountStr);
String remark = request.getParameter("remark");
//3.执行更新
fruitDAO.updateFruit(new Fruit(fid, fname, price, fcount, remark));
// response.sendRedirect("fruit.do");
return "redirect:fruit.do";//只负责返回这个字符串
}
- 我们在edit()方法之中返回了edit
private String edit(HttpServletRequest request) throws IOException, ServletException {
String fidStr = request.getParameter("fid");
if (StringUtil.isNotEmpty(fidStr)) {
int fid = Integer.parseInt(fidStr);
Fruit fruit = fruitDAO.getFruitByFid(fid);
request.setAttribute("fruit", fruit);
// super.processTemplate("edit", request, response);
return "edit";
}
return "error";
}
这样我们就将字符串返回给了中央控制器.同时如果我们都这样处理的话,这些类中的HttpServletResponse response,以及很多异常就不在需要了.所以是可以进行删除的
-
让我们继续回到中央控制器,来进行进一步的抽取工作.我们在service()方法中找到了通过反射调用的方法.首先对代码
Object returnObj = method.invoke(controllerBeanObj, request);
的返回值接受为一个object对象,然后将这个对象强制转换为String类型. -
然后开始进行处理,首先判断该字符串是不是以redirect:为开头,如果是以redirect:为开头的话,这种情况就是要求重定向的方法,就截取redirect:后面的部分,然后通过
response.sendRedirect(redirectStr);
来调用截取的字符串. -
如果该字符串不是以redirect:为开头的话那么就要求调用视图模板技术,我们让DispatcherServlet 继承 ViewBaseServlet这样的话就可以直接通过
uper.processTemplate(methodReturnStr, request, response);
直接调用方法@WebServlet("*.do") public class DispatcherServlet extends ViewBaseServlet { private Map<String, Object> beanMap = new HashMap<>(); public DispatcherServlet() { } public void init() throws ServletException { super.init(); try { InputStream inputStream = getClass().getClassLoader().getResourceAsStream("applicationContext.xml"); //1.创建DocumentBuilderFactory DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); //2.创建DocumentBuilder对象 DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); //3.创建Document对象 Document document = documentBuilder.parse(inputStream); //4.获取所有的bean节点 NodeList beanNodeList = document.getElementsByTagName("bean"); for (int i = 0; i < beanNodeList.getLength(); i++) { Node beanNode = beanNodeList.item(i); if (beanNode.getNodeType() == Node.ELEMENT_NODE) { Element beanElement = (Element) beanNode; String beanId = beanElement.getAttribute("id"); String className = beanElement.getAttribute("class"); Class controllerBeanClass = Class.forName(className); Object beanObj = controllerBeanClass.newInstance(); beanMap.put(beanId, beanObj); } } } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置编码 request.setCharacterEncoding("UTF-8"); //假设url是: http://localhost:8080/pro15/hello.do //那么servletPath是: /hello.do // 我的思路是: // 第1步: /hello.do -> hello 或者 /fruit.do -> fruit // 第2步: hello -> HelloController 或者 fruit -> FruitController String servletPath = request.getServletPath(); servletPath = servletPath.substring(1); int lastDotIndex = servletPath.lastIndexOf(".do"); servletPath = servletPath.substring(0, lastDotIndex); Object controllerBeanObj = beanMap.get(servletPath); String operate = request.getParameter("operate"); if (StringUtil.isEmpty(operate)) { operate = "index"; } try { Method method = controllerBeanObj.getClass().getDeclaredMethod(operate, HttpServletRequest.class); if (method != null) { //2.controller组件中的方法调用 method.setAccessible(true); Object returnObj = method.invoke(controllerBeanObj, request); //3.视图处理 String methodReturnStr = (String) returnObj; if (methodReturnStr.startsWith("redirect:")) { String redirectStr = methodReturnStr.substring("redirect".length());//获取redirect后面的内容 response.sendRedirect(redirectStr); } else { //这种情况返回的就是edit super.processTemplate(methodReturnStr, request, response); } } else { throw new RuntimeException("operate值非法!"); } } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }