Spring-MVC

1.1 mvc思想,前端控制器,springmvc概述,配置版spring mvc程序

MVC思想

MVC概念:模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范,将业务逻辑、数据、显示分离的方式来组织代码

MVC作用:降低视图和业务逻辑之间的双向耦合

MVC是架构模式

概念细分:模型:数据模型,提供展示的数据;视图:显示数据模型;控制器:接受用户请求,委托给模型处理,并将模型响应的结果返回给视图,由视图进行展示。

典型的MVC:servlet+jsp+javabean

前端控制器(中心控制器)

概念:是用来提供一个集中的请求处理机制,所有的请求都被发往该控制器统一处理,而后将请求分发给各自响应的处理程序。一般用来做权限检查、授权、日志记录等。

作用:因为前端控制集中处理请求的能力,提高了可重用性和扩展性

原理:类似Filter过滤器。一般称之为处理器(Controller).mvc框架必须在web.xml中配置处理器,要么是Filter,要么是Controller.springmvc的前端控制器基于Servlet.

springmvc

定义:spring framework的一部分,是基于java实现MVC的轻量级WEB框架

特点:高效、基于请求响应、与spring无缝兼容、约定优于配置、功能强大-Restful

与struts2对比

前端控制器:struts2是filter;mvc是controller

处理器:struts2基于类,多例;mvc基于方法,单例

mvc支持JSP303(JAVAEE6中的一项子规范)校验,且处理AJAX请求更方便,开发更简介,效率更高

springmvc程序(配置版)

1.导入依赖:org.springframework.spring-webmvc,javax.servler-servlet.api等

2.web.xm配置前端控制器 org.springframework.web.servlet.DispatcherServle(初始化spring容器)

3.配置springmvc核心配置文件 springmvc-servlet.xml

配置处理器映射器

(<bean clas="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">),目的:选择那个处理器(Controller)处理请求

配置处理器适配器

(<bean calss="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter">),目的:调用处理器处理请求的方法

配置视图解析器

(<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">),目的:处理dispatcherServlet(前端控制器)给它的ModelAndView

编写自定义controller,实现controller接口或添加注解@Controller,返回一个ModelAndView,装数据,封视图

spring-mvc-servler.xml中配置自定义controller,向ioc容器注入bean, 目的:通过处理器映射器在url寻找ID为指定配置值的jsp

4.编写自定义Controller类,实现Controller接口

5.WEB-INF文件夹下创建自定义jsp文件

1.2 spring mvc执行原理、核心组件、注解版spring mvc程序

1.1 执行过程

01 用户发送请求至DispatcherServlet(前端控制器)

02 DispatcherServlet收到请求后调用HandlerMapping(处理器映射器)

03 HandlerMapping找到具体的处理器,生成处理器对象及其拦截器(如果有的话)返回给DispatcherServlet

04 DispatcherServlet调用HandlerAdapter(处理器适配器)

05 HandlerAdapter经过适配调用具体的处理器的某个方法(Handler/Controller)

06 Controller执行完毕后返回ModelAndView对象

07 HandlerAdapter将Controller返回的ModelAndView对象返回至DispatcherServlet

08 DispatcherServlet将ModelAndView给到ViewResolver(视图解析器)

09 ViewResolver解析完毕后返回View给DispatcherServlet

10 DispatcherServlet根据View渲染视图(将模型数据填充至事务中)

11 DispatcherServlet响应用户

1.2 SpringMVC核心组件

DispatcherServlet(前端控制器),核心且必须

作用:接受用户请求,响应结果,相当于中央处理器,降低了组件之间的耦合性

HandlerMapping 处理器映射器,必要组件

作用:根据请求URL,找到对应的Handler(Controller),帮助DispatcherServler找到对应的Controller

HandlerInterceptor Handler(Controller)执行前后拦截器

HandlerInterceptor是接口,包含preHandle、postHandle、afterCompletion分别对应执行前、执行中、执行后,需要执行的3个方法

HandlerExecutionChain HandlerMapping返回给DispatcherServler的执行链

HandlerAdapter 处理器适配器,必要组件

作用:将自定义Controller适配成DispatcherServlet可使用的Handler

Handler(Controller) 处理器(需工程师开发)

注意:编写Handler需要按照HandlerAdapter的要求去编码,确保HandlerAdapter可以正确执行自定义的Handler。HandlerAdapter可看作相对于DispatcherServlet的后台控制器

ModelAndView

SpringMVC中Model的一种表现形式

ViewResolver 视图解析器,必要组件

作用:进行视图解析,根据逻辑实体转化为真正的视图

View 视图(需工程师开发)

一个接口,实现类支持不同的类型(html,jsp,freemarker,pdf等)

1.3 使用注解开发SpringMVC

优点:一个controller类中可以有多个处理方法;请求映射无需在XML中配置,效率更高

实现过程

01 pom.xml添加防止maven资源过滤的配置

02 导入springmvc相关依赖

03 配置web.xml

04 resource目录下配置springmvc-servlet.xml (配置处理器映射器、处理器适配器、视图解析器)

05 编写自定义controller

05 创建视图层 xx.jsp

1.4 spring IOC注解回顾

@Controller 控制层

@Service 业务逻辑层

@Repository 数据持久层

@Component 其他组件通用注解

1.5 MVC注解解析器 <mvc:annotation-driver>

此解析器会自动注册RequestMappingHandlerMapping、RequestMappingHandlerAdapter、ExceptionHandlerExceptionResolver 三大组件

同时还支持

使用ConversionService实例对表单数据进行类型转换

使用@NumberFormat、@DateTimeFormater 注解对数据进行格式化操作

使用@Valid注解对javabean进行JSR303验证(JSR是Java Specification Requests的缩写,是Java规范提案,JSP303是JavaEE6中的一项子规范,叫Bean Validation)

使用@RequestBody和@ResponseBody注解读写JSON

1.6 @RequestMapping注解

用来处理请求地址映射的注解,可用在类或方法上。

用于类上,表示类中所有请求的方法以此路径为父路径

有6个属性

value:指定请求url

method:指定请求method类型,如GET、POST、PUT、DELETE等

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

produces:指定返回的内容类型,如application/json;

params:请求参数resutst中必须包含此注解中指定的参数,方法才会处理

headers:请求头中必须包含此注解指定的参数,方法才会处理

1.3 静态资源访问问题、处理器方法响应类型、请求跳转

1.1 静态资源访问问题

问题描述:前端控制器拦截路径设置为/时,出现静态资源无法访问

问题原因:tomcat处理静态资源的servlet默认路径为/,项目启动,tomcat下的web.xml文件先加载,项目中的web.xml后加载,如果映射路径相同,项目中的web.xml会覆盖tomcat中web.xml中相同的配置。即DispatcherServlet的映射路径覆盖了Tomcat默认对静态资源处理的路径,会将静态资源当作controller处理,故此产生。

在SptingMVC上下文中定义一个

解决方案

方案一:使用 <mvc:default-servlet-handler/> (推荐使用)

原理:SpringMVC中定义个DefaultServletHttpRequestHandler,会对进入DispatcherServlet的请求进行筛查,如果没有经过映射请求,将其交由tomcat默认的serlvet处理,非静态资源,才DispatcherServlet继续处理

方案二:mvc:resource资源控制

springmvc-servlet.xml中配置 <mvc:resources location="/" mapping="/**"/> 例如:<mvc:resources location="/WEB-INF/Views" mapping="/**"/>

将web下的目录表示为根目录,/**表示根目录。SpringMVC自己处理静态资源,还附件了很多功能

方案三:url-pattern拦截方式

1.2 处理器方法响应处理(Contrlere)

返回void:就是将controller当作Servlet来使用,在方法上可通过形参request和response来指定响应结果

request请求转发界面:request.getRequestDispatcher("页面路径").forward(request,response);

response重定向界面:response.sendRedirect("url");

response指定响应界面:response.setContentType("text/json;charset=utf-8");response.getWriter().pring(JSON字符串)

返回ModelAndView: return new ModelAndView();

常用方法:addObject(key,value);

setViewName();

addObject(value);此方法对应key为value类型首字母小写

同时每次方法都需要配置很长的物理视图地址,可在xml文件中统一配置前缀和后缀。只需告知框架逻辑视图名称就可以了

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

<property name="prefix" value="/WEB-INF/Views/">

<property name="suffix" value="/*.jsp" >

<bean>

返回String:返回String类型和共享数据,使用广泛

返回String,此时物理视图路径为 前缀+逻辑哦视图+后缀

redirect前缀方式,表示重定向。重定向后地址栏变为重定向后的地址, 不会共享之前请求的数据

forward转发模式,表示请求转发,转发后浏览器地址不变,共享之前请求中的数据。

1.3 请求跳转

请求转发:

例如:return "forward:/hello.html";

原理:request.getRequestDispatcher().forward(request,response);

效果:浏览器地址不变,可以共享请求数据,会导致表单重复提交

重定向:

例如:return "redirect:/hello.html";

原理:response.sendRedirect("");

效果:浏览器地址会变,不会共享之前请求的数据,不会导致表单重复提交

URL重定向共享数据

传统方式,重定向是因为2次不同的请求,因此无法共享数据。

如何传递共享数据:Spring从3.1版本开始通过Flash属性提供了重定向传值方式,在方法上添加一个新的参数类型 RedirectAttributes,并在处理方法中调用 addFlashAttribute(String key,Object val)来保存需要共享的数据;

如何接受共享数据:在重定向的URL方法中,添加参数 @ModalAttribute("上述方法中调用addFlashAttribute方法中的key") String s,即可数据共享过来

1.4 处理器方法参数的处理

1.1 通过ServletAPI,(方法参数:HttpServletRequest;@Autowired ServletContext)

1.2 简单类型参数,controller方法形参和请求参数同名可直接接受;不同名可使用@RequestParam注解修饰形参,设置对应的参数名

1.3 POST请求中文乱码问题:web.xml中配置编码过滤器

1.4 Restful风格传参:例如:@RequestMapping("hello/{id}") public void test(@PathVariable("id") String id){...}

1.5 数组和list类型的参数:方法中使用数组可以直接接收多个参数(例如:localhost:8080/test?ids=1&ids=2);方法中参数类型是List,不可直接接收,可在对象中存在集合

1.6 JavaBean类型参数:方法参数为某实体类,可以将请求参数自动封装到controller方法的形参中,但是必须确保参数名和属性名一致

1,7 ModelAttribute注解:给model数据或符合类型参数使用此注解描述,即可实现参数共享

1.8 请求头、Cookie等:

获取请求头信息 @RequestHeader 或者request.getHeader("")

获取Cookie信息 @CookieValue

操作HttpSession 通常情况下@ModelAttribute注解修饰的参数是存储在request中的,在类上添加@SessionAttributes("此为@ModelAtttibute对应的key,多个用逗号分隔")注解,即可声明HttpSession存储级别,这些属性会自动存储到session中

1.9 数据绑定流程

SpringMVC通过反射机制针对目标处理方法的签名进行分析,将请求信息绑定到处理方法的形参中,数据绑定核心组件是DataBinder类。

数据绑定流程

框架将ServletRequest对象和请求参数传递给DataBinder

DataBinder首先调用ConversionService,进行数据类型转换和格式化操作,将ServletRequest中的信息填充到形参对象中

然后DataBinder调用Validator组件对已绑定的请求消息数据的形参对象进行数据合法性校验

DataBinder最后输出数据绑定结果对象BindingResult(包含已完成数据绑定对象和校验错误信息对象)

最终SpringMVC框架将BindingResult中的数据,分别赋给不同的处理方法

1.10 多对象封装参数传递(了解)

如果需要传递两个对象参数,并且都有相同的属性,此时请求参数不知道把值封装到哪一个参数中,需要为对象数据设置绑定规则

@InitBinder注解:自定义数据绑定注册支持,用于将请求参数转换到命令对象属性的对应类型

@InitBinder注解标注的方法,可对DataBinder的子类WebDataBinder对象进行初始化,用于完成请求参数到JavaBean的属性绑定

注意:@InitBinder标注的方法不能有返回值,必须是void;@InitBinder标注的方法参数通常是WebDataBinder

1.11 JSON数据处理

Jackson是java开源的json工具库,可轻松将java转换为json对象或者xml文档,也可逆向转换

SpringMVC中处理json的注解

@RequestBody:读取请求JSON字符串,转换为对象

@ResponseBody:将响应的对象转换成JSON字符串

@RestController:@Controller+@ResponseBody

1.12 日期类型处理

参数处理

方法只有一个Data参数,在参数上添加注解@DateTimeFormat(pattern = "yyyy-MM-dd")

方法参数是Entity,在属性上添加注解 @DateTimeFormat(pattern = "yyyy-MM-dd")

方法参数是Entity,如果类中有多个属性都是Date类型,则可创建一个类,使用@ControllerAdvice注解,类中添加一个方法,参数为WebDataBinder,方法使用@InitBinder修饰

后台响应JSON格式Date类型处理

解析字段上添加注解:@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss:SSS",timeZone="GMT+8")

1.5 CRUD操作

1.1 使用XML的方式:

web.xml;applicationContext.xml;springmvc-servlet.xml

1.2 使用注解+Class的方式:

创建类继承AbstractAnnotationConfigDispatcherServletInitializer代理web.xml;

创建类代替applicationContext.xml;

创建类实现WebMvcConfigurer接口代替springmvc-servlet.xml,此类使用@EnableWebMvc注解修饰,此注解做用是启动springmvc

1.6 拦截器原理

1.1 类似Servlet中的Filter,用于对处理器进行预处理和后处理

1.2 springmvc拦截器和Servlet过滤器的区别

过滤器:依赖Servlet容器,实现上基于函数回调,可对几乎所有请求进行过滤,但是只能在容器初始化时调用一次。可做一些过滤操作,例如修改字符编码、过滤低俗、危险文字等

拦截器:依赖于web框架,实现上基于java反射机制,属于AOP的应用,同一个拦截在在一个controller生命周期内可以多次调用

1.3 常见应用场景:日志记录、权限检查、性能监控、通用行为、进入处理器打开Session,完成后关闭Session;本质上还是AOP操作,符合横切关注点的都可以通过拦截器处理

1.4 springmvc提供的拦截器接口:

HandlerInterceptor,包含3个方法

preHandle(预处理方法,返回:true表示继续,false流程中断)

postHandle(后处理回调方法,controller之后视图返回之前调用(可对ModelAndView进行处理再返回),无返回值)

afterCompletion(请求完成后并且preHandle方法返回true,才会调用此回调方法,无返回值,)

1.5 拦截器适配器 HandlerInterceptorAdapter

部分源码:abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor

说明:适配器模式的实现,包含4个方法,分别为 preHandle、postHandle、afterCompletion、afterConcurrentHandlingStarted,允许只实现需要的回调方法

preHandle、postHandle、afterCompletion 含义和HandlerInterceptor一致

afterConcurrentHandlingStarted:异步请求处理开始时被调用

1.6 自定义拦截器

继承拦截器适配器

springmvc.xml文件中配置拦截器

1.7 spring boot中filter和interceptor的使用

Interceprot拦截器

拦截器(Interceptor)依赖于web框架,常在springmvc中使用(故此 Interceptor依赖于springmvc框架)

Interceptor基于java的反射机制,属于AOP的一种运用

所有拦截器都需要实现HandlerInterceptor接口(重写afterHandle、postHandle、agterCompletion方法)

优点:基于web框架的调用,可使用spring依赖向拦截器注入bean对象进行一些操作,同一个拦截器在一个controller生命周期内可多次调用

缺点:只能对controller进行拦截,对其他请求例如静态资源无法拦截

1.1 拦截器中的方法执行流程

请求到达DispatcherServler,将请求送至Interceptor,执行preHandle方法,返回false结束整个流程,返回true进行下一步

请求到达controller,执行处理器逻辑,进行业务逻辑处理

业务逻辑处理完毕之后,执行postHandle

视图解析和视图渲染

调用afterCompletion方法

1.2 传统项目中拦截器的配置

基于springmvc项目,在springmvc.xml文件中添加 <mvc:interceptors>标签进行配置

基于springboot2.1.2 整合拦截器实现步骤

自定义拦截器类实现HandlerInterceptor接口或者继承HandlerInterceptorAdapter抽象类

自定义接口注册拦截器(注意类上需要添加@Configuration),实现WebMvcConfigurer接口,重写addInterceptors方法,方法中使用InterceptorRegistry来进行指定拦截的路径与不拦截路径

多个拦截器的执行顺序

如果多个拦截器对同一个请求进行拦截,并且所有拦截器的preHandle方法都为true,则会按照责任链模式,preHandle方法会先注册先执行,postHandle和adterCompletion方法是先注册后执行

如果多个拦截器对同一个请求进行拦截,其中有个拦截器的preHandle返回值为false,则后续的拦截器、处理器和所有拦截器的postHandle方法都不会执行。afterCompletion方法则只会执行preHanle方法返回true的拦截器的方法,顺序是先注册后执行。

Filter过滤器

1.1 基于spring的filter,配置在web.xml中,依赖于servlet容器

优点:实现上基于函数回调,可几乎对所有请求都可以进行拦截

缺点:一个过滤器只会在容器启动时调用一次

使用场景:设置字符编码,拦截敏感词、禁止浏览器缓存所有动态页面、实现用户自动登录、实现URL级别的权限认证等

传统基于spring的fllter实现方式

自定义类实现Filter接口,重写doFilter方法

web.xml中通过<filter>和<filter-mappin>标签对编写的filter类进行注册,并配置拦截的资源

可以编写多个filter,组成filter链,根据注册顺序来决定执行顺序

1.2 基于springboot整合filter

方式一:FilterRegistrationBean注册实现(编写类实现Filter接口;配置类中注册自定义filter并设置拦截规则)

方式二:@WebFilter和@ServletCompantScan(编写类实现Filter接口,使用@WebFilter修饰配置过滤器名称和拦截规则;启动类添加@ServletCompantScan)

@ServletCompantScan作用:可将类上包含@WebServlet、@WebFilter、@WebListener自动注册

注意:因为filter是被server调用,interceptor是被spring调用,所以filter执行优于interceptor

1.8 全局异常@ControllerAdvice

1.1 为何使用全局异常?

springBoot会将所有的异常发送至server.error.path(默认为/error)的控制器方法中进行处理,详细代码位于BasicErrorController,提示相对不友好

未使用全局异常,代码中存在大量的try-catch,难以阅读,还可能因为异常捕获导致@Transactional失效

1.2 使用@ControllerAdvice和@ExceptionHandler实现自定义全局异常

1.3 @ControllerAdvice作用:处理controller层的异常信息,未进入controller则不会处理。未进入controller可使用BasicErrorController进行处理

1.4 @RestControllerAdvice=@ResponseBody+@ControllerAdvice

1.5 使用全局异常操作步骤

自定义异常类继承RuntimeException

封装异常信息模板

自定义全局异常处理类,编写类继承ResponseEntityExceptionHandler,并类上添加注解@RestControllerAdvice,定义的方法上添加@ExceptionHandler即可实现异常捕捉,方法的返回值是封装的异常信息模板

后续代码中通过 throw new 自定义异常即可进行全局处理

1.9 使用JSR-303 Validation进行后端验证

1.1 JST-303简介

JSR-303 是 JAVA EE 6 中的一项子规范,叫做 Bean Validation,官方参考实现是Hibernate Validator,此实现与Hibernate ORM无关。

JSR-303是数据验证的规范,Hibernate Validator是springmvc对JSP-303的支持

1.2 JSR-303基本校验规则

空检查

@Null、@NotNull、@NotBlank、@Empty

Boolean检查

@AssertTrue、@AssertFalse

长度检查

@Size、@Length

日期检查

@Past、@Future、

数值检查

@Min、@Max、@DecimalMax、@DecimalMin、@Valid、@Email

1.3 使用位置 可添加在实体类字段或controller中的方法参数上

1.10 文件上传下载

1.1 为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。

一旦设置了enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据

springmvc为了实现文件上传下载提供最直接的支持,是用即插即用的MultipartResolver实现的。

SpringMVC使用Apache Commons FileUpLoad实现了一个MultipartResolver实现类:CommonsMultipartResolver,因此想使用springmvc实现文件上传需要依赖apache commons fileupload

1.2 简单文件上传实现步骤

pom.xml导入commons-fileupload依赖

上下文配置文件中配置MultipartResolver

编写上传文件的界面 method="post",enctype="multipart/form-data"

编写controller及上传文件方法,方法中文件参数类型未MultipartFile

1.3 简单文件下载实现步骤

直接在界面给出超链接即可

springmvc提供了ResponseEntity类,可以很方便返回HttpHeaders和HttpStatus,将file文件作为ResponseEntity的属性返回即可

注意:ajax请求无法响应下载功能,是因为response原因,一般请求浏览器是会处理服务器输出的response,例如生成pfg、文件下载等。ajax只是字符型的请求,即请求的内容是以文本方式存放,但文件下载是以二进制返回的,可以读取到response,但是无法执行。更直白地说就是js无法调用浏览器的下载处理机制和程序

相关推荐
阿伟*rui1 小时前
配置管理,雪崩问题分析,sentinel的使用
java·spring boot·sentinel
XiaoLeisj3 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck3 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei3 小时前
java的类加载机制的学习
java·学习
Yaml45 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~5 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616885 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
aloha_7896 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
记录成长java6 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
睡觉谁叫~~~6 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust