首页 文章 精选 留言 我的

精选列表

搜索[指标分析],共10000篇文章
优秀的个人博客,低调大师

SpringMVC源码分析(8)剖析ViewResolver

ViewResolver很简单,通过名称(name),获取View视图的。 View视图 其实就是对应MVC中的"V" 1.ViewResolver 结构图 2.BeanNameViewResolver 通过把返回的逻辑视图名称去匹配定义好的视图bean对象。 @Test publicvoidtestBeanNameViewResolver()throwsServletException{ StaticWebApplicationContextwac=newStaticWebApplicationContext(); wac.setServletContext(newMockServletContext()); MutablePropertyValuespvs1=newMutablePropertyValues(); pvs1.addPropertyValue(newPropertyValue("url","/example1.jsp")); wac.registerSingleton("example1",InternalResourceView.class,pvs1); BeanNameViewResolvervr=newBeanNameViewResolver(); vr.setApplicationContext(wac); wac.refresh(); Viewview=vr.resolveViewName("example1",Locale.getDefault()); assertEquals("Correctviewclass",InternalResourceView.class,view.getClass()); assertEquals("CorrectURL","/example1.jsp",((InternalResourceView)view).getUrl()); } 3.XmlViewResolverXmlViewResolver这个视图解析器跟 BeanNameViewResolver 有点类似,也是通过把返回的逻辑视图名称去匹配定义好的视图 bean 对象。 3.1 配置XML <?xmlversion="1.0"encoding="UTF-8"?> <!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN2.0//EN""http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <beanid="example1"class="org.springframework.web.servlet.view.ViewResolverTests$TestView"> <propertyname="url"><value>/example1.jsp</value></property> <propertyname="attributesMap"> <map> <entrykey="test1"><value>testvalue1</value></entry> <entrykey="test2"><refbean="testBean"/></entry> </map> </property> <propertyname="location"><value>test</value></property> </bean> </beans> 3.2 测试用例 @Test publicvoidtestXmlViewResolver()throwsException{ StaticWebApplicationContextwac=newStaticWebApplicationContext(); wac.registerSingleton("testBean",TestBean.class); wac.setServletContext(newMockServletContext()); wac.refresh(); TestBeantestBean=(TestBean)wac.getBean("testBean"); XmlViewResolvervr=newXmlViewResolver(); vr.setLocation(newClassPathResource("org/springframework/web/servlet/view/views.xml")); vr.setApplicationContext(wac); Viewview1=vr.resolveViewName("example1",Locale.getDefault()); assertTrue("Correctviewclass",TestView.class.equals(view1.getClass())); assertTrue("CorrectURL","/example1.jsp".equals(((InternalResourceView)view1).getUrl()));BeanNameViewResolver VS XmlViewResolver 1. BeanNameViewResolver 要求视图 bean 对象都定义在 Spring 的 application context 中,而 XmlViewResolver 是在指定的配置文件中寻找视图 bean 对象, 2. XmlViewResolver是 AbstractCachingViewResolver的子类,支持缓存; BeanNameViewResolver 不会进行视图缓存。4.ResourceBundleViewResolver 和 XmlViewResolver 一样它也需要有一个配置文件来定义逻辑视图名称和真正的 View 对象的对应关系,不同的是 ResourceBundleViewResolver 的配置文件是一个属性文件,而且必须是放在 classpath 路径下面的,默认情况下这个配置文件是在 classpath 根目录下的 views.properties 文件,如果不使用默认值的话,则可以通过属性 baseName 或 baseNames 来指定。 4.1 配置文件testviews_fr.properties debugView.(class)=org.springframework.web.servlet.view.InternalResourceView debugView.url=jsp/debug/deboug.jsp debugView.contentType=text/xml;charset=ISO-8859-1 4.2 测试用例 publicclassResourceBundleViewResolverTestsextendsTestCase{ /**Comesfromthispackage*/ privatestaticStringPROPS_FILE="org.springframework.web.servlet.view.testviews"; privateResourceBundleViewResolverrb; privateStaticWebApplicationContextwac; protectedvoidsetUp()throwsException{ rb=newResourceBundleViewResolver(); rb.setBasename(PROPS_FILE); rb.setCache(getCache()); rb.setDefaultParentView("testParent"); wac=newStaticWebApplicationContext(); wac.setServletContext(newMockServletContext()); wac.refresh(); //Thiswillbepropagatedtoviews,soweneedit. rb.setApplicationContext(wac); } publicvoidtestDebugViewFrench()throwsException{ Viewv=rb.resolveViewName("debugView",Locale.FRENCH); assertTrue("FrenchdebugViewmustbeoftypeInternalResourceView",vinstanceofInternalResourceView); InternalResourceViewjv=(InternalResourceView)v; assertTrue("FrenchdebugViewmusthavecorrectURL","jsp/debug/deboug.jsp".equals(jv.getUrl())); assertTrue( "Correctoverridden(XML)contenttype,not'"+jv.getContentType()+"'", jv.getContentType().equals("text/xml;charset=ISO-8859-1")); } } 在ResourceBundleViewResolver第一次进行视图解析的时候会先new一个BeanFactory对象,然后把properties文件中定义好的属性按照它自身的规则生成一个个的bean对象注册到该BeanFactory中,之后会把该BeanFactory对象保存起来,所以ResourceBundleViewResolver缓存的是BeanFactory,而不是直接的缓存从BeanFactory中取出的视图bean。然后会从bean工厂中取出名称为逻辑视图名称的视图bean进行返回。接下来就讲讲Spring通过properties文件生成bean的规则。它会把properties文件中定义的属性名称按最后一个点“.”进行分割,把点前面的内容当做是bean名称,点后面的内容当做是bean的属性。这其中有几个特别的属性,Spring把它们用小括号包起来了,这些特殊的属性一般是对应的attribute,但不是bean对象所有的attribute都可以这样用。其中(class)是一个,除了(class)之外,还有(scope)、(parent)、(abstract)、(lazy-init)。而除了这些特殊的属性之外的其他属性,Spring会把它们当做bean对象的一般属性进行处理,就是bean对象对应的property。所以根据上面的属性配置文件将生成如下两个bean对象: from http://elim.iteye.com/blog/1770554 5.UrlBasedViewResolver 它是对ViewResolver的一种简单实现,而且继承了AbstractCachingViewResolver,主要就是提供的一种拼接URL的方式来解析视图,它可以让我们通过prefix属性指定一个指定的前缀,通过suffix属性指定一个指定的后缀,然后把返回的逻辑视图名称加上指定的前缀和后缀就是指定的视图URL了。 5.2 重要属性 publicclassUrlBasedViewResolverextendsAbstractCachingViewResolverimplementsOrdered{ /** *PrefixforspecialviewnamesthatspecifyaredirectURL(usually *toacontrollerafteraformhasbeensubmittedandprocessed). *Suchviewnameswillnotberesolvedintheconfigureddefault *waybutratherbetreatedasspecialshortcut. */ publicstaticfinalStringREDIRECT_URL_PREFIX="redirect:"; /** *PrefixforspecialviewnamesthatspecifyaforwardURL(usually *toacontrollerafteraformhasbeensubmittedandprocessed). *Suchviewnameswillnotberesolvedintheconfigureddefault *waybutratherbetreatedasspecialshortcut. */ publicstaticfinalStringFORWARD_URL_PREFIX="forward:"; //Settheviewclassthatshouldbeusedtocreateviews. privateClassviewClass; //SettheprefixthatgetsprependedtoviewnameswhenbuildingaURL. privateStringprefix=""; //thesuffixthatgetsappendedtoviewnameswhenbuildingaURL. privateStringsuffix=""; //viewnames;suchthat'my*','*Report'and'*Repo*' privateString[]viewNames=null; //contenttypeforallviews. privateStringcontentType; //UrlBasedViewResolver的redirectContextRelative的默认值为true, //这意味着,只要重定向的资源以/开头,那么spring会帮你添加contextPath privatebooleanredirectContextRelative=true; //whetherredirectsshouldstaycompatiblewithHTTP1.0clients privatebooleanredirectHttp10Compatible=true; //thenameoftheRequestContextattributeforallviews privateStringrequestContextAttribute; privateintorder=Integer.MAX_VALUE; /**Mapofstaticattributes,keyedbyattributename(String)*/ privatefinalMap<String,Object>staticAttributes=newHashMap<String,Object>(); ... } 5.3 createView方法 publicstaticfinalStringREDIRECT_URL_PREFIX="redirect:"; protectedViewcreateView(StringviewName,Localelocale)throwsException{ //Ifthisresolverisnotsupposedtohandlethegivenview, //returnnulltopassontothenextresolverinthechain. if(!canHandle(viewName,locale)){ returnnull; } //Checkforspecial"redirect:"prefix. if(viewName.startsWith(REDIRECT_URL_PREFIX)){ StringredirectUrl=viewName.substring(REDIRECT_URL_PREFIX.length()); returnnewRedirectView(redirectUrl,isRedirectContextRelative(),isRedirectHttp10Compatible()); } //Checkforspecial"forward:"prefix. if(viewName.startsWith(FORWARD_URL_PREFIX)){ StringforwardUrl=viewName.substring(FORWARD_URL_PREFIX.length()); returnnewInternalResourceView(forwardUrl); } //Elsefallbacktosuperclassimplementation:callingloadView. returnsuper.createView(viewName,locale); } URLBasedViewResolver发现返回的视图名称包含”redirect:”前缀,于是把返回的视图名称前缀”redirect:”去掉,取后面的test.do组成一个RedirectView,RedirectView中将把请求返回的模型属性组合成查询参数的形式组合到redirect的URL后面,然后调用HttpServletResponse对象的sendRedirect方法进行重定向。同样URLBasedViewResolver还支持forword:前缀,对于视图名称中包含forword:前缀的视图名称将会被封装成一个InternalResourceView对象,然后在服务器端利用RequestDispatcher的forword方式跳转到指定的地址。使用UrlBasedViewResolver的时候必须指定属性viewClass,表示解析成哪种视图,一般使用较多的就是InternalResourceView,利用它来展现jsp,但是当我们使用JSTL的时候我们必须使用JstlView。 5.4 一段UrlBasedViewResolver的定义 <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver"> <propertyname="prefix"value="/WEB-INF/"/> <propertyname="suffix"value=".jsp"/> <propertyname="viewClass"value="org.springframework.web.servlet.view.InternalResourceView"/> </bean> 6.InternalResourceViewResolver 内部资源视图解析器 InternalResourceViewResolver会把返回的视图名称都解析为InternalResourceView对象,InternalResourceView会把Controller处理器方法返回的模型属性都存放到对应的request属性中,然后通过RequestDispatcher在服务器端把请求forword重定向到目标URL。 6.1最熟悉的一段配置 <beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver"> <propertyname="prefix"value="/WEB-INF/"/> <propertyname="suffix"value=".jsp"></property> </bean> 总结 ViewResolver解决的事情很单一 通过配置,根据不同策略,找出匹配的JSP(也可以是其他)。 适当添加缓存处理 根据策略不同,返回不同的VIEW,降低耦合度。

优秀的个人博客,低调大师

SparkES 多维分析引擎设计

设计动机 ElasticSearch 毫秒级的查询响应时间还是很惊艳的。其优点有: 优秀的全文检索能力 高效的列式存储与查询能力 数据分布式存储(Shard 分片) 其列式存储可以有效的支持高效的聚合类查询,譬如groupBy等操作,分布式存储则提升了处理的数据规模。 相应的也存在一些缺点: 缺乏优秀的SQL支持 缺乏水平扩展的Reduce(Merge)能力,现阶段的实现局限在单机 JSON格式的查询语言,缺乏编程能力,难以实现非常复杂的数据加工,自定义函数(类似Hive的UDF等) Spark 作为一个计算引擎,可以克服ES存在的这些缺点: 良好的SQL支持 强大的计算引擎,可以进行分布式Reduce 支持自定义编程(采用原生API或者编写UDF等函数对SQL做增强) 所以在构建即席多维查询系统时,Spark 可以和ES取得良好的互补效果。通过ES的列式存储特性,我们可以非常快的过滤出数据,并且支持全文检索,之后这些过滤后的数据从各个Shard 进入Spark,Spark分布式的进行Reduce/Merge操作,并且做一些更高层的工作,最后输出给用户。 通常而言,结构化的数据结构可以有效提升数据的查询速度,但是会对数据的构建产生一定的吞吐影响。ES强大的Query能力取决于数据结构化的存储(索引文件),为了解决这个问题,我们可以通过Spark Streaming有效的对接各个数据源(Kafka/文件系统)等,将数据规范化后批量导入到ES的各个Shard。Spark Streaming 基于以下两点可以实现为ES快速导入数据。 Spark RDD 的Partition 能够良好的契合ES的Shard的概念。能够实现一一对应。避免经过ES的二次分发 Spark Streaming 批处理的模式 和 Lucene(ES的底层存储引擎)的Segment对应的非常好。一次批处理意味着新生成一个文件,我们可以有效的控制生成文件的大小,频度等。 架构设计 下面是架构设计图: spark-es-4.png 整个系统大概分成四个部分。分别是: API层 Spark 计算引擎层 ES 存储层 ES 索引构建层 API 层 API 层主要是做多查询协议的支持,比如可以支持SQL,JSON等形态的查询语句。并且可是做一些启发式查询优化。从而决定将查询请求是直接转发给后端的ES来完成,还是走Spark 计算引擎。也就是上图提到的 Query Optimize,根据条件决定是否需要短路掉 Spark Compute。 Spark 计算引擎层 前面我们提到了ES的三个缺陷,而Spark 可以有效的解决这个问题。对于一个普通的SQL语句,我们可以把 where 条件的语句,部分group 等相关的语句下沉到ES引擎进行执行,之后可能汇总了较多的数据,然后放到Spark中进行合并和加工,最后转发给用户。相对应的,Spark 的初始的RDD 类似和Kafka的对接,每个Kafka 的partition对应RDD的一个partiton,每个ES的Shard 也对应RDD的一个partition。 ES 存储层 ES的Shard 数量在索引构建时就需要确定,确定后无法进行更改。这样单个索引里的Shard 会越来越大从而影响单Shard的查询速度。但因为上层有了 Spark Compute层,所以我们可以通过添加Index的方式来扩大Shard的数目,然后查询时查询所有分片数据,由Spark完成数据的合并工作。 ES 索引构建层 数据的结构化必然带来了构建的困难。所以有了Spark Streaming层作为数据的构建层。这里你有两种选择: 通过ES原生的bulk API 完成索引的构建 然Spark 直接对接到 ES的每个Shard,直接针对该Shard 进行索引,可有效替身索引的吞吐量。

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册