searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

WebFlux使用案例

2023-12-08 08:45:08
19
0

1、引入webFlux依赖

 <dependency>    
     <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

如果引入webFlux的微服务之前,pom.xml中引入了`spring-boot-starter-web`的依赖,需要将`spring-boot-starter-web`依赖注释掉或者删除掉,因为webFlux的依赖与web的依赖是不兼容的。

2、编写调用的业务代码

这里可以根据需求调用远程服务。为了简便,在此次实验中只是在当前的服务下实现了一个业务代码。

例如:根据id查询支付记录。

@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@TableName("payment")
public class Payment {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    private String serial;
}
public interface PaymentMapper extends BaseMapper<Payment> {

}
@Slf4j
@Service
public class PaymentService {

    @Resource
    private PaymentMapper paymentMapper;

    public Payment getById(Integer id) {
        Payment payment = paymentMapper.selectById(id);
        return payment;
    }
}
@Slf4j
@RestController
@RequestMapping("/payment")
public class PaymentController {

    @Resource
    private PaymentService paymentService;

    //根据id查询支付
    @GetMapping("/getById")
    public CommonResult<Payment> getPaymentById(Integer id) {
        Payment payment = paymentService.getById(id);
        if (payment != null) {
            return new CommonResult<>(200, "数据查询成功", payment);
        } else {
            return new CommonResult<>(444, "数据查询失败", null);
        }
    }

}

3、WebFlux调用业务代码

@RestController
@RequestMapping("/webFlux")
public class WebFluxController {

    @Resource
    private WebFluxService webFluxService;

    @GetMapping("/getById")
    public Mono<CommonResult> getById(Integer id) {
        return webFluxService.getPayment(id);
    }

}
@Slf4j
@Service
public class WebFluxService {

    public Mono<CommonResult> getPayment(Integer id) {
        String path = "/payment/getById";

        WebClient webClient = WebClient.builder()
                .baseUrl("http://localhost:8001").build();

        WebClient.ResponseSpec responseSpec = webClient.get()
                .uri(uriBuilder -> uriBuilder.path(path).queryParam("id", id).build())
                .header("Content-type", "application/json")
                .retrieve();

        Mono<ResponseEntity<String>> response = responseSpec.toEntity(String.class);
        return response.flatMap(responseEntity -> {
            //响应结构
            HttpHeaders httpHeaders = responseEntity.getHeaders();
            HttpStatus httpStatus = responseEntity.getStatusCode();
            String body = responseEntity.getBody();

            CommonResult commonResult = new CommonResult();

            if (httpStatus == httpStatus.OK) {
                commonResult = JSONObject.parseObject(body, CommonResult.class);
            } else {
                commonResult.setCode(500);
                commonResult.setMessage("调用出错了");
            }
            return Mono.just(commonResult);
        }).onErrorResume(exception -> {
            log.error("使用webFlux远程调用失败:" + exception.getMessage());
            CommonResult commonResult = new CommonResult();
            commonResult.setCode(500);
            commonResult.setMessage("调用出错了");

            return Mono.just(commonResult);
        });
    }
}

使用WebClient.builder()来创建一个web请求的链路。

尝试使用@Resource WebClient webClient;的方式进行注入,发现无法注入,所以这里采用WebClient.builder()的方式创建web请求的链路。

4、WebFlux的全局异常处理类

@Slf4j
@Component
@Order(-2)   //这里将全局处理错误程序的顺序设置为-2,是为了让它比@Order(-1)注册的DefaultErrorWebExceptionHandler处理程序更高的优先级
public class GlobalErrorConfig extends AbstractErrorWebExceptionHandler {

    public GlobalErrorConfig(DefaultErrorAttributes g, ApplicationContext applicationContext,
                             ServerCodecConfigurer serverCodecConfigurer) {
        super(g, new WebProperties.Resources(), applicationContext);
        super.setMessageWriters(serverCodecConfigurer.getWriters());
        super.setMessageReaders(serverCodecConfigurer.getReaders());
    }

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
    }

    private Mono<ServerResponse> renderErrorResponse(final ServerRequest request) {
        Map<String, Object> errorPropertiesMap = getErrorAttributes(request, false);

        int httpCode = errorPropertiesMap.get("status") == null ? 500 : Integer.parseInt(errorPropertiesMap.get("status").toString());

        CommonResult commonResult = new CommonResult();

        if (HttpStatus.NOT_FOUND.value() == httpCode) {
            commonResult.setCode(404);
            commonResult.setMessage("请求的资源不存在");

            return ServerResponse.status(HttpStatus.NOT_FOUND)
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(BodyInserters.fromValue(commonResult));
        } else {
            commonResult.setCode(500);
            commonResult.setMessage("除404之外的错误");

            return ServerResponse.status(HttpStatus.OK)
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(BodyInserters.fromValue(commonResult));
        }

    }
}
0条评论
0 / 1000