在乐视风口浪尖的时候,勇于站出来讲我是乐视的而不怕被打脸的,也就是我了。就算我之后不在乐视了,提起来在乐视工做过,我也仍是挺骄傲的。由于这是一个有理想,敢拼敢干的公司。想起复仇者联盟里Fury指挥官的一句话:Until such time as the world ends, we will act as though it intends to spin on. 上周咱们去怀柔团建,人家都是两个大人住一间,带小孩子的是三我的一间。我带着我家小王子两人住了1380一晚的别墅,听说是最好的房间。像我说过的,往往好事儿都让我摊上了,因此仍是该干啥干啥。前端
咱们部门叫基础业务平台部,负责基本管理乐视视频的视频,音频及所在的专辑数据。单台QPS几千,业内人士表示并发量不大,只是公司的集中缓存差强人意。web
开放平台的系统框架是这样的:redis
这是一个很规范的网站系统框架,基本能够知足目前大部分SOA垂直拆分网站架构的需求。项目依赖关系是这样的:spring
客户层ope-web采用的是标准的spring mvc架构。定义了三个视图解析器:编程
1>InternalResourceViewResolver 这个是UrlBasedViewResolver的方便子类。由于前端页面采用的是JSP,这个必然是首选。后端
2>CommonsMultipartResolver 涉及上传视频和图片,这个必不可少。须要注意最大上传大小和最大占用内存大小。缓存
3>SimpleMappingExceptionResolver 定义统一异常处理。咱们这个项目中配置的默认跳转页面defaultErrorView是404,异常时携带的属性exceptionAttribute是ex。在exceptionMappings只定义了一个叫AccessException的异常,跳转到errors页面。安全
说到Spring MVC仍是先放一张架构图吧架构
由图中能够看到整个spring mvc核心是dispatcherServlet,客户端将请求提交给它,它查询web.xml里的mapping定义找到Controller。咱们项目mapping定义是并发
<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/applicationContext.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
全部的请求都走这个dispatcherServlet,按照applicationContext.xml的配置处理,这里面配置了自动扫描的controller路径和上面提到的视图解释器。来看一眼dispatcherServlet的核心源码:
protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); //文件上传解析,若是请求类型是multipart将经过MultipartResolver进行文件上传解析; initLocaleResolver(context); //本地化解析 initThemeResolver(context); //主题解析 initHandlerMappings(context); //经过HandlerMapping,将请求映射处处理器 initHandlerAdapters(context); //经过HandlerAdapter支持多种类型的处理器 initHandlerExceptionResolvers(context); //若是执行过程当中遇到异常将交给HandlerExceptionResolver来解析 initRequestToViewNameTranslator(context); //直接解析请求到视图名 initViewResolvers(context); //经过ViewResolver解析逻辑视图名到具体视图实现 initFlashMapManager(context); //flash映射管理器 }
从命名就能够看出,这里面主要用到了策略模式,对不一样的视图采用不一样的策略。ApplicationContext是一个抽象接口,spring的上下文将框架内部的各个组件信息都经过一个context暴露给外部,是一个门面模式。
dispatcherServlet在进行请求分发的时候还提供了一些服务:
1>保存现场:保存request熟悉的快照,以便能在必要时恢复。
2>将框架须要的对象放入request中,以便view和handler使用。
3>在请求分发后恢复现场。
建议你们看看DispatcherServlet的源码,常常作spring mvc项目的话,相信源码不难看懂。你们可能常常遇到的问题,好比看了<Java并发编程实践>这本书,感受这些东西项目中用不到啊。其实不是这样,这本书很基础,里面的东西都用到了,只是封装在框架里了,不少人没仔细研究而已。记得书里讲安全发布的时候讲到使用Collections.unmodifiableMap来发布一个只读的map。这个在DispatcherServlet源码里对它的运用很是的典型:将flashmap的一个快照保存在request的属性里以备查看用。
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response); if (inputFlashMap != null) { request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); }
从源码到原理,最基础的,好比:调用构造器来建立一个Java类的时候,要知道这个构造器其实是一个静态方法。因此第一次调用构造器建立对象的时候,或者访问这个类的静态方法或者静态成员的时候,Java解释器先要定位其字节码(class)文件,加载了字段文件后,要进行全部的静态初始化工做,这个工做只进行一次。
多想一想,从编码到排查问题,相信都不会无从下手。
上面说了在spring里能够配置异常处理页面,这个不经过spring直接走servlet也能够,只要在web.xml里配置一下:
DispatcherServlet还实现了一个很重要的功能:拦截器,咱们项目中主要用它来作用户身份验证。用户身份验证要走乐视网统一的SSO,在隔着我工位4,5排的用户中心组那边。只是一个外部接口的调用,可是总不能每次用户发一个请求就调一次sso啊,外部调用network hops延时很严重的,因此这时候就用到了集中式缓存。取了一次以后将验证身份的token存于redis里,有效期24小时。
咱们组和SSO组中间隔着前端组。JSP的静态页和JS都是前端提供的。为了进一步解耦先后端的工做,数据的加载都走的是js异步调用,数据由前端去渲染。为了应对前端的修改,jSP中大量引入静态分片。这个静态分片由一个后台服务定时将最新的分配刷新到本地。路径保存在本地缓存中。本地缓存用的google的guava工具包。
再说拦截器,拦截器和servlet的过滤器很像,它们都是AOP变成思想的体现。这地方要注意:在web.xml配置的都是servlet的功能,在applicationContext里配置的是spring mvc的功能。它们的区别也在这个地方。由于Filter是Servlet的规范,仅能在Servlet先后起做用。而interceptor和spring能够亲密互动,可以深刻到方法先后,异常抛出先后等,能够访问Action上下文,值栈里的对象,可屡次被调用。
通常项目中用过滤器的就是utf8字符过滤器,在web.xml的配置以下:
<filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
Servlet规范中还定义了一种特殊类,监听器,用于监听域对象的建立与销毁,以及这些域对象属性的修改事件。咱们项目中它来配置logback日志的监听。