使用 ExceptionHandler 处理业务流程的异常情况

都在说这是啥,我来告诉你怎么用!

Problem

在业务实现过程中,我们可能会有类似如下的场景,要实现一个下单功能,除了下单正常执行的流程之外,我们还可能需要处理各种的业务异常情况,比如说下单的用户在服务端找不到,下单的商品在服务端找不到等等的业务异常情况(注意是业务异常),这时可能会有如下的伪代码,用户找不到时,给客户端响应 http status 为 500,http body 里的内容为一个 map 对象;如果是正常执行完毕,则给客户端的响应为 http status 200,http body 里的内容为订单的id。

//controller
@RequestMapping
public Object place(HttpServletResponse response,String userId,OrderDTO orderDTO) {
	Map<String,Object> result = new HashMap<>();
	Uzer uzer = orderService.findById(userId);

	if (ObjectUtils.isEmpty(uzer)) {
		result.put("msg", String.format("User %s not be found",userId));
		response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.ordinal());
		return result;
	}
	
	response.setStatus(HttpStatus.OK.ordinal());
	String orderId = orderService.place(userId, orderDTO);
	return orderId;
} 

//service
public String place(String userId, OrderDTO orderDTO) {
	// 正常逻辑
	Uzer uzer = userRepository.findById(userId);
	// 正常逻辑	
	Order order = new Order();
	//assembler form OrderDto
	Order o = orderRepository.save(order);
	return o.id;
}

上面的代码特别丑,比如用了 Spring MVC ,还在方法上传入了 HttpServletResponse 对象;因为不同的情况返回的内容不同,返回值只能是Object,Java的强类型在此一无是处;

Spring MVC Support

如上例所示,一个业务流程的正常情况和异常情况,返回给客户端的响应码,响应体的格式都是不同的;那有没有一种方法可以分开返回业务正常执行成功之后的响应内容和业务的各种异常情况下的响应内容呢?
Spring MVC 的 Exception Handler 机制,完美的解决了这个问题。

//controller
@RequestMapping(value="/place")
@ResponseStatus(code=HttpStatus.CREATED)
public String place(String userId, OrderDTO orderDTO) {
	String orderId = orderService.place(userId, orderDTO);
	return orderId;
}

//service
public String place(String userId, OrderDTO orderDTO) {
	// 正常逻辑
	Uzer uzer = userRepository.findById(userId);

	if (ObjectUtils.isEmpty(uzer)) {
		throw new PlaceOrderException(String.format("User %s is not found", userId));
	}

	// 正常逻辑
	Order order = new Order();
	//assembler form OrderDto
	Order o = orderRepository.save(order);
	return o.id;
}

// exception handler
@ExceptionHandler
@ResponseStatus(value = HttpStatus.OK)
public DRuntimeException dealException(PlaceOrderException e) {
	DRuntimeException exception = new DRuntimeException(e);
	return exception;
}

上述伪代码解耦了下单这个流程的正常业务逻辑和异常业务结果的处理。在 service 层,如果遇到业务异常的情况,只抛出异常,不做其他任何处理。Spring MVC 捕获此异常,并回调 Exception Handler 的方法并将此异常传给此异常处理的逻辑。
解耦之后,在 controller 层,只管构建成功执行的结果,标注的 @ResponseStatus 指定 http 响应的影响码,controller 的返回结果指定响应的内容。
在 ExceptionHandler 中处理异常的情况,可以给此异常,单独指定 ResponseStatus 和 响应内容;
如果业务的异常情况想控制的更精细,可以定义更多的异常类,用于代表不同的异常情况,然后就可以给不同的 ExceptionHandler 写单独的处理逻辑,指定各自的响应码和响应体。

More

@ExceptionHandler 是 Web 应用里使用的,如果输入输出是消息中间件,Spring Messaging 模块还定义了 @MessageExceptionHandler 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈振阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值