引入
前面的小小水果摊 虽然完成了全部功能,但是整体结构比较复杂,一个页面对应的请求需要多个Servlet进行响应,代码量重复复杂。
优化1
将所有的代码集成为私有函数,页面都对同一个fruit.do进行响应,但是同时传入一个operate操作符,用于判断对页面的操作,同时利用反射,优化调用函数的代码量,将所有的反射方法调用到dispatchServlet中,同时将一个负责判断转发的操作交给该类进行,而fruitservlet变为控制器,只保存一些调用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| @WebServlet("*.do") public class DispatcherServlet extends ViewBaseServlet {
private Map<String ,Object> map=new HashMap<>(); @Override public void init() { super.init(); try {
InputStream inputStream=getClass().getClassLoader().getResourceAsStream("applicationContext.xml"); DocumentBuilderFactory documentBuilderFactory= DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder(); Document document= documentBuilder.parse(inputStream); 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 beamId=beanElement.getAttribute("id"); String className=beanElement.getAttribute("class"); Class clas=Class.forName(className); Object beanObj=clas.newInstance();
map.put(beamId,beanObj); } } } catch (ParserConfigurationException | ClassNotFoundException | InstantiationException | IllegalAccessException | SAXException | IOException e) { e.printStackTrace(); }
}
@Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException{ req.setCharacterEncoding("UTF-8"); String servletPath=req.getServletPath(); int lastslash=servletPath.lastIndexOf("/")+1; int lastpoint=servletPath.lastIndexOf("."); servletPath=servletPath.substring(lastslash,lastpoint);
Object controllerObj=map.get(servletPath); System.out.println(servletPath); String operate =req.getParameter("operate"); if (operate == null | Objects.equals(operate, "")) { operate="inquire"; } try { Method method=controllerObj.getClass().getDeclaredMethod(operate,HttpServletRequest.class); method.setAccessible(true); Object obj=method.invoke(controllerObj,req); String meth=(String) obj; if (meth.startsWith("sendRedirect")){ String sendRedStr=meth.substring("sendRedirect".length()); resp.sendRedirect(sendRedStr); } else { super.processTemplate(servletPath+"/"+meth,req,resp); } } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); throw new RuntimeException("operate非法"); }
} }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <xml version="1.0" encodeing="utf-8">
<beans> <bean id="fruit" class="com.zss.myssm.myspringmvc.controller.FruitController"/>
</beans>
</xml>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| private String inquire(HttpServletRequest req) throws IOException { req.setCharacterEncoding("UTF-8"); int pageNum; String pagePer=req.getParameter("pagePer"); if (pagePer == null|pagePer==""){ pagePer="1"; } pageNum=Integer.parseInt(pagePer); List<Fruit> list=fruitDAO.inquFruit(new Fruit(),pageNum); int lastPageNum=((fruitDAO.getColumn()-1)/5)+1; HttpSession session=req.getSession(); session.setAttribute("lastPage",lastPageNum); session.setAttribute("pageNo",pageNum); session.setAttribute("fruitList",list); return "FruitShow"; }
|
优化2
虽然我们将这些方法进行了集成,但是可以发现,我们的fruitcontroller中仍旧还是有重复的的参数需要获取,而且每一个参数都不相同,假如我们有user,还需要给他单独设置参数,那么就不能在设置转发方法的时候,同时完成参数的转发吗???
于是我们更改service方法部分代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| try { Method[] methods = controllerObj.getClass().getDeclaredMethods(); for (Method method : methods) {
if (method.getName().equals(operate)) { Parameter[] parameters = method.getParameters(); Object []objectParameters=new Object[parameters.length]; for (int i=0;i<objectParameters.length;i++ ){ Parameter parameter=parameters[i]; if ("req".equals(parameter.getName())){ objectParameters[i]=req; continue; } String parameValue=req.getParameter(parameter.getName()); objectParameters[i]=parameValue; } method.setAccessible(true); Object obj = method.invoke(controllerObj, objectParameters); String meth = (String) obj; if (meth.startsWith("sendRedirect")) { String sendRedStr = meth.substring("sendRedirect".length()); resp.sendRedirect(sendRedStr); } else { super.processTemplate(servletPath + "/" + meth, req, resp); } }
} } catch (InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); }
|