SpringMVC

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 注解。

主要用途

  1. 返回值作为响应体 :与 @Controller 注解不同,@RestController 注解的方法默认使用 @ResponseBody 语义,即方法的返回值会被自动序列化为 JSON 或 XML 格式(取决于请求头的 Accept 字段和配置的 HttpMessageConverter),并作为 HTTP 响应体返回给客户端。

  2. RESTful 服务@RestController 通常用于构建 RESTful Web 服务,因为它简化了数据交换的过程,使得开发者可以专注于业务逻辑的实现,而不需要过多关注视图的渲染。

  3. 简化代码 :使用 @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 注解的控制器方法上。

主要用途

  1. 全局异常处理 :通过实现 HandlerExceptionResolver 接口或使用 @ExceptionHandler 注解的方法,可以全局捕获并处理控制器中抛出的异常。

  2. 全局数据绑定 :通过实现 WebDataBinderFactory 接口或使用 @InitBinder 注解的方法,可以在控制器方法执行之前对请求参数进行全局的数据绑定和验证。

  3. 全局数据预处理 :通过实现 HandlerMethodArgumentResolver 接口或使用 @ModelAttribute 注解的方法,可以在控制器方法执行之前对请求数据进行预处理,并将处理后的数据添加到 Model 中。

  4. 全局响应体后处理 :通过实现 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()){ }的条件语句,在条件语句中写发生错误绑定信息后的逻辑处理的代码

相关推荐
P7进阶路42 分钟前
72.是否可以把所有Bean都通过Spring容器来管理?(Spring的applicationContext.xml中配置全局扫 描)
xml·java·spring
每天写点bug43 分钟前
【go每日一题】 责任链模式的实现
开发语言·golang·责任链模式
找了一圈尾巴44 分钟前
Wend看源码-Java-Map学习
java·学习·map
罗政1 小时前
PDF书籍《手写调用链监控APM系统-Java版》第4章 SPI服务模块化系统
java·pdf·linq
北欧人写代码1 小时前
javaWeb开发
java
犬余1 小时前
设计模式之享元模式:看19路棋盘如何做到一子千面
java·设计模式·享元模式
半盏茶香1 小时前
C语言勘破之路-最终篇 —— 预处理(下)
c语言·开发语言·c++·算法
老马啸西风1 小时前
NLP 中文拼写检测纠正论文 Automatic-Corpus-Generation
java
时雨h1 小时前
30天面试打卡计划 2024-12-25 26 27 面试题
java·开发语言·数据库
别致的影分身2 小时前
Linux 线程池
java·开发语言·jvm