SpringMVC

Posted tripledemo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringMVC相关的知识,希望对你有一定的参考价值。

源码:https://github.com/tripleDemo/springmvc

三层架构

Web开发的最佳实践就是根据功能职责的不同,划分为控制层,划分为控制层、业务层、持久层。

技术图片

 

MVC原理

MVC模型:是一种架构型的模式,本身不引入新功能,只是帮助我们将开发的结构组织的更加合理,使展示与模型分离、流程控制逻辑、业务逻辑调用与展示逻辑分离---->责任分离。

MVC框架的功能作用(WEB开发常见功能):

MVC令程序开发有章可循,但是表现层的困惑来了,因为需要处理的功能太多:设置编码、接受请求参数、输入校验、参数类型转换、把参数封装成对象、文件上传、处理响应、国际化处理、自定义标签等。

技术图片 

 

CS架构标准的MVC中模型能主动推数据给视图进行更新(观察者设计模式,在模型上注册视图,当模型更新时自动更新视图)。但在Web开发中模型是无法主动推给视图(无法主动更新用户界面),因为在Web开发是请求-响应模型。

Front Controller模型要求在WEB应用系统的前端(Front)设置一个入口控制器(Controller),所有的request请求都被发往该控制器统一处理,处理所有请求共同的操作。学习MVC框架:都得先配置前端控制器。

 

什么是前端控制器

Front Controller模式要求在WEB应用系统的前端(Front)设置一个入口控制器(Controller),是用来提供一个集中的请求处理机制,所有的请求都被发往该控制器统一处理,然后把请求分发给各自相应的处理程序。一般用来做一个共同的处理,如权限检查,授权,日志记录等。因为前端控制的集中处理请求的能力,因此提高了可重用性和可拓展性。

 

什么是SpringMVC

MVC框架,它解决WEB开发中常见的问题(参数接收、文件上传、表单验证、国际化、等等),而且使用简单,与Spring无缝集成。Spring3.0后全面超越Struts2,成为最优秀的MVC框架(更安全,性能更好,更简单)

支持RESTful风格的URL请求,非常容易与其他视图技术集成,如VelocityFreeMarker

采用了松散耦合可插拔组件结构,比其他MVC框架更具扩展性和灵活性。

(SpringMVC是同步阻塞的IO模型,资源浪费相对来说比较严重,当处理一个比较耗时的任务时,服务器的线程一直在等待接收文件,而Spring WebFlux(Spring的异步非阻塞Web框架)可以做到异步非阻塞。)

SpringMVCStruts2对比:

  1. Spring MVC的前端控制器是Servlet,而Struts2Filter
  2. Spring MVC会稍微比Struts2快些,Spring MVC是基于方法设计,处理器是单例,而Struts2是基于类,每次发一次请求都会实例一个新的Action对象,Action是多例的。
  3. Spring MVC更加简洁,开发效率Spring MVCStruts2高,如支持JSR303校验,且处理AJAX请求更方便。
  4. Struts2OGNL表达式使页面的开发效率相比Spring MVC更高些,但是Spring MVC也不差。

 

SpringMVC核心组件分析

1.前端控制器DispatcherServlet

不需要我们开发,由框架提供,需要在web.xml中配置。

作用:接受请求,处理响应结果,转发器,中央处理器

2.处理器映射器HandlerMapping

不需要我们开发,由框架提供

作用:根据请求URL,找到对应的Handler

3.处理器适配器HandlerAdapter

不需要我们开发,由框架提供

作用:调用处理器(Handler/Controller)的方法

4.处理器Handler(又名Controller),后端控制器

需要我们开发,必须按照HandlerAdapter的规范去开发

作用:接受用户请求数据,调用业务方法处理请求

5.视图解析器ViewResolver

不需要我们开发,由框架/第三方提供

作用:视图解析,把逻辑视图名称解析成真正的物理视图,支持多种视图技术,JSTLViewFreeMarkerPdfView...

6.视图View

需要我们开发

作用:把数据展现给用户

 技术图片

 

@RequestMapping

RequestMapping是一个用来处理请求地址映射的注解,可以贴在类或方法上。贴在类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

RequestMapping注解有六个属性,下面我们把她分成三类进行说明。

1、 value, method;

value     指定请求的实际地址,path一样,指定请求URL

method  指定请求的method类型, GETPOSTPUTDELETE等;

2、 consumes,produces;

consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;

produces:    指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;

3、 params,headers;

params: 指定request中必须包含某些参数值是,才让该方法处理。

headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求。

 

前端控制器url-pattern拦截方式

第一种:*.拓展名,比如*.do,古老的方式,不会导致静态资源文件(比如图片,html,css,js这些)被拦截问题,但是不支持RESTfull编码风格。

第二种:/,支持RESTfull风格,但是会导致静态资源文件被拦截。

第三种:/*,错误的方式,可以请求到Controller方法,但是跳转到JSP时会被拦截,JSP不能正常显示。

 

(启动项目的时候,启动Tomcat,加载web.xml文件,启动项目,加载web.xml文件,项目中的web.xml所映射的 / 所覆盖了Tomcatweb.xml配置的映射规则。)

解决静态资源文件被拦截问题:

  1. 使用<mvc:default-servlet-handler/>(在开发中使用比较多)

将静态资源有SpringMVC交回给Servlet来处理

原理:SpringMVC上下文中定义了一个DefaultServletHttpRequestHandler,对所有前端控制器的请求做筛选和盘查,如果发现没有经过映射请求,就交给Tomcat的默认servlet来处理。

  1. 资源映射:<mvc:resources location="/" mapping="/**"/>

SpringMVC自己来处理静态资源,而且还附件了很多功能

(SpringBoot运行把静态资源放在任何地方,比如WEB-INF里面,resources目录,设置把JS等静态文件打包放在jar中,也能找到。都可以通过location去指定静态资源路径,locationResource类型,可以使用前缀,如classpath:)

 

请求和响应

处理多个对象封装

技术图片

  1. 框架把ServletRequest对象和请求参数传递给DataBinder
  2. DataBinder首先调用Spring Web环境中的ConversionService组件,数据类型转换和格式化操作
  3. DataBinder调用Validator组件,对绑定参数数据做合法性校验
  4. DataBinder最后输出数据绑定的结果----->BindingResult
  5. 最后SpringMVC框架会把BindingResult中的数据,分别传递给响应的处理方法

 

处理JSON的注解:

@ResponseBody:处理响应,把对象转换为JSON字符串

 贴到方法上:只针对当前方法做JSON处理

 贴到类上:会对当前类中所有的方法做JSON处理

@Restcontroller@Controller + @ResponseBody

@RequestBody:处理请求,用于读取HTTP请求的内容,把JSON格式的请求数据封装成对象  

一般的请求数据格式:

application/x-www-form-urlencoded:传统的key-value格式,处理起来非常方便,不需要RequestBody都可以,贴上也可以

application/multipart:文件上传的请求,SpringMVC装饰设计模式,既能处理文件上传,也能处理普通表单数据

application/json:参数是JSON格式的,此时就必须使用RequestBody

 

RequestContextHolder

 技术图片

SpringMVC提供了一个非常方便的工具类,能够在任意地方很方便的获取requestsession对象。RequestContextHolder顾名思义,持有上下文的Request容器。

public class UserContext {

  public static final String USER_IN_SESSION = “user_in_session”;

  private static HttpSession getSession() {

    return ((ServletRequestAttributes(RequestContextHolder.getRequestAttributes())).getRequest().getSession();

  }

  public static void setCurrentUser(Employee current) {

    If(current != null){

      getSession().setAttribute(USER_IN_SESSION,current);

    }else {

      getSession().invalidate();

    }

  }

   public static Employee getCurrentUser() {

    return (Employee) getSession().getAttribute(USER_IN_SESSION);

  }

}

 

拦截器

应用场景
1、日志记录,可以记录请求信息的日志,以便进行信息监控、信息统计等。
2、权限检查:如登陆检测,进入处理器检测是否登陆,如果没有直接返回到登陆页面。
3、性能监控:典型的是慢日志。

public interface HandlerInterceptor {

  default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

    return true;

  }

  default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable ModelAndView modelAndView) throws Exception {}

   default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable Exception ex) throws Exception {}

}

1.preHandle方法:在请求达到Handler之前,先执行这个前置处理方法。当该方法返回false时,请求直接返回,不会传递到链中的下一个拦截器,更不会传递到处理链末端的Handler中。只有返回true时,请求才向链中的下一个处理节点传递。

2.postHandle方法:控制器方法执行后,视图渲染之前执行(可以加入统一的响应信息)

3.afterCompletion方法:视图渲染之后执行(处理Controller异常信息,记录操作日志,清理资源等)

开发SpringMVC拦截器步骤:

1.定义拦截器类实现接口org.springframework.web.servlet.HandlerInterceptor

2.在xml中配置拦截器

<!-- 注册拦截器 -->

<mvc:interceptors>

     <mvc:interceptor>

        <!-- 对哪些资源做拦截

        /*:只能拦截一级路径

        /**:可以拦截一级或多级路径

         -->

        <mvc:mapping path=""/>

        <!-- 排除不需要被拦截的资源 -->

        <mvc:exclude-mapping path=""/>

        <!-- 拦截器类 -->

        <bean class=""></bean>

     </mvc:interceptor>

</mvc:interceptors>

 

异常处理

SpringMVC统一处理异常的解决和实现过程

SpringMVC处理异常有三种方式:

(1)使用SpringMVC提供的简单异常处理器SimpleMappingExceptionResolver;

<!-- 配置异常处理器 -->

<bean class=”org.springframework.web.servlet.handler.SimpleMappingExceptionResolver”>

  <!-- 设置错误的视图 -->

  <property name=”defaultErrorView” value=”” />

  <!-- 在错误页面,获取异常信息对象变量名称,缺省exception -->

  <property name=”exceptionAttribute” value=”” />

  <!-- 根据不同类型异常,跳转到不同的错误页面 -->

  <property name=”exceptionMappings”></property>

</bean>

(2)实现Spring的异常处理接口HandlerExceptionResolver自定义自己的异常处理器;

(3)使用@ExceptionHandler注解实现异常处理;

 

数据校验

Web开发任务之一,在SpringMVC中有两种方式可以实现,分别是使用Spring自带的验证框架和使用JSR303实现,也称之为spring-validatorjsr303-validator,在开发中更建议使用jsr303-validator

jsr303-validator标准的校验框架

步骤

1.SpringMVC 虽然提供了对这套标准的支持,提供了接口,但是本身并没有提供JSR-303 的实现,一般会引入 Hibernate-validator jar 包。

classmate-1.3.4.jar

javax.el-3.0.1-b09.jar

jboss-logging-3.3.2.Final.jar

validation-api-2.0.1.Final.jar

2.SpringMVC中,可直接通过注解驱动的方式进行数据校验SpringLocalValidatorFactory即实现SpringValidator接口,也实现了jsr303Validator接口。

3.Spring在进行数据绑定时,可同时调用校验框架完成数据校验工作, bean对象的属性标准@NotNull @Max @min 注解标签,来指定他的校验规则

4. handler 方法上将需要校验的对象加上@validated标签,并且紧随其后加上 BindingResult 对象接收校验信息

以上是关于SpringMVC的主要内容,如果未能解决你的问题,请参考以下文章

SpringMVCSpringMVC系列2之@RequestMapping 映射约束请求

SpringMVCSpringMVC简介&第一个SpringMVC项目

SpringMVCSpringMVC简介&第一个SpringMVC项目

SpringMVC概述+SpringMVC运行流程+SpringMVC搭建

不得不看的SpringMVC篇!!!(概述+SpringMVC运行流程+SpringMVC搭建)

SpringMVC