SpringBoot3 Web开发新特性(Problemdetails、函数式Web)

1. Problemdetails

错误信息返回新格式

package org.springframework.boot.autoconfigure.web.servlet;
......省略部分......
public class WebMvcAutoConfiguration {
    ......省略部分......
    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnProperty(
        prefix = "spring.mvc.problemdetails",
        name = {"enabled"},
        havingValue = "true"
    )
    static class ProblemDetailsErrorHandlingConfiguration {
        ProblemDetailsErrorHandlingConfiguration() {
        }

        @Bean
        @ConditionalOnMissingBean({ResponseEntityExceptionHandler.class})
        ProblemDetailsExceptionHandler problemDetailsExceptionHandler() {
            return new ProblemDetailsExceptionHandler();
        }
    }
    ......省略部分......
}
  1. 默认是关闭的。需要配置一个属性spring.mvc.problemdetails.enabled=true
  2. ProblemDetailsExceptionHandler是一个@ControllerAdvice集中处理系统异常
  3. 如果系统出现以下异常,会被SpringBoot支持以RFC 7807规范方式返回错误数据
	@ExceptionHandler({
			HttpRequestMethodNotSupportedException.class,    // 请求方式不支持
			HttpMediaTypeNotSupportedException.class,
			HttpMediaTypeNotAcceptableException.class,
			MissingPathVariableException.class,
			MissingServletRequestParameterException.class,
			MissingServletRequestPartException.class,
			ServletRequestBindingException.class,
			MethodArgumentNotValidException.class,
			NoHandlerFoundException.class,
			AsyncRequestTimeoutException.class,
			ErrorResponseException.class,
			ConversionNotSupportedException.class,
			TypeMismatchException.class,
			HttpMessageNotReadableException.class,
			HttpMessageNotWritableException.class,
			BindException.class
		})
  1. 以HttpRequestMethodNotSupportedException来讲解开启的效果。不开启前,以post方式请求一个get url: http://localhost:8080/exception。显示如下。其中headers的Content-Type是application/json
{
    "timestamp": "2023-07-22T02:51:16.088+00:00",
    "status": 405,
    "error": "Method Not Allowed",
    "path": "/exception"
}

开启后。显示如下。。其中headers的Content-Type是application/problem+json。其中problem可以通过额外的拓展返回一些业务数据

{
    "type": "about:blank",
    "title": "Method Not Allowed",
    "status": 405,
    "detail": "Method 'POST' is not supported.",
    "instance": "/exception"
}

2. 函数式Web

使用函数式的方式,定义Web的请求处理流程。使用的java8函数式接口

Web请求处理的方式:

  1. @Controller + @RequestMapping:耦合式 (路由、业务耦合)
  2. 函数式Web:分离式(路由、业务分离)

2.1 场景

以Restful方式,对User进行CRUD

  • GET /user/1: 获取id=1的用户
  • GET /users: 获取所有用户
  • POST /user: 请求体携带json,新增一个用户
  • PUT /user/1: 请求体携带json,修改id=1的用户
  • DELETE /user/1: 删除id=1的用户

2.2 主要逻辑

  1. 给容器中放一个Bean:类型是RouterFunction,集中所有路由信息
  2. 每个业务准备一个的Handler

2.3 核心对象

  1. RouterFunction:定义路由信息。发什么请求,谁来处理
  2. RequestPredicate:定义请求规则:请求方式(GET、POST)和请求参数
  3. ServerRequest:封装请求完整数据
  4. ServerResponse:封装响应完整数据

2.4 示例程序

WebFunctionConfig.java

package com.hh.springboot3test.config;

import com.hh.springboot3test.bean.User;
import com.hh.springboot3test.biz.UserBizHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.function.RequestPredicates;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.RouterFunctions;
import org.springframework.web.servlet.function.ServerResponse;


@Configuration
public class WebFunctionConfig {

    @Bean
    public RouterFunction<ServerResponse> userRoute(UserBizHandler userBizHandler/*这个会被自动注入进来*/) {

        return RouterFunctions.route() // 开始定义路由信息
                .GET("/user/{id}", RequestPredicates.accept(MediaType.ALL).and(RequestPredicates.param("key1", "value1")/* 只有/user/n?key1=value1能查询出来结果 */), request -> {
                    String id = request.pathVariable("id");
                    System.out.println("查询的用户的id = " + id);
                    // 模拟数据库查询出来的用户
                    User user = new User(1, "jim", 28);
                    // 构造响应。和@ResponseBody原理一样,利用HttpMessageConverter,可写出为json
                    return ServerResponse.ok().body(user);
                })
                .GET("/users", userBizHandler::getUsers)
                .POST("/user", RequestPredicates.accept(MediaType.APPLICATION_JSON), userBizHandler::saveUser)
                .PUT("/user/{id}", RequestPredicates.accept(MediaType.APPLICATION_JSON), userBizHandler::updateUser)
                .DELETE("/user/{id}", userBizHandler::deleteUser)
                .build();
    }

}

UserBizHandler.java

package com.hh.springboot3test.biz;

import com.hh.springboot3test.bean.User;
import jakarta.servlet.ServletException;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.function.ServerRequest;
import org.springframework.web.servlet.function.ServerResponse;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;


@Service
public class UserBizHandler {

    /**
     * 获取所有用户
     */
    public ServerResponse getUsers(ServerRequest request) throws Exception {
        // 模拟数据库查询出来的所有用户
        List<User> users = Arrays.asList(
                new User(1, "jim", 28),
                new User(2, "lily", 18)
        );

        return ServerResponse
                .ok()
                .body(users);
    }


    /**
     * 保存用户
     */
    public ServerResponse saveUser(ServerRequest request) throws ServletException, IOException {
        // 提取请求体
        User user = request.body(User.class);

        // 模拟保存用户
        System.out.println("保存的用户是: " + user);

        return ServerResponse.ok().build();
    }

    /**
     * 更新用户
     */
    public ServerResponse updateUser(ServerRequest request) throws ServletException, IOException {
        // 提取请求体
        User user = request.body(User.class);

        // 模拟更新用户
        System.out.println("更新的用户是: " + user);

        return ServerResponse.ok().build();
    }

    /**
     * 删除用户
     */
    public ServerResponse deleteUser(ServerRequest request) {
        String id = request.pathVariable("id");

        // 模拟删除用户
        System.out.println("删除的用户的id = " + id);

        return ServerResponse.ok().build();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot 是一个快速构建基于 Spring 框架的应用程序的工具。它为 Spring 应用程序开发提供了一种简单的方法,无需繁琐地配置 XML,只需要使用注解即可实现常见的业务逻辑。 下面是一个基本的 Spring Boot Web 应用程序的步骤: 1. 创建一个 Maven 项目,并添加 Spring Boot 的依赖。 2. 创建一个 Controller 类,并添加处理请求的方法。 3. 配置应用程序的入口点,并启动应用程序。 以下是一个简单的示例: 1. 创建 Maven 项目 使用 Maven 创建一个新的项目,可以参考以下命令: ``` mvn archetype:generate -DgroupId=com.example -DartifactId=webapp -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false ``` 2. 添加 Spring Boot 依赖 在 pom.xml 文件添加 Spring Boot Starter Web 依赖: ``` <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> ``` 3. 创建 Controller 类 创建一个 HomeController 类,并添加处理请求的方法: ``` @RestController public class HomeController { @GetMapping("/") public String home() { return "Hello, World!"; } } ``` 4. 配置应用程序的入口点 创建一个 SpringBootWebApplication 类,并使用 @SpringBootApplication 注解标记为应用程序的入口点: ``` @SpringBootApplication public class SpringBootWebApplication { public static void main(String[] args) { SpringApplication.run(SpringBootWebApplication.class, args); } } ``` 5. 启动应用程序 使用以下命令启动应用程序: ``` mvn spring-boot:run ``` 在浏览器访问 http://localhost:8080/ ,即可看到 "Hello, World!"。 这就是一个简单的 Spring Boot Web 应用程序的开发过程。当然,除了以上步骤,还有很多其他的配置和实现方,具体可以参考官方文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值