Controller层代码就该这么写,简洁又优雅
一个优秀的Controller层逻辑
说到 Controller,相信大家都不陌生,它可以很方便地对外提供数据接口。它的定位,我认为是「不可或缺的配角」,说它不可或缺是因为无论是传统的三层架构还是现在的COLA架构,Controller 层依旧有一席之地,说明他的必要性;说它是配角是因为 Controller 层的代码一般是不负责具体的逻辑业务逻辑实现,但是它负责接收和响应请求 从现状看问题
Controller 主要的工作有以下几项 接收请求并解析参数 调用 Service 执行具体的业务代码(可能包含参数校验) 捕获业务逻辑异常做出反馈 业务逻辑执行成功做出响应 //DTO @Data public class TestDTO { private Integer num; private String type; } //Service @Service public class TestService { public Double service(TestDTO testDTO) throws Exception { if (testDTO.getNum() <= 0) { throw new Exception("输入的数字需要大于0"); } if (testDTO.getType().equals("square")) { return Math.pow(testDTO.getNum(), 2); } if (testDTO.getType().equals("factorial")) { double result = 1; int num = testDTO.getNum(); while (num > 1) { result = result * num; num -= 1; } return result; } throw new Exception("未识别的算法"); } } //Controller @RestController public class TestController { private TestService testService; @PostMapping("/test") public Double test(@RequestBody TestDTO testDTO) { try { Double result = this.testService.service(testDTO); return result; } catch (Exception e) { throw new RuntimeException(e); } } @Autowired public DTOid setTestService(TestService testService) { this.testService = testService; } }
如果真的按照上面所列的工作项来开发 Controller 代码会有几个问题 参数校验过多地耦合了业务代码,违背单一职责原则 可能在多个业务中都抛出同一个异常,导致代码重复 各种异常反馈和成功响应格式不统一,接口对接不友好 改造 Controller 层逻辑统一返回结构
统一返回值类型无论项目前后端是否分离都是非常必要的,方便对接接口的开发人员更加清晰地知道这个接口的调用是否成功(不能仅仅简单地看返回值是否为 null 就判断成功与否,因为有些接口的设计就是如此),使用一个状态码、状态信息就能清楚地了解接口调用情况 //定义返回数据结构 public interface IResult { Integer getCode(); String getMessage(); } //常用结果的枚举 public enum ResultEnum implements IResult { SUCCESS(2001, "接口调用成功"), VALIDATE_FAILED(2002, "参数校验失败"), COMMON_FAILED(2003, "接口调用失败"), FORBIDDEN(2004, "没有权限访问资源"); private Integer code; private String message; //省略get、set方法和构造方法 } //统一返回数据结构 @Data @NoArgsConstructor @AllArgsConstructor public class Result { private Integer code; private String message; private T data; public static Result success(T data) { return new Result<>(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMessage(), data); } public static Result success(String message, T data) { return new Result<>(ResultEnum.SUCCESS.getCode(), message, data); } public static Result<?> failed() { return new Result<>(ResultEnum.COMMON_FAILED.getCode(), ResultEnum.COMMON_FAILED.getMessage(), null); } public static Result<?> failed(String message) { return new Result<>(ResultEnum.COMMON_FAILED.getCode(), message, null); } public static Result<?> failed(IResult errorResult) { return new Result<>(errorResult.getCode(), errorResult.getMessage(), null); } public static Result instance(Integer code, String message, T data) { Result result = new Result<>(); result.setCode(code); result.setMessage(message); result.setData(data); return result; } }
统一返回结构后,在 Controller 中就可以使用了,但是每一个 Controller 都写这么一段最终封装的逻辑,这些都是很重复的工作,所以还要继续想办法进一步处理统一返回结构 统一包装处理
Spring 中提供了一个类 ResponseBodyAdvice ,能帮助我们实现上述需求
ResponseBodyAdvice 是对 Controller 返回的内容在 HttpMessageConverter 进行类型转换之前拦截,进行相应的处理操作后,再将结果返回给客户端。那这样就可以把统一包装的工作放到这个类里面。 public interface ResponseBodyAdvice { boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType); @Nullable T beforeBodyWrite(@Nullable T body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response); } supports:判断是否要交给 beforeBodyWrite 方法执行,ture:需要;false:不需要 beforeBodyWrite:对 response 进行具体的处理 // 如果引入了swagger或knife4j的文档生成组件,这里需要仅扫描自己项目的包,否则文档无法正常生成 @RestControllerAdvice(basePackages = "com.example.demo") public class ResponseAdvice implements ResponseBodyAdvice
其实我真的很重要,别自作多情啦(一)孔雀欲将南飞妻子与亲家母俩,那是亲如姐妹,在熟悉我们的朋友圈里,已成为大家津津乐道的美谈。这不,还在十一假期呢,俩姐妹已约好一起飞海南游玩了。对生活在北方的人,尤其是寒风咧咧
自古多情空余恨那一个深秋,印记着我们,浪漫美丽的邂逅,美好的时光转眼就溜走。离别的站台,我独自伤心,难以控制的眼泪,写在眼角诉说曾经美梦。秋雨在飘摇,徒添着忧愁,想起每次的相拥,一次又一次的内心
女团四强出炉!2场30,中日女团能否决战于决赛?10月6日,2022年世界乒乓球团体锦标赛淘汰赛继续进行,4场女团14决赛全部结束。上午进行的2场14决赛,赛况激烈,都打满五盘。中国台北32新加坡第一盘陈思羽30战胜周静怡,三局
赵丽颖的新剧,让我们重新认识了一个不一样的她哈喽大家好,我是娱乐辉赵丽颖新剧野蛮生长的预告大家看了,人设真的超带感,看似温温柔柔的,却是雷厉风行的女企业家还有网友做了对比图,赵丽颖这些年的变化真的太大了,清纯可爱小白花冷艳气
欧冠冠军悲喜夜!皇马3战3胜,8。6亿航母逆袭,7冠王03惨败北京时间10月6日,欧冠小组赛第3轮继续进行,皇马凯尔特人AC米兰尤文切尔西多特蒙德和本菲卡7支前冠军球队齐齐登场亮相,但命运各不相同。皇马21顿涅茨克矿工皇马此前2战2胜排名榜首
巩俐突然现身营业!这生图,看得我一惊话说,昨天写到了刚刚结束的SaintLaurent2023年春夏大秀。而巴黎时装周还在轰轰烈烈进行中,来了不少明星,包括失踪人口巩俐萧亚轩等,好不精彩趁着小长假,我们这就来一起看看
没本事男人的特征1。不敢花钱,天真认为万事做好准备,或站在风口上就能赚到大钱。2。做什么事情都是尝试一下,一遇到困难就想放弃。3。不能控制住自己的脾气,尤其对爱自己的人发脾气。4。及时享乐的人,比
RNG时隔五年拿下队史第二个S赛Bo5胜利,小组赛首战将面对强敌GEN在经过了长达六天的比赛之后,目前S12全球总决赛的入围赛已经正式圆满结束了,从入围赛12支队伍中突破晋级到小组赛的4支队伍也都全部诞生了,他们分别为进入到A组的FNC进入到B组的E
骑马与砍杀2霸主正式版即将推出IT之家10月6日消息,2020年,骑马与砍杀2霸主抢先体验版在Steam开售。10月25日,该作将结束抢先体验,正式登陆PCXboxSeriesXSXboxOne和索尼PS4及P
宁王AJ预测S12小组赛出线TES第一RNG第二,AB全是死亡之组随着RNG让一追三击败DFM拿到最后一个入围赛的晋级名额,今年世界赛正赛的四个小组战队都已经全部确定,分别是A组C9T1EDGFNCB组JDGG2DKEGC组RGETESGAMDR
早上刚刮的胡子,隔早就长出来了,胡须长太快说明了什么?我们常说爱美是女人的天性,其实不只是女性,如今越来越多的男性也都非常注意自己的自身形象,每天早上起床之后,洗脸刷牙刮胡子是必备项目。当然也有很多男性会特意把胡子修剪一下,使整个人看