前面与你们分享了几篇在 Smart 中有关数据持久层的重构解决方案,今天咱们把目光集中到 MVC 框架上来吧。众所周知,Smart 是一款看起来还不错的轻量级 Java Web 框架,若是连 MVC 框架都很差用或者不容易扩展,那岂不是本身给本身找麻烦吗?前端
当我刚说完上面这句话时,咱们团队中的一名帅哥 快枪手 同窗,他指出了我在 Smart MVC 上的严重问题,请容许我再次感谢个人小伙伴快枪手,感谢他深厚的功力与犀利的言语!解救我于水火之中,让我学到了不少,受益不浅。java
咱们先来看看 Smart MVC 中一个很是重要的类 —— 前端控制器,它就是 DispatcherServlet
,重构前是这样的:git
<!-- lang: java --> @WebServlet(urlPatterns = "/*", loadOnStartup = 0) public class DispatcherServlet extends HttpServlet { private static final Logger logger = LoggerFactory.getLogger(DispatcherServlet.class); @Override public void init(ServletConfig config) throws ServletException { // 初始化相关配置 ServletContext servletContext = config.getServletContext(); UploadHelper.init(servletContext); } @Override public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 设置请求编码方式 request.setCharacterEncoding(FrameworkConstant.UTF_8); // 获取当前请求相关数据 String currentRequestMethod = request.getMethod(); String currentRequestPath = WebUtil.getRequestPath(request); logger.debug("[Smart] {}:{}", currentRequestMethod, currentRequestPath); // 将“/”请求重定向到首页 if (currentRequestPath.equals("/")) { WebUtil.redirectRequest(FrameworkConstant.HOME_PAGE, request, response); return; } // 去掉当前请求路径末尾的“/” if (currentRequestPath.endsWith("/")) { currentRequestPath = currentRequestPath.substring(0, currentRequestPath.length() - 1); } // 定义几个变量(在下面的循环中使用) ActionBean actionBean = null; Matcher requestPathMatcher = null; // 获取并遍历 Action 映射 Map<RequestBean, ActionBean> actionMap = ActionHelper.getActionMap(); for (Map.Entry<RequestBean, ActionBean> actionEntry : actionMap.entrySet()) { // 从 RequestBean 中获取 Request 相关属性 RequestBean requestBean = actionEntry.getKey(); String requestMethod = requestBean.getRequestMethod(); String requestPath = requestBean.getRequestPath(); // 正则表达式 // 获取请求路径匹配器(使用正则表达式匹配请求路径并从中获取相应的请求参数) requestPathMatcher = Pattern.compile(requestPath).matcher(currentRequestPath); // 判断请求方法与请求路径是否同时匹配 if (requestMethod.equalsIgnoreCase(currentRequestMethod) && requestPathMatcher.matches()) { // 获取 ActionBean 及其相关属性 actionBean = actionEntry.getValue(); // 若成功匹配,则终止循环 break; } } // 若未找到 Action,则跳转到 404 页面 if (actionBean == null) { WebUtil.sendError(HttpServletResponse.SC_NOT_FOUND, "", response); return; } // 初始化 DataContext DataContext.init(request, response); try { // 调用 Action 方法 invokeActionMethod(request, response, actionBean, requestPathMatcher); } catch (Exception e) { // 处理 Action 异常 handleActionException(request, response, e); } finally { // 销毁 DataContext DataContext.destroy(); } } private void invokeActionMethod(HttpServletRequest request, HttpServletResponse response, ActionBean actionBean, Matcher requestPathMatcher) throws Exception { // 获取 Action 相关信息 Class<?> actionClass = actionBean.getActionClass(); Method actionMethod = actionBean.getActionMethod(); // 从 BeanHelper 中建立 Action 实例 Object actionInstance = BeanHelper.getBean(actionClass); // 获取 Action 方法参数 List<Object> paramList = createParamList(request, actionBean, requestPathMatcher); Class<?>[] paramTypes = actionMethod.getParameterTypes(); if (paramTypes.length != paramList.size()) { throw new RuntimeException("因为参数不匹配,没法调用 Action 方法!"); } // 调用 Action 方法 actionMethod.setAccessible(true); // 取消类型安全检测(可提升反射性能) Object actionMethodResult = actionMethod.invoke(actionInstance, paramList.toArray()); // 处理 Action 方法返回值 handleActionMethodReturn(request, response, actionMethodResult); } private List<Object> createParamList(HttpServletRequest request, ActionBean actionBean, Matcher requestPathMatcher) throws Exception { // 定义参数列表 List<Object> paramList = new ArrayList<Object>(); // 获取 Action 方法参数类型 Class<?>[] actionParamTypes = actionBean.getActionMethod().getParameterTypes(); // 添加路径参数列表(请求路径中的带占位符参数) paramList.addAll(createPathParamList(requestPathMatcher, actionParamTypes)); // 分两种状况进行处理 if (UploadHelper.isMultipart(request)) { // 添加 Multipart 请求参数列表 paramList.addAll(UploadHelper.createMultipartParamList(request)); } else { // 添加普通请求参数列表(包括 Query String 与 Form Data) Map<String, Object> requestParamMap = WebUtil.getRequestParamMap(request); if (MapUtil.isNotEmpty(requestParamMap)) { paramList.add(new Params(requestParamMap)); } } // 返回参数列表 return paramList; } private List<Object> createPathParamList(Matcher requestPathMatcher, Class<?>[] actionParamTypes) { // 定义参数列表 List<Object> paramList = new ArrayList<Object>(); // 遍历正则表达式中所匹配的组 for (int i = 1; i <= requestPathMatcher.groupCount(); i++) { // 获取请求参数 String param = requestPathMatcher.group(i); // 获取参数类型(支持四种类型:int/Integer、long/Long、double/Double、String) Class<?> paramType = actionParamTypes[i - 1]; if (paramType.equals(int.class) || paramType.equals(Integer.class)) { paramList.add(CastUtil.castInt(param)); } else if (paramType.equals(long.class) || paramType.equals(Long.class)) { paramList.add(CastUtil.castLong(param)); } else if (paramType.equals(double.class) || paramType.equals(Double.class)) { paramList.add(CastUtil.castDouble(param)); } else if (paramType.equals(String.class)) { paramList.add(param); } } // 返回参数列表 return paramList; } private void handleActionMethodReturn(HttpServletRequest request, HttpServletResponse response, Object actionMethodResult) { // 判断返回值类型 if (actionMethodResult != null) { if (actionMethodResult instanceof Result) { // 分两种状况进行处理 Result result = (Result) actionMethodResult; if (UploadHelper.isMultipart(request)) { // 对于 multipart 类型,说明是文件上传,须要转换为 HTML 格式并写入响应中 WebUtil.writeHTML(response, result); } else { // 对于其它类型,统一转换为 JSON 格式并写入响应中 WebUtil.writeJSON(response, result); } } else if (actionMethodResult instanceof View) { // 转发 或 重定向 到相应的页面中 View view = (View) actionMethodResult; if (view.isRedirect()) { // 获取路径 String path = view.getPath(); // 重定向请求 WebUtil.redirectRequest(path, request, response); } else { // 获取路径 String path = FrameworkConstant.JSP_PATH + view.getPath(); // 初始化请求属性 Map<String, Object> data = view.getData(); if (MapUtil.isNotEmpty(data)) { for (Map.Entry<String, Object> entry : data.entrySet()) { request.setAttribute(entry.getKey(), entry.getValue()); } } // 转发请求 WebUtil.forwardRequest(path, request, response); } } } } private void handleActionException(HttpServletRequest request, HttpServletResponse response, Exception e) { // 判断异常缘由 Throwable cause = e.getCause(); if (cause instanceof AccessException) { // 分两种状况进行处理 if (WebUtil.isAJAX(request)) { // 跳转到 403 页面 WebUtil.sendError(HttpServletResponse.SC_FORBIDDEN, "", response); } else { // 重定向到首页 WebUtil.redirectRequest(FrameworkConstant.HOME_PAGE, request, response); } } else if (cause instanceof PermissionException) { // 跳转到 403 页面 WebUtil.sendError(HttpServletResponse.SC_FORBIDDEN, "", response); } else { // 跳转到 500 页面 logger.error("执行 Action 出错!", e); WebUtil.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, cause.getMessage(), response); } } }
代码量虽然不算太多,可是你们能够发现,这个类犯了一个严重的错误,或许应该说是编程中的一个大忌! —— 严重违反了“单一职责原则”。正则表达式
当快枪手指出这个问题时,我仿佛被一根针狠狠扎了一下,瞬间就清醒过来了,本身果真是犯了错误。编程
正所谓“知错能改,善莫大焉”,因此我虚心地向快枪手请教,因而他开始舞弄笔墨,只需一分钟就帮我画了一张草图:缓存
这貌似哪里见过呀,没错,Spring MVC 就长这样子!安全
可见结构很是清晰:app
DispatcherServlet
(前端控制器)DispatcherServlet
调用 HandlerMapping
接口,获取 Handler
对象(该对象是对 Action 方法的抽象)DispatcherServlet
调用 HandlerInvoker
接口,调用具体的 Action 方法(同时须要获取 Action 参数)HandlerInvoker
调用 ViewResolver
接口,进行视图解析(视图能够是 JSP、HTML 或 Velocity 模板等)DispatcherServlet
调用 HandlerExceptionResolver
接口,进行相关的异常处理(可能会跳转到相应的错误页面)你们可能会问:为何要使用如此之多的接口呢?框架
由于在每一个成功接口的背后,总会有一个默默支持它的实现,而这些实现都是 Smart 框架内部提供的默认实现,开发人员能够根据实际须要进行定制,此时就须要与 InstanceFactory
打交道了。ide
<!-- lang: java --> /** * 实例工厂 * * @author huangyong * @since 2.3 */ public class InstanceFactory { /** * 用于缓存对应的实例 */ private static final Map<String, Object> cache = new ConcurrentHashMap<String, Object>(); ... /** * HandlerMapping */ private static final String HANDLER_MAPPING = "smart.framework.custom.handler_mapping"; /** * HandlerInvoker */ private static final String HANDLER_INVOKER = "smart.framework.custom.handler_invoker"; /** * HandlerExceptionResolver */ private static final String HANDLER_EXCEPTION_RESOLVER = "smart.framework.custom.handler_exception_resolver"; /** * ViewResolver */ private static final String VIEW_RESOLVER = "smart.framework.custom.view_resolver"; ... /** * 获取 HandlerMapping */ public static HandlerMapping getHandlerMapping() { return getInstance(HANDLER_MAPPING, DefaultHandlerMapping.class); } /** * 获取 HandlerInvoker */ public static HandlerInvoker getHandlerInvoker() { return getInstance(HANDLER_INVOKER, DefaultHandlerInvoker.class); } /** * 获取 HandlerExceptionResolver */ public static HandlerExceptionResolver getHandlerExceptionResolver() { return getInstance(HANDLER_EXCEPTION_RESOLVER, DefaultHandlerExceptionResolver.class); } /** * 获取 ViewResolver */ public static ViewResolver getViewResolver() { return getInstance(VIEW_RESOLVER, DefaultViewResolver.class); } @SuppressWarnings("unchecked") public static <T> T getInstance(String cacheKey, Class<T> defaultImplClass) { // 若缓存中存在对应的实例,则返回该实例 if (cache.containsKey(cacheKey)) { return (T) cache.get(cacheKey); } // 从配置文件中获取相应的接口实现类配置 String implClassName = ConfigHelper.getString(cacheKey); // 若实现类配置不存在,则使用默认实现类 if (StringUtil.isEmpty(implClassName)) { implClassName = defaultImplClass.getName(); } // 经过反射建立该实现类对应的实例 T instance = ObjectUtil.newInstance(implClassName); // 若该实例不为空,则将其放入缓存 if (instance != null) { cache.put(cacheKey, instance); } // 返回该实例 return instance; } }
好比说,当开发者想提供本身的 HandlerInvoker 实现,怎么作到呢?
他只须要在 smart.properties
配置文件中,添加以下配置项:
<!-- lang: java --> smart.framework.custom.handler_invoker=本身的 HandlerInvoker 实现类
abel533 同窗就实现了一个更强大的 HandlerInvoker,他的代码地址以下:
http://git.oschina.net/free/Args/tree/smart_plugin_args/
很是感谢他的贡献!
说到这里,你们应该火烧眉毛想看看,快枪手这位大神到底是如何定义这些接口的。别急,下面的才是精华!
这是 HandlerMapping
接口:
<!-- lang: java --> /** * 处理器映射 * * @author huangyong * @since 2.3 */ public interface HandlerMapping { /** * 获取 Handler * * @param currentRequestMethod 当前请求方法 * @param currentRequestPath 当前请求路径 * @return Handler */ Handler getHandler(String currentRequestMethod, String currentRequestPath); }
这是 HandlerInvoker
接口:
<!-- lang: java --> /** * Handler 调用器 * * @author huangyong * @since 2.3 */ public interface HandlerInvoker { /** * 调用 Handler * * @param request 请求对象 * @param response 响应对象 * @param handler Handler * @throws Exception 异常 */ void invokeHandler(HttpServletRequest request, HttpServletResponse response, Handler handler) throws Exception; }
这是 ViewResolver
接口:
<!-- lang: java --> /** * 视图解析器 * * @author huangyong * @since 2.3 */ public interface ViewResolver { /** * 解析视图 * * @param request 请求对象 * @param response 响应对象 * @param actionMethodResult Action 方法返回值 */ void resolveView(HttpServletRequest request, HttpServletResponse response, Object actionMethodResult); }
这是 HandlerExceptionResolver
接口:
<!-- lang: java --> /** * Handler 异常解析器 * * @author huangyong * @since 2.3 */ public interface HandlerExceptionResolver { /** * 解析 Handler 异常 * * @param request 请求对象 * @param response 响应对象 * @param e 异常 */ void resolveHandlerException(HttpServletRequest request, HttpServletResponse response, Exception e); }
可见,每一个接口中只包含一个方法,充分作到了“单一职责”,并且接口方法的参数很是简单。
其中有一个 Handler
类须要说明一下,它就是曾经的 ActionBean
,这里只是把它改了一个名字,让它看起来更加的专业,说白了,Handler
就是 Action 方法,没什么神奇的。
此外,快枪手建议将之前的 RequestBean
重命名为 Requestor
,用于封装请求对象的相关信息。
有必要再对 Handler
的代码说明一下:
<!-- lang: java --> /** * 封装 Action 方法相关信息 * * @author huangyong * @since 1.0 */ public class Handler { private Class<?> actionClass; private Method actionMethod; private Matcher requestPathMatcher; public Handler(Class<?> actionClass, Method actionMethod) { this.actionClass = actionClass; this.actionMethod = actionMethod; } public Class<?> getActionClass() { return actionClass; } public Method getActionMethod() { return actionMethod; } public Matcher getRequestPathMatcher() { return requestPathMatcher; } public void setRequestPathMatcher(Matcher requestPathMatcher) { this.requestPathMatcher = requestPathMatcher; } }
该类中包括三个成员变量:
Class<?> actionClass
:表示该 Handler 所在的 Action 类Method actionMethod
:表示当前的 Action 方法Matcher requestPathMatcher
:表示请求路径的正则表达式匹配器(用于根据请求 URL 匹配 Action 方法)准备工做现已就绪,下面就来看看这些接口的默认实现吧。
接口定义清楚了,重构犹如复制粘贴,下面根据以上 MVC 相关接口的出现顺序,分别展现具体的实现代码。
这是 HandlerMapping
接口的默认实现:
<!-- lang: java --> /** * 默认处理器映射 * * @author huangyong * @since 2.3 */ public class DefaultHandlerMapping implements HandlerMapping { /** * 用于缓存 Handler 实例 */ private static final Map<String, Handler> cache = new ConcurrentHashMap<String, Handler>(); @Override public Handler getHandler(String currentRequestMethod, String currentRequestPath) { // 若缓存中存在对应的实例,则返回该实例 String cacheKey = currentRequestMethod + ":" + currentRequestPath; if (cache.containsKey(cacheKey)) { return cache.get(cacheKey); } // 定义一个 Handler Handler handler = null; // 获取并遍历 Action 映射 Map<Requestor, Handler> actionMap = ActionHelper.getActionMap(); for (Map.Entry<Requestor, Handler> actionEntry : actionMap.entrySet()) { // 从 Requestor 中获取 Request 相关属性 Requestor requestor = actionEntry.getKey(); String requestMethod = requestor.getRequestMethod(); String requestPath = requestor.getRequestPath(); // 正则表达式 // 获取请求路径匹配器(使用正则表达式匹配请求路径并从中获取相应的请求参数) Matcher requestPathMatcher = Pattern.compile(requestPath).matcher(currentRequestPath); // 判断请求方法与请求路径是否同时匹配 if (requestMethod.equalsIgnoreCase(currentRequestMethod) && requestPathMatcher.matches()) { // 获取 Handler 及其相关属性 handler = actionEntry.getValue(); // 设置请求路径匹配器 if (handler != null) { handler.setRequestPathMatcher(requestPathMatcher); } // 若成功匹配,则终止循环 break; } } // 若该实例不为空,则将其放入缓存 if (handler != null) { cache.put(cacheKey, handler); } // 返回该 Handler return handler; } }
这是 HandlerInvoker
接口的默认实现:
<!-- lang: java --> /** * 默认 Handler 调用器 * * @author huangyong * @since 2.3 */ public class DefaultHandlerInvoker implements HandlerInvoker { private ViewResolver viewResolver = InstanceFactory.getViewResolver(); @Override public void invokeHandler(HttpServletRequest request, HttpServletResponse response, Handler handler) throws Exception { // 获取 Action 相关信息 Class<?> actionClass = handler.getActionClass(); Method actionMethod = handler.getActionMethod(); // 从 BeanHelper 中建立 Action 实例 Object actionInstance = BeanHelper.getBean(actionClass); // 建立 Action 方法的参数列表 List<Object> actionMethodParamList = createActionMethodParamList(request, handler); // 检查参数列表是否合法 checkParamList(actionMethod, actionMethodParamList); // 调用 Action 方法 Object actionMethodResult = invokeActionMethod(actionMethod, actionInstance, actionMethodParamList); // 解析视图 viewResolver.resolveView(request, response, actionMethodResult); } public List<Object> createActionMethodParamList(HttpServletRequest request, Handler handler) throws Exception { // 定义参数列表 List<Object> paramList = new ArrayList<Object>(); // 获取 Action 方法参数类型 Class<?>[] actionParamTypes = handler.getActionMethod().getParameterTypes(); // 添加路径参数列表(请求路径中的带占位符参数) paramList.addAll(createPathParamList(handler.getRequestPathMatcher(), actionParamTypes)); // 分两种状况进行处理 if (UploadHelper.isMultipart(request)) { // 添加 Multipart 请求参数列表 paramList.addAll(UploadHelper.createMultipartParamList(request)); } else { // 添加普通请求参数列表(包括 Query String 与 Form Data) Map<String, Object> requestParamMap = WebUtil.getRequestParamMap(request); if (MapUtil.isNotEmpty(requestParamMap)) { paramList.add(new Params(requestParamMap)); } } // 返回参数列表 return paramList; } private List<Object> createPathParamList(Matcher requestPathMatcher, Class<?>[] actionParamTypes) { // 定义参数列表 List<Object> paramList = new ArrayList<Object>(); // 遍历正则表达式中所匹配的组 for (int i = 1; i <= requestPathMatcher.groupCount(); i++) { // 获取请求参数 String param = requestPathMatcher.group(i); // 获取参数类型(支持四种类型:int/Integer、long/Long、double/Double、String) Class<?> paramType = actionParamTypes[i - 1]; if (ClassUtil.isInt(paramType)) { paramList.add(CastUtil.castInt(param)); } else if (ClassUtil.isLong(paramType)) { paramList.add(CastUtil.castLong(param)); } else if (ClassUtil.isDouble(paramType)) { paramList.add(CastUtil.castDouble(param)); } else if (ClassUtil.isString(paramType)) { paramList.add(param); } } // 返回参数列表 return paramList; } private Object invokeActionMethod(Method actionMethod, Object actionInstance, List<Object> actionMethodParamList) throws IllegalAccessException, InvocationTargetException { // 经过反射调用 Action 方法 actionMethod.setAccessible(true); // 取消类型安全检测(可提升反射性能) return actionMethod.invoke(actionInstance, actionMethodParamList.toArray()); } private void checkParamList(Method actionMethod, List<Object> actionMethodResult) { // 判断 Action 方法参数的个数是否匹配 Class<?>[] actionMethodParameterTypes = actionMethod.getParameterTypes(); if (actionMethodParameterTypes.length != actionMethodResult.size()) { throw new RuntimeException("因为参数不匹配,没法调用 Action 方法!"); } } }
这是 ViewResolver
接口的默认实现:
<!-- lang: java --> /** * 默认视图解析器 * * @author huangyong * @since 2.3 */ public class DefaultViewResolver implements ViewResolver { @Override public void resolveView(HttpServletRequest request, HttpServletResponse response, Object actionMethodResult) { if (actionMethodResult != null) { // Action 返回值可为 View 或 Result if (actionMethodResult instanceof View) { // 若为 View,则需考虑两种视图类型(重定向 或 转发) View view = (View) actionMethodResult; if (view.isRedirect()) { // 获取路径 String path = view.getPath(); // 重定向请求 WebUtil.redirectRequest(path, request, response); } else { // 获取路径 String path = FrameworkConstant.JSP_PATH + view.getPath(); // 初始化请求属性 Map<String, Object> data = view.getData(); if (MapUtil.isNotEmpty(data)) { for (Map.Entry<String, Object> entry : data.entrySet()) { request.setAttribute(entry.getKey(), entry.getValue()); } } // 转发请求 WebUtil.forwardRequest(path, request, response); } } else { // 若为 Result,则需考虑两种请求类型(文件上传 或 普通请求) Result result = (Result) actionMethodResult; if (UploadHelper.isMultipart(request)) { // 对于 multipart 类型,说明是文件上传,须要转换为 HTML 格式并写入响应中 WebUtil.writeHTML(response, result); } else { // 对于其它类型,统一转换为 JSON 格式并写入响应中 WebUtil.writeJSON(response, result); } } } } }
这是 HandlerExceptionResolver
接口的默认实现:
<!-- lang: java --> /** * 默认 Handler 异常解析器 * * @author huangyong * @since 2.3 */ public class DefaultHandlerExceptionResolver implements HandlerExceptionResolver { @Override public void resolveHandlerException(HttpServletRequest request, HttpServletResponse response, Exception e) { // 判断异常缘由 Throwable cause = e.getCause(); if (cause instanceof AccessException) { // 分两种状况进行处理 if (WebUtil.isAJAX(request)) { // 跳转到 403 页面 WebUtil.sendError(HttpServletResponse.SC_FORBIDDEN, "", response); } else { // 重定向到首页 WebUtil.redirectRequest(FrameworkConstant.HOME_PAGE, request, response); } } else if (cause instanceof PermissionException) { // 跳转到 403 页面 WebUtil.sendError(HttpServletResponse.SC_FORBIDDEN, "", response); } else { // 跳转到 500 页面 WebUtil.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, cause.getMessage(), response); } } }
代码量虽然有增无减,但这样的结构更加清晰了,职责更加分明,便于往后的扩展与维护。看来快枪手真不是通常的神人啊!
这些实现类的代码都来自于重构前的 DispatcherServlet
,这里只是根据职责进行了分类,那么如今的 DispatcherServlet
又是啥样子呢?
最后给你们奉上重构后的 DispatcherServlet
:
<!-- lang: java --> /** * 前端控制器 * * @author huangyong * @since 1.0 */ @WebServlet(urlPatterns = "/*", loadOnStartup = 0) public class DispatcherServlet extends HttpServlet { private static final Logger logger = LoggerFactory.getLogger(DispatcherServlet.class); private HandlerMapping handlerMapping = InstanceFactory.getHandlerMapping(); private HandlerInvoker handlerInvoker = InstanceFactory.getHandlerInvoker(); private HandlerExceptionResolver handlerExceptionResolver = InstanceFactory.getHandlerExceptionResolver(); @Override public void init(ServletConfig config) throws ServletException { // 初始化相关配置 ServletContext servletContext = config.getServletContext(); UploadHelper.init(servletContext); } @Override public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 设置请求编码方式 request.setCharacterEncoding(FrameworkConstant.UTF_8); // 获取当前请求相关数据 String currentRequestMethod = request.getMethod(); String currentRequestPath = WebUtil.getRequestPath(request); logger.debug("[Smart] {}:{}", currentRequestMethod, currentRequestPath); // 将“/”请求重定向到首页 if (currentRequestPath.equals("/")) { WebUtil.redirectRequest(FrameworkConstant.HOME_PAGE, request, response); return; } // 去掉当前请求路径末尾的“/” if (currentRequestPath.endsWith("/")) { currentRequestPath = currentRequestPath.substring(0, currentRequestPath.length() - 1); } // 获取 Handler Handler handler = handlerMapping.getHandler(currentRequestMethod, currentRequestPath); // 若未找到 Action,则跳转到 404 页面 if (handler == null) { WebUtil.sendError(HttpServletResponse.SC_NOT_FOUND, "", response); return; } // 初始化 DataContext DataContext.init(request, response); try { // 调用 Handler handlerInvoker.invokeHandler(request, response, handler); } catch (Exception e) { // 处理 Action 异常 handlerExceptionResolver.resolveHandlerException(request, response, e); } finally { // 销毁 DataContext DataContext.destroy(); } } }
此时,只需在 DispatcherServlet
中调用 InstanceFactory
的相关方法,即可获取相应的接口,代码看起来也轻松了许多。
重构是一个永恒的话题,也是一件永无休止的事情,好代码毫不是一开始就写得出来的,必定是通过了反复的重构,将不合理的地方变成更合理,之后有机会再与你们分享重构的心得与体会。
欢迎下载 Smart 源码:
http://git.oschina.net/huangyong/smart
欢迎阅读 Smart 博文: