SpringMVC(下篇)
1.响应数据
1.1请求转发和响应重定向
在 Spring MVC 中,Handler 方法返回值来实现快速转发,可以使用 redirect 或者 forward 关键字来实现重定向。
流程:
-
将方法的返回值,设置String类型
-
转发使用forward关键字,重定向使用redirect关键字
-
关键字: /路径
-
注意:如果是项目下的资源,转发和重定向都一样都是项目下路径!都不需要添加项目根路径!
控制层
java
@Controller
@RequestMapping("jsp")
public class JspController {
/**
*方法的返回值是字符串类型
*不能添加@ResponseBody,直接返回字符串给浏览器
*返回值对应中间的视图名即可
*/
@GetMapping("index")
public String index(HttpServletRequest request) {
request.setAttribute("data","你好黄金圣斗士");
System.out.println("成功找到视图");
return "index";
}
/**
*方法的返回值是字符串类型
*不能添加@ResponseBody,直接返回字符串给浏览器
*返回的字符串前forword:/转发地址
*/
@RequestMapping("forword")
public String forword(){
System.out.println("请求转发成功执行");
return "forword:/jsp/index";
}
/**
*方法的返回值是字符串类型
*不能添加@ResponseBody,直接返回字符串给浏览器
*返回的字符串前redirect:/重定向地址
*/
@RequestMapping("redirect")
public String redirect(){
System.out.println("响应重定向成功执行");
return "redirect:/jsp/index";
}
}
1.2Json数据返回
前置准备:
XML
==============================导入jackson依赖================================
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.0</version>
</dependency>
java
======================添加json数据转化器(@EnableWebMvc)=======================
//TODO: SpringMVC对应组件的配置类 [声明SpringMVC需要的组件信息]
//TODO: 导入handlerMapping和handlerAdapter的三种方式
//1.自动导入handlerMapping和handlerAdapter [推荐]
//2.可以不添加,springmvc会检查是否配置handlerMapping和handlerAdapter,没有配置默认加载
//3.使用@Bean方式配置handlerMapper和handlerAdapter
@EnableWebMvc //json数据处理,必须使用此注解,因为他会加入json处理器
@Configuration
@ComponentScan(basePackages = "com.atguigu.controller") //TODO: 进行controller扫描
//WebMvcConfigurer springMvc进行组件配置的规范,配置组件,提供各种方法! 前期可以实现
public class SpringMvcConfig implements WebMvcConfigurer {
}
@ResponseBody注解
@ResponseBody
是 Spring MVC 框架中的一个注解,用于将控制器的返回值自动转换为 JSON 或 XML 格式,并写入 HTTP 响应体中。这个注解通常用在返回数据而不是视图名称的控制器方法上。
主要用途
-
自动序列化 Java 对象 :当你希望将 Java 对象(如 POJOs)直接转换为 JSON 或 XML 并发送给客户端时,可以使用
@ResponseBody
。 -
RESTful API 开发 :在开发 RESTful Web 服务时,
@ResponseBody
非常有用,因为它允许你轻松地返回结构化数据而不是视图。
@RestController注解
@RestController
是 Spring MVC 中的一个注解,它是 @Controller 和 @ResponseBody 注解的组合。当你使用 @RestController
注解一个类时,意味着这个类中的所有方法默认都会将返回值作为 HTTP 响应体返回,而不需要在每个方法上都添加 @ResponseBody
注解。
主要用途
-
返回值作为响应体 :与
@Controller
注解不同,@RestController
注解的方法默认使用@ResponseBody
语义,即方法的返回值会被自动序列化为 JSON 或 XML 格式(取决于请求头的Accept
字段和配置的HttpMessageConverter
),并作为 HTTP 响应体返回给客户端。 -
RESTful 服务 :
@RestController
通常用于构建 RESTful Web 服务,因为它简化了数据交换的过程,使得开发者可以专注于业务逻辑的实现,而不需要过多关注视图的渲染。 -
简化代码 :使用
@RestController
可以减少模板代码,因为它自动为所有方法添加了@ResponseBody
注解,避免了重复书写。
①@ResponseBody注解可以加在方法和类上
加在类上相当于给类中的每一个方法都分配一个 @ResponseBody注解
数据直接放入响应体中返回,不会走视图解析器(用于将方法返回的对象序列化为 JSON 或 XML 格式的数据,并发送给客户端。具体来说,@ResponseBody 注解可以用来标识方法或者方法返回值,表示方法的返回值是要直接返回给客户端的数据,而不是由视图解析器来解析并渲染生成响应体(viewResolver没用)。)
②@RestController=@Controller+@ @ResponseBody
可以在类上声明@RestController注解
java
@Controller
@RequestMapping("json")
public class JsonController {
@ResponseBody
@GetMapping("data")
public User data(){
User user = new User();
user.setAge("18");
user.setName("huermosi");
return user;
}
@ResponseBody
@GetMapping("data1")
public List<User> dataList(){
User user = new User();
user.setAge("18");
user.setName("huermosi");
ArrayList<User> users = new ArrayList<>();
users.add(user);
return users;
}
}
1.3静态资源返回
静态资源: 资源本身已经是可以直接拿到浏览器上使用的程度了,不需要在服务器端做任何运算、处理。典型的静态资源包括:
纯HTML文件
图片
CSS文件
JavaScript文件
......
准备: 配置类要实现WebMvcConfigurer接口
在配置类中实现configureDefalutServletHandling方法,调用参数configurer的enable方法即可
如此在dispatcherServlet通过一个路径去handlerMapping中找对应的handler方法没找到时,就会继续通过此路径去找静态资源
配置类
java
@EnableWebMvc //json数据处理,必须使用此注解,因为他会加入json处理器
@Configuration
@ComponentScan(basePackages = "com.atguigu.controller") //TODO: 进行controller扫描
//WebMvcConfigurer springMvc进行组件配置的规范,配置组件,提供各种方法! 前期可以实现
public class SpringMvcConfig implements WebMvcConfigurer {
//配置jsp对应的视图解析器
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
//快速配置jsp模板语言对应的
registry.jsp("/WEB-INF/views/",".jsp");
}
//开启静态资源处理 <mvc:default-servlet-handler/>
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
2.RESTFUI风格
**[RESTful]风格((Representational State Transfer))** 是一种网络应用程序的设计风格和开发方式,它基于[HTTP协议](如[GET]、[POST]、[PUT]、[DELETE])来操作资源,并通过[URI]进行资源定位。RESTful风格的核心思想是将Web应用程序的功能作为资源来表示,使用统一的标识符(URI)对这些资源进行操作。
规范的设计:
①url【地址】
②请求方式【GET,POST,PUT,DELETE】
③传递参数【param,json,path】
特点:1.每一个URI代表1种资源(URI 是名词);
2.客户端使用GET、POST、PUT、DELETE 4个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源;
3.资源的表现形式是XML或者JSON;
4.客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含理解请求所必需的信息。
5.HTTP协议请求方式要求
REST 风格主张在项目设计、开发过程中,具体的操作符合HTTP协议定义的请求方式的语义。
根据接口的具体动作,选择具体的HTTP协议请求方式
路径设计从原来携带动标识,改成名词,对应资源的唯一标识即可
3.扩展
3.1全局异常处理机制
1编程式异常处理 :是指在代码中显式地编写处理异常的逻辑。它通常涉及到对异常类型的检测及其处理,例如使用 try-catch 块来捕获异常,然后在 catch 块中编写特定的处理代码,或者在 finally 块中执行一些清理操作。在编程式异常处理中,开发人员需要显式地进行异常处理,异常处理代码混杂在业务代码中,导致代码可读性较差
2.声明式异常处理 :则是将异常处理的逻辑从具体的业务逻辑中分离出来,通过配置等方式进行统一的管理和处理。在声明式异常处理中,开发人员只需要为方法或类标注相应的注解(如 @Throws 或 @ExceptionHandler),就可以处理特定类型的异常。相较于编程式异常处理,声明式异常处理可以使代码更加简洁、易于维护和扩展。
全局异常处理步骤
1.定义异常处理类(全局异常发生会走此类的handler):
全局异常处理类的声明:@ControllerAdvice,@RestControllerAdvice
使用@ControllerAdvice注解, 可以返回逻辑视图,转发和重定向的
使用@RestControllerAdvice注解,等于@ControllerAdvice+@RequestBody直接返回json字符串
2.在对应的异常处理方法上添加 @ExceptionHandler注解(给注解的对应属性进行赋值,对应的异常类抛出后会执行此方法内的代码)
3.在异常处理类中寻找对应的异常对象:
在没有精确的异常时,会寻找父异常
全局异常处理类构建
java
//@ControllerAdvice
/**
* projectName: com.atguigu.execptionhandler
*
* description: 全局异常处理器,内部可以定义异常处理Handler!
*/
/**
* @RestControllerAdvice = @ControllerAdvice + @ResponseBody
* @ControllerAdvice 代表当前类的异常处理controller!
*/
@RestControllerAdvice
public class GlobalException {
@ExceptionHandler(ArithmeticException.class)
public Object ArithmeticExceptionHandler(ArithmeticException e) {
e.getMessage();
return "ArithmeticException"+"出现全局异常";
}
/**
* 当发生空指针异常会触发此方法!
* @param e
* @return
*/
@ExceptionHandler(NullPointerException.class)
public Object NullPointerExceptionHandler(NullPointerException e) {
e.printStackTrace();
return "NullPointerException"+"出现全局异常";
}
/**
* 所有异常都会触发此方法!但是如果有具体的异常处理Handler!
* 具体异常处理Handler优先级更高!
* 例如: 发生NullPointerException异常!
* 会触发handlerNullException方法,不会触发handlerException方法!
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
public Object ExceptionHandler(Exception e) {
e.printStackTrace();
return "Exception"+e.getMessage();
}
}
java
==============================全局异常处理方法模板=================================
/**
* 异常处理handler
* @ExceptionHandler(HttpMessageNotReadableException.class)
* 该注解标记异常处理Handler,并且指定发生异常调用该方法!
*
*
* @param e 获取异常对象!
* @return 返回handler处理结果!
*/
@ExceptionHandler(HttpMessageNotReadableException.class)
public Object handlerJsonDateException(HttpMessageNotReadableException e){
return null;
}
异常类构建
java
@Controller
@RequestMapping("user")
public class UserController {
@GetMapping("data")
public String data() {
String name=null;
name.toString();//空指针异常
return "ok";
}
@GetMapping("data1")
public String data1() {
int i=10/0;//除零异常
return "ok";
}
}
@ControllerAdvice注解
@ControllerAdvice
是 Spring MVC 中的一个注解,它用于定义全局的控制器增强器(Controller Advisor)。@ControllerAdvice
注解可以用于定义一些全局的配置,比如异常处理、数据绑定、数据预处理等,这些配置将会应用于所有使用 @RequestMapping
注解的控制器方法上。
主要用途
-
全局异常处理 :通过实现
HandlerExceptionResolver
接口或使用@ExceptionHandler
注解的方法,可以全局捕获并处理控制器中抛出的异常。 -
全局数据绑定 :通过实现
WebDataBinderFactory
接口或使用@InitBinder
注解的方法,可以在控制器方法执行之前对请求参数进行全局的数据绑定和验证。 -
全局数据预处理 :通过实现
HandlerMethodArgumentResolver
接口或使用@ModelAttribute
注解的方法,可以在控制器方法执行之前对请求数据进行预处理,并将处理后的数据添加到 Model 中。 -
全局响应体后处理 :通过实现
ResponseBodyAdvice
接口,可以对控制器的响应体进行全局的后处理,比如统一添加响应头、修改响应体等。
@RestControllerAdvice注解
@RestControllerAdvice
注解是 Spring MVC 和 Spring Boot 应用程序中用于定义全局异常处理类的注解。它是 @ControllerAdvice 注解的特殊版本,专为 RESTful 风格的应用程序设计。@RestControllerAdvice
可以捕获整个应用程序中抛出的异常,并对它们进行处理,从而实现整个应用程序范围内统一处理异常的目标。@RestControllerAdvice = @ControllerAdvice + @ResponseBody
主要用途
-
全局异常处理 :通过实现
@ExceptionHandler
方法,可以捕获并处理控制器中抛出的异常,返回统一的错误响应格式。 -
全局数据绑定 :通过实现
@InitBinder
方法,可以在控制器方法执行之前对请求参数进行全局的数据绑定和验证。 -
全局数据预处理 :通过实现
@ModelAttribute
方法,可以在控制器方法执行之前对请求数据进行预处理,并将处理后的数据添加到 Model 中。
@ExceptionHandler注解
@ExceptionHandler
注解是 Spring MVC 提供的一个用于处理控制器中抛出的异常的注解。当控制器方法在执行过程中抛出异常时,Spring MVC 会查找是否有带有 @ExceptionHandler 注解的方法能够处理该异常,如果有,则会调用该方法来处理异常,而不是将异常信息直接返回给客户端。
主要用途
-
异常处理 :通过
@ExceptionHandler
注解,你可以为控制器中的方法定义异常处理逻辑,从而避免异常信息直接暴露给客户端,提高应用程序的安全性和用户体验。 -
统一响应格式 :你可以使用
@ExceptionHandler
注解来确保所有异常都按照统一的格式进行响应,这对于 RESTful API 尤为重要,因为它可以保持 API 的一致性。
3.2拦截器
过滤器VS拦截器
1、过滤器和拦截器触发时机不一样,过滤器是在请求进入容器后,在请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。
2、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,因为拦截器是spring提供并管理的,spring的功能可以被拦截器使用,在拦截器里注入一个service,可以调用业务逻辑。而过滤器是JavaEE标准,只需依赖servlet api ,不需要依赖spring。
3、过滤器的实现基于回调函数。而拦截器(代理模式)的实现基于反射
4、Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。
5、Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理(反射)的方式来执行。
6、Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便
拦截器实现步骤
1.创建一个拦截器类,实现HandlerInterceptor接口
2.重写三个方法preHandle,postHandle,afterCompletion
3.在SpringMVC配置类中注册添加创建的拦截器类
java
public class MyInterceptor implements HandlerInterceptor {
/**
*
* @param request 请求对象
* @param response 响应对象
* @param handler 我们要调用的方法对象
* @return true放行 false拦截
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor.preHandle");
return true;
}
/**
* 当handler执行完毕后,触发的方法 没有拦截机制
* 结果处理,敏感词汇检查
*
* @param request 请求对象
* @param response 响应对象
* @param handler 我们要调用的方法对象
* @param modelAndView 返回的视图和共享域对象
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor.postHandle");
}
/**
*
* @param request 请求对象
* @param response 响应对象
* @param handler 我们要调用的方法对象
* @param ex 异常对象(handler报错)
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor.afterCompletion");
}
}
java
===================在SpringMVC配置类中注册拦截器============================================
@EnableWebMvc //json数据处理,必须使用此注解,因为他会加入json处理器
@Configuration
@ComponentScan(basePackages = {"com.atguigu.controller","com.atguigu.exceptionhandler"}) //TODO: 进行controller扫描
//WebMvcConfigurer springMvc进行组件配置的规范,配置组件,提供各种方法! 前期可以实现
public class SpringMvcConfig implements WebMvcConfigurer {
//添加拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
//将拦截器添加到Springmvc环境,默认拦截所有Springmvc分发的请求
registry.addInterceptor(new Process01Interceptor());
}
}
拦截器细节配置
1.拦截全部请求
registry.addInterceptor(new MyInterceptor());
2.指定拦截的地址
①具体地址拦截: registry.addInterceptor(newMyInterceptor()).addPathPatterns("/user/data");
②模糊地址拦截(* 任意一层字符串,** 任意多层字符串):
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/user/**");
③排除地址拦截:
registry.addInterceptor(newMyInterceptor()).addPathPatterns("/user/**"). excludePathPatterns("/user/data");
java
@EnableWebMvc //json数据处理,必须使用此注解,因为他会加入json处理器
@Configuration
@ComponentScan(basePackages = {"com.atguigu.controller","com.atguigu.exceptionhandler"}) //TODO: 进行controller扫描
//WebMvcConfigurer springMvc进行组件配置的规范,配置组件,提供各种方法! 前期可以实现
public class SpringMvcConfig implements WebMvcConfigurer {
//配置jsp对应的视图解析器
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
//快速配置jsp模板语言对应的
registry.jsp("/WEB-INF/views/",".jsp");
}
//开启静态资源处理 <mvc:default-servlet-handler/>
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
//添加拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
//将拦截器添加到Springmvc环境,默认拦截所有Springmvc分发的请求
registry.addInterceptor(new Process01Interceptor());
}
}
3.3参数校验
相关依赖配置
XML
<!-- 校验注解 -->
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-web-api</artifactId>
<version>9.1.0</version>
<scope>provided</scope>
</dependency>
<!-- 校验注解实现-->
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.0.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator-annotation-processor -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>8.0.0.Final</version>
</dependency>
、
NotNull VS NotEmpty VS NotBlank
1NotNull :包装类型不为null
2 NotEmpty:集合长度大于零
3NotBlank:字符串不为null,且不为" "字符串
java
@Data
public class User {
@NotBlank
private String name;
@Length(min = 6)
private String password;
@Min(1)
private int age;
@Email
private String email;
@Past
private Date birthday;
}
-
在控制层的handler方法使用其实体类接收请求的数据时,在参数列表的其实体类类型的参数前,要加上@Validated注解
-
设置错误绑定信息的捕捉,在handler方法的参数列表中,在要校验的对象后加上一个BindingResult类型的对象(BindingResult类型的对象必须跟在要校验的对象后面),在handler方法中加上一个if(result.hasErrors()){ }的条件语句,在条件语句中写发生错误绑定信息后的逻辑处理的代码