乐视开放平台技术架构-servlet和spring mvc篇

简介: 客户层ope-web采用的是标准的spring mvc架构。定义了三个视图解析器

 在乐视风口浪尖的时候,敢于站出来说我是乐视的而不怕被打脸的,也就是我了。就算我以后不在乐视了,提起来在乐视工作过,我也还是挺骄傲的。因为这是一个有理想,敢拼敢干的公司。想起复仇者联盟里Fury指挥官的一句话:Until such time as the world ends, we will act as though it intends to spin on. 上周我们去怀柔团建,人家都是两个大人住一间,带小孩子的是三个人一间。我带着我家小王子两人住了1380一晚的别墅,据说是最好的房间。像我说过的,每每好事儿都让我摊上了,所以还是该干啥干啥。


  我们部门叫基础业务平台部,负责基本管理乐视视频的视频,音频及所在的专辑数据。单台QPS几千,业内人士表示并发量不大,只是公司的集中缓存差强人意。


  开放平台的系统框架是这样的:


1112728-20170605171737028-2129869231.png


 这是一个很规范的网站系统框架,基本可以满足目前大部分SOA垂直拆分网站架构的需求。项目依赖关系是这样的:


1112728-20170605172253950-2029566421.png


客户层ope-web采用的是标准的spring mvc架构。定义了三个视图解析器:


  1>InternalResourceViewResolver  这个是UrlBasedViewResolver的方便子类。因为前端页面采用的是JSP,这个必然是首选。


  2>CommonsMultipartResolver  涉及上传视频和图片,这个必不可少。需要注意最大上传大小和最大占用内存大小。


  3>SimpleMappingExceptionResolver  定义统一异常处理。我们这个项目中配置的默认跳转页面defaultErrorView是404,异常时携带的属性exceptionAttribute是ex。在exceptionMappings只定义了一个叫AccessException的异常,跳转到errors页面。


说到Spring MVC还是先放一张架构图吧



1112728-20170605184707168-1854649609.png


由图中可以看到整个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里配置一下:



1112728-20170605201001903-295417262.png


  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日志的监听。



相关文章
|
6月前
|
前端开发 Java 微服务
《深入理解Spring》:Spring、Spring MVC与Spring Boot的深度解析
Spring Framework是Java生态的基石,提供IoC、AOP等核心功能;Spring MVC基于其构建,实现Web层MVC架构;Spring Boot则通过自动配置和内嵌服务器,极大简化了开发与部署。三者层层演进,Spring Boot并非替代,而是对前者的高效封装与增强,适用于微服务与快速开发,而深入理解Spring Framework有助于更好驾驭整体技术栈。
|
前端开发 Java 测试技术
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestParam
本文介绍了 `@RequestParam` 注解的使用方法及其与 `@PathVariable` 的区别。`@RequestParam` 用于从请求中获取参数值(如 GET 请求的 URL 参数或 POST 请求的表单数据),而 `@PathVariable` 用于从 URL 模板中提取参数。文章通过示例代码详细说明了 `@RequestParam` 的常用属性,如 `required` 和 `defaultValue`,并展示了如何用实体类封装大量表单参数以简化处理流程。最后,结合 Postman 测试工具验证了接口的功能。
731 0
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestParam
|
7月前
|
Java 数据库 数据安全/隐私保护
Spring Boot四层架构深度解析
本文详解Spring Boot四层架构(Controller-Service-DAO-Database)的核心思想与实战应用,涵盖职责划分、代码结构、依赖注入、事务管理及常见问题解决方案,助力构建高内聚、低耦合的企业级应用。
1409 1
|
JSON 前端开发 Java
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestBody
`@RequestBody` 是 Spring 框架中的注解,用于将 HTTP 请求体中的 JSON 数据自动映射为 Java 对象。例如,前端通过 POST 请求发送包含 `username` 和 `password` 的 JSON 数据,后端可通过带有 `@RequestBody` 注解的方法参数接收并处理。此注解适用于传递复杂对象的场景,简化了数据解析过程。与表单提交不同,它主要用于接收 JSON 格式的实体数据。
1383 0
|
前端开发 Java 微服务
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@PathVariable
`@PathVariable` 是 Spring Boot 中用于从 URL 中提取参数的注解,支持 RESTful 风格接口开发。例如,通过 `@GetMapping(&quot;/user/{id}&quot;)` 可以将 URL 中的 `{id}` 参数自动映射到方法参数中。若参数名不一致,可通过 `@PathVariable(&quot;自定义名&quot;)` 指定绑定关系。此外,还支持多参数占位符,如 `/user/{id}/{name}`,分别映射到方法中的多个参数。运行项目后,访问指定 URL 即可验证参数是否正确接收。
823 0
|
7月前
|
Kubernetes Java 微服务
Spring Cloud 微服务架构技术解析与实践指南
本文档全面介绍 Spring Cloud 微服务架构的核心组件、设计理念和实现方案。作为构建分布式系统的综合工具箱,Spring Cloud 为微服务架构提供了服务发现、配置管理、负载均衡、熔断器等关键功能的标准化实现。本文将深入探讨其核心组件的工作原理、集成方式以及在实际项目中的最佳实践,帮助开发者构建高可用、可扩展的分布式系统。
626 0
|
9月前
|
存储 Java 数据库连接
简单学Spring Boot | 博客项目的三层架构重构
本案例通过采用三层架构(数据访问层、业务逻辑层、表现层)重构项目,解决了集中式开发导致的代码臃肿问题。各层职责清晰,结合依赖注入实现解耦,提升了系统的可维护性、可测试性和可扩展性,为后续接入真实数据库奠定基础。
683 0
|
9月前
|
前端开发 Java API
Spring Cloud Gateway Server Web MVC报错“Unsupported transfer encoding: chunked”解决
本文解析了Spring Cloud Gateway中出现“Unsupported transfer encoding: chunked”错误的原因,指出该问题源于Feign依赖的HTTP客户端与服务端的`chunked`传输编码不兼容,并提供了具体的解决方案。通过规范Feign客户端接口的返回类型,可有效避免该异常,提升系统兼容性与稳定性。
638 0
|
9月前
|
SQL Java 数据库连接
Spring、SpringMVC 与 MyBatis 核心知识点解析
我梳理的这些内容,涵盖了 Spring、SpringMVC 和 MyBatis 的核心知识点。 在 Spring 中,我了解到 IOC 是控制反转,把对象控制权交容器;DI 是依赖注入,有三种实现方式。Bean 有五种作用域,单例 bean 的线程安全问题及自动装配方式也清晰了。事务基于数据库和 AOP,有失效场景和七种传播行为。AOP 是面向切面编程,动态代理有 JDK 和 CGLIB 两种。 SpringMVC 的 11 步执行流程我烂熟于心,还有那些常用注解的用法。 MyBatis 里,#{} 和 ${} 的区别很关键,获取主键、处理字段与属性名不匹配的方法也掌握了。多表查询、动态
269 0

热门文章

最新文章