当前位置: 首页 > news >正文

网站首页添加代码wordpress 解释符号

网站首页添加代码,wordpress 解释符号,品牌推广的内容,福州网站建设 找燕狂徒 04Spring源码阅读目录 第一部分——IOC篇 第一章 Spring之最熟悉的陌生人——IOC 第二章 Spring之假如让你来写IOC容器——加载资源篇 第三章 Spring之假如让你来写IOC容器——解析配置文件篇 第四章 Spring之假如让你来写IOC容器——XML配置文件篇 第五章 Spring之假如让你来写…Spring源码阅读目录 第一部分——IOC篇 第一章 Spring之最熟悉的陌生人——IOC 第二章 Spring之假如让你来写IOC容器——加载资源篇 第三章 Spring之假如让你来写IOC容器——解析配置文件篇 第四章 Spring之假如让你来写IOC容器——XML配置文件篇 第五章 Spring之假如让你来写IOC容器——BeanFactory和FactoryBean 第六章 Spring之假如让你来写IOC容器——Scope和属性填充 第七章 Spring之假如让你来写IOC容器——属性填充特别篇SpEL表达式 第八章 Spring之假如让你来写IOC容器——拓展篇 第九章 Spring之源码阅读——环境搭建篇 第十章 Spring之源码阅读——IOC篇 第二部分——AOP篇 第十一章 Spring之不太熟的熟人——AOP 第十二章 Spring之不得不了解的内容——概念篇 第十三章 Spring之假如让你来写AOP——AOP联盟篇 第十四章 Spring之假如让你来写AOP——雏形篇 第十五章 Spring之假如让你来写AOP——Joinpoint连接点篇 第十六章 Spring之假如让你来写AOP——Pointcut切点篇 第十七章 Spring之假如让你来写AOP——Advice通知上篇 第十八章 Spring之假如让你来写AOP——Advice通知下篇 第十九章 Spring之假如让你来写AOP——番外篇Spring早期设计 第二十章 Spring之假如让你来写AOP——Aspect切面篇 第二十一章 Spring之假如让你来写AOP——Weaver织入器篇 第二十二章 Spring之假如让你来写AOP——Target Object目标对象篇 第二十三章 Spring之假如让你来写AOP——融入IOC容器篇 第二十四章 Spring之源码阅读——AOP篇 第三部分——事务篇 第二十五章 Spring之曾经的老朋友——事务 第二十六章 Spring之假如让你来写事务——初稿篇 第二十七章 Spring之假如让你来写事务——铁三角篇 第二十八章 Spring之假如让你来写事务——属性篇 第二十九章 Spring之假如让你来写事务——状态篇 第三十章 Spring之假如让你来写事务——管理篇 第三十一章 Spring之假如让你来写事务——融入IOC容器篇 第三十二章 Spring之源码阅读——事务篇 第四部分——MVC篇 第三十三章 Spring之梦开始的地方——MVC 第三十四章 Spring之假如让你来写MVC——草图篇 第三十五章 Spring之假如让你来写MVC——映射器篇 第三十六章 Spring之假如让你来写MVC——拦截器篇 第三十七章 Spring之假如让你来写MVC——控制器篇 第三十八章 Spring之假如让你来写MVC——适配器篇 第三十九章 Spring之假如让你来写MVC——番外篇类型转换 第四十章 Spring之假如让你来写MVC——ModelAndView篇 第四十一章 Spring之假如让你来写MVC——番外篇数据绑定 第四十二章 Spring之假如让你来写MVC——视图篇 第四十三章 Spring之假如让你来写MVC——上传文件篇 第四十四章 Spring之假如让你来写MVC——异常处理器篇 第四十五章 Spring之假如让你来写MVC——国际化篇 第四十六章 Spring之假如让你来写MVC——主题解析器篇 第四十七章 Spring之假如让你来写MVC——闪存管理器篇 第四十八章 Spring之假如让你来写MVC——请求映射视图篇 第四十九章 Spring之假如让你来写MVC——番外篇属性操作 第五十章 Spring之假如让你来写MVC——融入IOC容器篇 第五十一章 Spring之源码阅读——MVC篇 文章目录 Spring源码阅读目录第一部分——IOC篇第二部分——AOP篇第三部分——事务篇第四部分——MVC篇 前言尝试动手写IOC容器第三十四版 适配器request参数参数类型转换注解适配器改造DispatcherServlet测试 总结 前言 对于Spring一直都是既熟悉又陌生说对它熟悉吧平时用用没啥问题但面试的时候被问的一脸懵逼就很尴尬都不好意思在简历上写着熟悉Spring了 所以决定花点时间研究研究Spring的源码。主要参考的书籍是《Spring源码深度解析第2版》、《Spring揭秘》、《Spring技术内幕深入解析Spring架构与设计原理第2版》 书接上回在上篇 第三十七章 Spring之假如让你来写MVC——控制器篇 中A君 已经完成了 控制器 部分的功能了。接下来看看 A君 会有什么骚操作吧 尝试动手写IOC容器 出场人物A君苦逼的开发、老大项目经理 背景老大 要求 A君在一周内开发个简单的 IOC容器 前情提要A君 已经完成了 控制器 部分的功能了 。。。 第三十四版 适配器 “A君 呐你用if..else来判断调用哪个处理器就很灵性了。” 老大 感叹道 “额。” A君 不知道怎么结果话茬只能装傻充愣了 “这种拓展性太低了后边还有其他处理器的实现方式呢。这样子往后稍微发展下你的代码就变成了传说中的 屎山代码。还有一点就是关于请求参数的处理要知道一个请求可以携带很多参数的而你现在这个实现用户只能去request里获取这一点用户体验非常的糟糕。去把这两部部分内容处理下吧。” 说完老大 就没再说什么了 看到 老大 没有继续往下说的意思看来是要自己发挥。A君 默默的退了出去准备着手干活了 对于这种类型适配器A君 其实并不算陌生早在之前实现 IOC容器 的时候A君 就已经接触过只不过当时是根据属性类型找到对应的转换器进行类型转换。而这次只是改成根据不同的 控制器 找到对应的 适配器 而已其本质本无实际上的区别。那么 适配器 的接口就好定义了必然存在着两个方法一个是能不能转换另一个是进行转换。基本盘有了接下来就要考虑特殊性了由于HTTP中定义了Last-Modified。其规范如下 这个属性跟缓存息息相关如果没有超过对应时间则服务器可以直接不处理返回上次结果。那么整体的接口定义就出来了A君 新增HandlerAdapter接口代码如下 /*** 控制器的适配器找到对应的控制器*/ public interface HandlerAdapter {/*** 是否可以转换** param handler* return*/boolean supports(Object handler);/*** 处理请求** param request* param response* param handler* return* throws Exception*/Object handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;/*** 如果没有默认实现默认返回-1* 这个方法放在这里感觉并不合适LastModified和适配器并有什么关系违反了接口单一原则并不符合Spring一贯的作风* 新版本已经弃用这里考虑到老项目** param request* param handler* return*/Deprecatedlong getLastModified(HttpServletRequest request, Object handler); } Last-Modified的处理方法放在这里感觉并不合适Last-Modified和适配器本身并没有什么关系违反了接口单一原则。按理说适配器只负责找到处理对应的控制器进行处理并不会去关心Last-Modified这些东西此处的设计不符合Spring一贯的作风不知道当初是基于什么考虑才如此设计这里为了贴近Spring所以也加上getLastModified方法。在Spring5.3.9后续版本中该方法已经标记成弃用 好了接口出来后先挑个简单的练练手A君 盯上了Controller和Servlet原因也简单实现了对应接口的其实是最好处理的只需要强转后调用该接口方法就行了。这里 A君 就以Controller适配器为例新增SimpleControllerHandlerAdapter类代码如下 /*** Controller相关接口适配*/ public class SimpleControllerHandlerAdapter implements HandlerAdapter {Overridepublic boolean supports(Object handler) {return (handler instanceof Controller);}Overridepublic Object handle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {return ((Controller) handler).handleRequest(request, response);}OverrideSuppressWarnings(deprecation)public long getLastModified(HttpServletRequest request, Object handler) {if (handler instanceof LastModified) {return ((LastModified) handler).getLastModified(request);}return -1L;} }简单过后A君 就开始头疼了简单之所以简单是因为实现了对应接口方法参数、返回值都是固定的。而基于注解的 控制器这两个没有一个是能确定的不能确定就意味着需要框架去推算匹配那么参数处理就会变得异常的麻烦。没办法只能先易后难。A君 谨遵 老大 的教诲对于有公共内容的提取出来一个抽象类。于是A君 新增AbstractHandlerMethodAdapter类代码如下 public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {Overridepublic final boolean supports(Object handler) {return (handler instanceof HandlerMethod supportsInternal((HandlerMethod) handler));}Overridepublic final Object handle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {return handleInternal(request, response, (HandlerMethod) handler);}protected abstract Object handleInternal(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;protected abstract boolean supportsInternal(HandlerMethod handlerMethod);OverrideSuppressWarnings(deprecation)public final long getLastModified(HttpServletRequest request, Object handler) {return getLastModifiedInternal(request, (HandlerMethod) handler);}Deprecatedprotected abstract long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod);}简单的完成了接下来就得考虑困难的事了当务之急就是要解决参数匹配的问题不然 注解适配类 无从实现 request参数 要想自动适配 控制器 参数A君 得先知道哪些可以成为入参也就是一个request请求中哪些可以作为 控制器 的参数。A君 在翻阅 Servlet规范 时看到这些东西如下 请求参数 属性 3.头 那么正常情况下request中属性Attributes、请求头Headers、请求参数Params 都可以作为 控制器 的入参。明白参数从哪里之后就可以先把这部分东西抽象化了。这里要注意的是虽然 A君 一直以 Servlet规范 作为例子实际上在Web环境下不仅仅 Servlet 一种规范还有很多不同的规范像WebSocket、 WebFlux、Portlet 等所以这里定义接口更是为了通用性适配这些规范。A君 定义 RequestAttributes 接口用来封装 属性Attributes 的相关操作。代码如下 /*** request请求属性*/ public interface RequestAttributes {int SCOPE_REQUEST 0;int SCOPE_SESSION 1;/*** request作用域*/String REFERENCE_REQUEST request;/*** session作用域*/String REFERENCE_SESSION session;Object getAttribute(String name, int scope);void setAttribute(String name, Object value, int scope);void removeAttribute(String name, int scope);String[] getAttributeNames(int scope);/*** 注册回调** param name* param callback* param scope*/void registerDestructionCallback(String name, Runnable callback, int scope);/*** 处理引用类型** param key* return*/Object resolveReference(String key);/*** 获取SessionId** return*/String getSessionId();/*** 获取Session同步锁** return*/Object getSessionMutex();}这个接口只是规定了 属性Attributes 的相关操作显然是远远不够的还需要 请求头Headers、请求参数Params 的相关操作于是A君 对其进行拓展定义WebRequest接口。代码如下 public interface WebRequest extends RequestAttributes {/*** 获取请求头** param headerName* return*/String getHeader(String headerName);String[] getHeaderValues(String headerName);IteratorString getHeaderNames();String getParameter(String paramName);String[] getParameterValues(String paramName);IteratorString getParameterNames();MapString, String[] getParameterMap();Locale getLocale();String getContextPath();String getRemoteUser();Principal getUserPrincipal();boolean isUserInRole(String role);boolean isSecure();/*** 检查资源是否过期** param lastModifiedTimestamp* return*/boolean checkNotModified(long lastModifiedTimestamp);boolean checkNotModified(String etag);boolean checkNotModified(String etag, long lastModifiedTimestamp);String getDescription(boolean includeClientInfo);}前文提到由于存在着多种规范那么对于获取其真实的请求或者响应对象就很有必要了A君 不可以预判到用户要用哪种协议所以只能再定义个接口用来获取真实的请求对象、响应对象。新增NativeWebRequest接口代码如下 public interface NativeWebRequest extends WebRequest {/*** 获取真实请求对象** return*/Object getNativeRequest();/*** 获取真实响应对象** return*/Object getNativeResponse();T T getNativeRequest(ClassT requiredType);T T getNativeResponse(ClassT requiredType); } 接口定义完成之后接下来就是实现了虽然存在着多种规范但 A君 并不太关心起码现在不用关心这里是 MVC 的主场。A君 只关注 Servlet 的实现那问题就简单了这些东西只需要从 Servlet容器 中获取就行了。A君 新增ServletWebRequest类代码如下 public class ServletWebRequest extends ServletRequestAttributes implements NativeWebRequest {Overridepublic String getParameter(String paramName) {return getRequest().getParameter(paramName);}Overridepublic String getHeader(String headerName) {return getRequest().getHeader(headerName);}//省略其他方法 }参数类型转换 解决了参数的来源问题现在就可以开始进行参数的转换了。要知道request请求过来的参数可只有字符串类型或字节流字节流现在不在考虑的范围之内那还需要把字符串转成 控制器 对应的类型才行。所谓自动适配无非就是把请求参数转成方法参数罢了。转换接口依旧是那两板斧能处理吗进行处理玩不出什么花来。于是A君 照猫画虎定义HandlerMethodArgumentResolver接口代码如下 /*** 参数转换接口*/ public interface HandlerMethodArgumentResolver {boolean supportsParameter(MethodParameter parameter);Object resolveArgument(MethodParameter parameter, NativeWebRequest webRequest) throws Exception; }接着就是实现了类那么多A君 还没颠到全部实现的地步只要实现主流的类就行了剩余的部分嘛就看用户自己发挥了。A君 决定先从两个最重要的参数开始那就是request、response。两个都是类似的这里就以request为例A君 新增ServletRequestMethodArgumentResolver类那么问题来了要支持那些类型呢 对于Web来说request可谓是举足轻重主要是从request可以拿到太多的东西了比如ServletRequest、HttpSession、Principal、InputStream等。那么能从request中获取的东西就是ServletRequestMethodArgumentResolver支持的类型。代码如下 public class ServletRequestMethodArgumentResolver implements HandlerMethodArgumentResolver {Overridepublic boolean supportsParameter(MethodParameter parameter) {Class? paramType parameter.getParameterType();return (WebRequest.class.isAssignableFrom(paramType) ||ServletRequest.class.isAssignableFrom(paramType) ||HttpSession.class.isAssignableFrom(paramType) ||(pushBuilder ! null pushBuilder.isAssignableFrom(paramType)) ||Principal.class.isAssignableFrom(paramType) ||InputStream.class.isAssignableFrom(paramType) ||Reader.class.isAssignableFrom(paramType) ||HttpMethod.class paramType);}Overridepublic Object resolveArgument(MethodParameter parameter,NativeWebRequest webRequest) throws Exception {Class? paramType parameter.getParameterType();if (WebRequest.class.isAssignableFrom(paramType)) {if (!paramType.isInstance(webRequest)) {throw new IllegalStateException(Current request is not of type [ paramType.getName() ]: webRequest);}return webRequest;}if (ServletRequest.class.isAssignableFrom(paramType)) {return resolveNativeRequest(webRequest, paramType);}return resolveArgument(paramType, resolveNativeRequest(webRequest, HttpServletRequest.class));} }这还是很简单的一堆if...esle就行了A君 感叹道。接着还需要支持下基本类型首先要考虑的是如何从request中获取到参数HTTP请求只有字符串或字节流按照类型匹配显然是不合适的。现在 参数转换器 要做的事情就是根据名称从request对应的值转成 控制器 参数的类型 #mermaid-svg-U89WMqJEGitVJKHb {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-U89WMqJEGitVJKHb .error-icon{fill:#552222;}#mermaid-svg-U89WMqJEGitVJKHb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-U89WMqJEGitVJKHb .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-U89WMqJEGitVJKHb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-U89WMqJEGitVJKHb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-U89WMqJEGitVJKHb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-U89WMqJEGitVJKHb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-U89WMqJEGitVJKHb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-U89WMqJEGitVJKHb .marker.cross{stroke:#333333;}#mermaid-svg-U89WMqJEGitVJKHb svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-U89WMqJEGitVJKHb .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-U89WMqJEGitVJKHb .cluster-label text{fill:#333;}#mermaid-svg-U89WMqJEGitVJKHb .cluster-label span{color:#333;}#mermaid-svg-U89WMqJEGitVJKHb .label text,#mermaid-svg-U89WMqJEGitVJKHb span{fill:#333;color:#333;}#mermaid-svg-U89WMqJEGitVJKHb .node rect,#mermaid-svg-U89WMqJEGitVJKHb .node circle,#mermaid-svg-U89WMqJEGitVJKHb .node ellipse,#mermaid-svg-U89WMqJEGitVJKHb .node polygon,#mermaid-svg-U89WMqJEGitVJKHb .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-U89WMqJEGitVJKHb .node .label{text-align:center;}#mermaid-svg-U89WMqJEGitVJKHb .node.clickable{cursor:pointer;}#mermaid-svg-U89WMqJEGitVJKHb .arrowheadPath{fill:#333333;}#mermaid-svg-U89WMqJEGitVJKHb .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-U89WMqJEGitVJKHb .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-U89WMqJEGitVJKHb .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-U89WMqJEGitVJKHb .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-U89WMqJEGitVJKHb .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-U89WMqJEGitVJKHb .cluster text{fill:#333;}#mermaid-svg-U89WMqJEGitVJKHb .cluster span{color:#333;}#mermaid-svg-U89WMqJEGitVJKHb div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-U89WMqJEGitVJKHb :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 解析 是 否 request参数 参数类型 是否匹配类型 成功转换 转换失败 控制器参数 结束 A君 先定义一个NamedValueInfo类用以包装参数名相关信息。代码如下 protected static class NamedValueInfo {private final String name;private final boolean required;private final String defaultValue;public NamedValueInfo(String name, boolean required, String defaultValue) {this.name name;this.required required;this.defaultValue defaultValue;}}接着A君 思考了下根据方法参数名方法参数名的获取在AOP 相关章节中有过说明这里就不在进行赘述了去request中获取值不论是 属性Attributes、请求头Headers、请求参数Params 都是从 request 中获取的只是地方不一样罢了那这就可以提取一个抽象类了。于是A君 定义AbstractNamedValueMethodArgumentResolver类代码如下 public abstract class AbstractNamedValueMethodArgumentResolver implements HandlerMethodArgumentResolver {Overridepublic final Object resolveArgument(MethodParameter parameter, NativeWebRequest webRequest) throws Exception {/*** 获取目标参数名*/NamedValueInfo namedValueInfo getNamedValueInfo(parameter);MethodParameter nestedParameter parameter.nestedIfOptional();Object resolvedName namedValueInfo.name;if (resolvedName null) {throw new IllegalArgumentException(Specified name must not resolve to null: [ namedValueInfo.name ]);}/*** 从request获取值由子类实现*/Object arg resolveName(resolvedName.toString(), nestedParameter, webRequest);if (arg null) {if (namedValueInfo.defaultValue ! null) {arg namedValueInfo.defaultValue;} else if (namedValueInfo.required !nestedParameter.isOptional()) {handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);}arg handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());} else if (.equals(arg) namedValueInfo.defaultValue ! null) {arg namedValueInfo.defaultValue;}handleResolvedValue(arg, namedValueInfo.name, parameter, webRequest);return arg;}//省略其他方法 }好了抽象类已经抽取完毕那么 属性Attributes、请求头Headers、请求参数Params 都大同小异了只需要去各自的区域取值就行了。A君 这里以 请求参数Params 为例新增RequestParamMethodArgumentResolver类代码如下 public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolverimplements UriComponentsContributor {Overridepublic boolean supportsParameter(MethodParameter parameter) {if (parameter.hasParameterAnnotation(RequestParam.class)) {/*** map类型*/if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {RequestParam requestParam parameter.getParameterAnnotation(RequestParam.class);return (requestParam ! null StringUtils.hasText(requestParam.name()));} else {return true;}} else {/*** 是否是Optional*/parameter parameter.nestedIfOptional();if (this.useDefaultResolution) {return BeanUtils.isSimpleProperty(parameter.getNestedParameterType());} else {return false;}}}Overrideprotected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {HttpServletRequest servletRequest request.getNativeRequest(HttpServletRequest.class);Object arg null;if (arg null) {String[] paramValues servletRequest.getParameterValues(name);if (paramValues ! null) {arg (paramValues.length 1 ? paramValues[0] : paramValues);}}return arg;}//省略其他方法 } 好了现在都准备好了剩下的就是把这些参数处理器进行一下整合方便别人使用。A君 在定义HandlerMethodArgumentResolverComposite类这个不负责具体实现而是调用别的类来实现转换类似于一个管理者的角色。代码如下 public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {private final ListHandlerMethodArgumentResolver argumentResolvers new ArrayList();private final MapMethodParameter, HandlerMethodArgumentResolver argumentResolverCache new ConcurrentHashMap(256);Overridepublic boolean supportsParameter(MethodParameter parameter) {return getArgumentResolver(parameter) ! null;}private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {HandlerMethodArgumentResolver result this.argumentResolverCache.get(parameter);if (result null) {for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {if (resolver.supportsParameter(parameter)) {result resolver;this.argumentResolverCache.put(parameter, result);break;}}}return result;}Overridepublic Object resolveArgument(MethodParameter parameter, NativeWebRequest webRequest) throws Exception {HandlerMethodArgumentResolver resolver getArgumentResolver(parameter);if (resolver null) {throw new IllegalArgumentException(Unsupported parameter type [ parameter.getParameterType().getName() ]. supportsParameter should be called first.);}return resolver.resolveArgument(parameter, webRequest);} 好嘞现在处理参数部分也完事了饶了一大圈总算把参数处理完了现在可以继续前行了 注解适配器 解决完最麻烦的参数处理之后剩下的 注解适配器 就没有什么东西了跟反射调用基本一样了。A君 新增RequestMappingHandlerAdapter类代码如下 public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {private HandlerMethodArgumentResolverComposite argumentResolvers;protected Object invokeHandlerMethod(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {ServletWebRequest webRequest new ServletWebRequest(request, response);try {ServletInvocableHandlerMethod invocableMethod createInvocableHandlerMethod(handlerMethod);if (this.argumentResolvers ! null) {invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);}if (this.returnValueHandlers ! null) {invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);}invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);return invocableMethod.invokeAndHandle(webRequest);} finally {webRequest.requestCompleted();}}//省略其他代码 } 改造DispatcherServlet 适配器 弄完之后A君 想起还需要对DispatcherServlet进行改造毕竟当初折腾 适配器 的目的不就是为了替换DispatcherServlet中的if...else吗改造如下 新增 适配器 类 替换doDispatch方法中的if...else 测试 现在一切都准备好了可以进入检验成果的时候了。A君 修改HelloController新增一个参数。代码如下 Controller public class HelloController {RequestMapping(/hello)public String sayHello(HttpServletRequest req, HttpServletResponse resp, String str) {String key message;String message (String) req.getAttribute(key);if (message null) {message ;}req.setAttribute(key, message V34 HandleMapping! str);return hello;} }其他测试代码不需要变动编写测试代码如下 Testpublic void v34() throws Throwable {System.out.println(############# 第三十四版 适配器篇 #############);Tomcat tomcat new Tomcat();//设置端口tomcat.setPort(8082);//设置静态资源路径String webApp new File(src/main/resources/v34).getAbsolutePath();Context context tomcat.addWebapp(/test/, webApp);tomcat.start();//挂起tomcat.getServer().await();}测试结果如下 后台成功接收到参数并显示出来了说明 A君 的努力并没有白费。OK这下子总算弄好了也可以向 老大 交差了 总结 正所谓树欲静而风不止欲知后事如何请看下回分解(✪ω✪)
http://www.w-s-a.com/news/874559/

相关文章:

  • 芜湖做网站都有哪些广州音乐制作公司
  • 青岛好的网站制作推广注册公司流程步骤
  • 怎么制作营销网站模板wordpress苗木模板
  • 手机网站样例wordpress 排序
  • 济南网站建设手机网站开发人员需要去做原型吗
  • 动易网站模板下载微信支付 wordpress
  • 学校建设外文网站情况阿里云 建设网站怎么样
  • 网站建设与网页设计制作深圳网站建设首选上榜网络
  • 网站浏览成交指标计算机应用是做什么的
  • 企业网站建设的要求wordpress 404页面模板
  • 公司怎么注册官方网站wordpress花园网站
  • 一般网站的建设步骤有哪些企业网站建设应该注意什么事项问题
  • 枣庄市建设局网站建设工程合同交底的内容包括
  • 全国十大跨境电商排名seo优化入门教程
  • 福安网站开发网站内容建设要求age06
  • 网站开发制作公司罗湖在线
  • 做网站银川潍坊网络科技有限公司
  • 南宁企业网站建站模板盐田高端网站建设
  • 深圳市建设局网站张局北京档案馆网站建设
  • 运动健身型网站开发网站备案掉了什么原因
  • 网站开发的前后端是什么注册网站多少钱一年
  • 彩票网站建设需要什么网站未备案被阻断怎么做
  • wordpress 版权声明网站优化排名哪家性价比高
  • dedecms网站关键词外包做网站平台 一分钟
  • 酒网站建设游戏分类网站怎么做
  • 仿牌网站安全北京大良网站建设
  • ps中怎样做网站轮播图片吉林省网站建设公司
  • 广西网站建设-好发信息网温江做网站哪家好
  • 网站建设属于什么职位类别南京哪个网站建设比较好
  • wdcp 网站备份东莞网站建设五金建材