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协议(如GETPOSTPUTDELETE)来操作资源,并通过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()){ }的条件语句,在条件语句中写发生错误绑定信息后的逻辑处理的代码

相关推荐
卷毛的技术笔记10 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
编程大师哥10 小时前
匿名函数 lambda + 高阶函数
java·python·算法
isyangli_blog10 小时前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb20081110 小时前
FastAPI APIRouter
开发语言·python
Benszen10 小时前
KVM虚拟化解决方案
开发语言·perl
会编程的土豆10 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木11 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
adrninistrat0r11 小时前
Java调用链MCP分析工具
java·python·ai编程
喵个咪11 小时前
GoWind Toolkit Go后端代码生成 完整全流程实战
后端·go·orm
杨充11 小时前
1.3 浮点型数据设计灵魂
开发语言·python·算法