• 我的订阅
  • 科技

看动画,轻松学习23种C++设计模式-霜飞浪活河汉精

类别:科技 发布时间:2022-12-20 04:02:00 来源:我是程序猿
看动画,轻松学习23种C++设计模式-霜飞浪活河汉精

控制器层代码就应该这么写,简洁优雅!

出色的控制器层逻辑

看动画,轻松学习23种C++设计模式

download:https://www.sisuoit.com/3611.html

说起控制器,相信大家都不陌生,它可以很方便的对外提供数据接口。它的定位,在我看来,是不可或缺的配角。

不可或缺是因为无论是传统的三层架构还是现在的可乐架构,控制器层还是有一席之地的,可见其必要性。

之所以说是配角,是因为控制器层的代码一般不负责具体的逻辑业务逻辑实现,而是负责接收和响应请求。

从现状看问题

控制器的主要工作如下:

看动画,轻松学习23种C++设计模式-霜飞浪活河汉精

接收请求并解析参数。

调用服务来执行特定的业务代码(可能包括参数验证)

捕捉业务逻辑异常并给出反馈。

逻辑成功执行以做出响应。

//DTO

@数据

公共类TestDTO <{p>私有整数num

私有字符串类型;

}

//服务

@服务

公共类测试服务<{p>

公共双服务(TestDTO testDTO)引发异常<{p>if (testDTO.getNum() 1) <{p>结果=结果*数量;

num-= 1;

}

返回结果;

}

抛出新异常(“无法识别的算法”);

}

}

//控制器

@RestController

公共类TestController <{p>

私有TestService testService

@PostMapping("/test ")

公共双重测试(@RequestBody TestDTO testDTO) <{p>尝试<{p>double result = this . test service . service(test dto);

返回结果;

} catch(异常e) <{p>抛出新的runtime exception(e);

}

}

@自动连线

公共DTOid setTestService(TestService TestService)<{p>this.testService = testService

}

}

如果你真的按照上面列出的工作项来开发控制器代码,会有几个问题:

看动画,轻松学习23种C++设计模式-霜飞浪活河汉精

参数检查与业务代码耦合过多,违背了单一责任原则。

同一个异常可能在多个服务中抛出,导致代码重复。

各种异常反馈和成功响应格式不统一,界面对接不友好。

转换控制器层逻辑

统一回报结构

无论项目前后是否分离,都需要统一返回值类型,让对接接口的开发者更清楚的知道这个接口的调用是否成功(我们不能简单的判断返回值是否为null,因为有些接口就是这样设计的)。

推荐一个开源免费的Spring Boot最全教程:

https://github.com/javastacks/spring-boot-best-practice

使用状态代码和状态信息来清楚地理解接口调用:

//定义返回数据结构

公共接口IResult <{p>integer getCode();

string getMessage();

}

//常用结果的枚举

公共枚举ResultEnum实现IResult <{p>成功(2001,“接口调用成功”),

VALIDATE_FAILED(2002,“参数验证失败”),

COMMON_FAILED(2003,“接口调用失败”),

禁止(2004年《无权限访问资源》);

私有整数代码;

私有字符串消息;

//省略get、set方法和构造方法

}

//统一返回数据结构

@数据

@NoArgsConstructor

@AllArgsConstructor

公共类结果<{p>私有整数代码;

私有字符串消息;

私人测试数据;

公共静态结果成功(测试数据)<{p>返回新结果(ResultEnum。SUCCESS.getCode(),ResultEnum。SUCCESS.getMessage(),数据);

}

公共静态结果成功(字符串消息,测试数据)<{p>返回新结果(ResultEnum。SUCCESS.getCode(),message,data);

}

公共静态结果失败()<{p>返回新结果(ResultEnum。COMMON_FAILED.getCode(),ResultEnum。COMMON_FAILED.getMessage(),null);

}

公共静态结果失败(字符串消息)<{p>返回新结果(ResultEnum。COMMON_FAILED.getCode(),message,null);

}

公共静态结果失败(IResult errorResult) <{p>返回新结果(errorResult.getCode()、errorResult.getMessage()、null);

}

公共静态结果实例(整数代码、字符串消息、测试数据)<{p>结果Result = new Result();

result.setCode(代码);

result.setMessage(消息);

result.setData(数据);

返回结果;

}

}

统一结构返回后,可以在控制器中使用。但是,每个控制器都要编写这样一段最终封装的逻辑,这是一个非常重复的工作。因此,我们应继续寻找进一步处理统一回报结构的方法。

统一包装处理

Spring中提供了一个类ResponseBodyAdvice,可以帮助我们实现上述需求:

公共接口响应加载Advice <{p>布尔支持(MethodParameter returnType,Class > converter type);

@Nullable

T before body write(@ Nullable T body,MethodParameter returnType,MediaType selectedContentType,Class> selectedConverterType,ServerHttpRequest,server httpresponse response);

}

Body Advice在HttpMessageConverter执行类型转换之前截获控制器返回的内容,然后在相应的处理操作之后将结果返回给客户端。

然后你可以把统一打包的工作放到这个类中:

支持:确定是否交给beforeBodyWrite方法执行,true:yes;False:不是必需的。

BeforeBodyWrite:响应的特殊处理

//如果引入了swagger或者knife4j的文档生成组件,在这里只需要扫描自己项目的包,否则无法正常生成文档。

@ RestControllerAdvice(base packages = " com . example . demo ")

公共类ResponseAdvice实现ResponseBodyAdvice <{p>@覆盖

公共布尔支持(MethodParameter returnType,Class> converterType) <{p>//如果不需要封装,可以添加一些验证手段,比如添加标记排除的注释。

返回true

}

@覆盖

public Object beforeBodyWrite(Object body,MethodParameter returnType,MediaType selectedContentType,Class> selectedConverterType,ServerHttpRequest,ServerHttpResponse response) <{p>//提供一定程度的灵活性。如果几何体已经打包,则不会打包。

if(结果的正文实例)<{p>返回正文;

}

返回result . success(body);

}

}

经过这种转换,控制器返回的数据可以统一打包,不需要对原代码做大量的改动。

参数验证

Java API的规范JSR303定义了用于验证的标准验证API,其中一个众所周知的实现是hibernate验证。

Spring validation是SpringMVC的二次封装,经常用来自动验证Spring MVC的参数,所以参数验证的代码不需要耦合业务逻辑代码。

①@ path variable和@RequestParam的参数验证

Get请求的参数接收一般依赖于这两个注释,但是url长度有限,代码可维护。如果实体尽可能传递五个以上的参数。

@PathVariable和@RequestParam参数的验证需要参数中约束声明的批注。

如果验证失败,将引发methoalgumentnotvalidieexception异常。

@ rest controller(value = " pretty test controller ")

@RequestMapping("/pretty ")

公共类TestController <{p>

私有TestService testService

@GetMapping("/{num} ")

公共整数细节(@ path variable(" num ")@ Min(1)@ Max(20)Integer num)<{p>返回num * num

}

@GetMapping("/getByEmail ")

public test to getby account(@ request param @ not blank @ Email String Email)<{p>test dto test dto = new test dto();

testDTO.setEmail(电子邮件);

返回testDTO

}

@自动连线

public void setTestService(TestService pretty TestService)<{p>this . testservice = pretty testservice;

}

}

证实原则

在SpringMVC中,有一个类叫做RequestResponseBodyMethodProcessor,它有两个功能(其实可以从名字中得到启发)。

用于解析@RequestBody批注的参数

处理@ResponseBody批注方法的返回值

解析@RequestBoyd批注参数的方法是resolveArgument。

公共类RequestResponseBodyMethodProcessor扩展了AbstractMessageConverterMethodProcessor <{p>/**

*如果验证失败,将引发MethodArgumentNotValidException。

* @如果{@link RequestBody#required()}则抛出httpmessagenoretreadableexception

* is {@code true}并且没有正文内容,或者如果没有合适的

*用于读取内容的转换器。

*/

@覆盖

公共对象resolve argument(method parameter参数,@ Nullable ModelAndViewContainer MAV container,

NativeWebRequest webRequest,@ Nullable WebDataBinderFactory binder factory)引发异常<{p>

parameter = parameter . nestedifoptional();

//将请求数据封装到标记的DTO对象中

object arg = readWithMessageConverters(webRequest,parameter,parameter . getnestedgenericparametertype());

string name = conventions . getvariablenameforparameter(参数);

if (binderFactory!= null) <{p>WebDataBinder binder = binder factory . create binder(webRequest,arg,name);

如果(arg!= null) <{p>//执行数据验证

validateifapplable(binder,parameter);

//如果验证失败,则抛出methodgargumentnotvalidieexception异常。

//如果我们自己不捕捉,最终会被DefaultHandlereXceptionResolver捕捉并处理。

if (binder.getBindingResult()。has errors()& & isBindExceptionRequired(binder,parameter)) <{p>抛出新方法argumentnotvaliexception(parameter,binder . getbinding result());

}

}

if (mavContainer!= null) <{p>MAV container . add attribute(binding result。MODEL_KEY_PREFIX + name,binder . getbinding result());

}

}

返回adaptArgumentIfNecessary,parameter);

}

}

公共抽象类AbstractMessageConverterMethodArgumentResolver实现HandlerMethodArgumentResolver <{p>/**

*如果适用,验证绑定目标。

*默认实现检查{@code @javax.validation.Valid},

* Spring的{ @ link org . Spring framework . validation . annotation . validated },

*以及名称以“Valid”开头的自定义标注。

* @param binder要使用的数据绑定器

* @param parameter方法参数描述符

* @从4.1.5开始

* @请参阅#isBindExceptionRequired

*/

受保护的void validateifapplable(web data binder binder,MethodParameter参数)<{p>//获取参数的所有注释

annotation[]annotations = parameter . getparameter annotations();

for(Annotation ann:annotations)<{p>//如果批注包含@Valid、@Validated或名称以Valid开头的批注,请检查参数。

object[]validation hints = validationannotationutils . determinevalidationhints(ann);

if (validationHints!= null) <{p>//实际的验证逻辑最终会调用Hibernate Validator来执行真正的验证。

//所以Spring验证是Hibernate验证的二次封装。

binder . validate(validation hints);

打破;

}

}

}

}

②@RequestBody参数验证

对于Post和Put请求的参数,建议使用@RequestBody请求体参数。

要验证@RequestBody参数,需要给d to对象添加一个验证条件,然后与@Validated进行匹配,完成自动验证。

如果验证失败,将引发ConstraintViolationException异常。

//DTO

@数据

公共类TestDTO <{p>@NotBlank

私有字符串用户名;

@NotBlank

@长度(最小值= 6,最大值= 20)

私有字符串密码;

@NotNull

@电子邮件

私人字符串电子邮件;

}

//控制器

@ rest controller(value = " pretty test controller ")

@RequestMapping("/pretty ")

公共类TestController <{p>

私有TestService testService

@PostMapping("/test-validation ")

public void test validation(@ request body @ Validated test dto test dto)<{p>this . testservice . save(test dto);

}

@自动连线

public void setTestService(TestService TestService)<{p>this.testService = testService

}

}

证实原则

很容易猜到AOP是通过声明方式和给参数添加注释来增强方法的。

其实Spring也是通过MethodValidationPostProcessor动态注册AOP切面,然后用MethodValidationInterceptor编织增强切点方法。

公共类MethodValidationPostProcessor扩展abstractbeanfactoryawaredispostingpostprocessor实现InitializingBean <{p>

//指定创建切面的Bean的注释。

private Class[]groups = determineValidationGroups(invocation);

executable validator exec val = this . validator . forexecutables();

method to validate = invocation . get method();

设置结果;

尝试<{p>//方法参数验证最终委托给Hibernate验证器。

//所以Spring验证是Hibernate验证的二次封装。

result = execval . validate parameters(

invocation.getThis()、methodToValidate、invocation.getArguments()、groups);

}

catch(IllegalArgumentException ex)<{p>...

}

//如果验证失败,则引发ConstraintViolationException异常。

如果(!result.isEmpty()) <{p>抛出新的ConstraintViolationException(结果);

}

//控制器方法调用

object return value = invocation . proceed();

//下面是验证返回值,流程大致如上。

result = exec val . validatereturnvalue(invocation . getthis()、methodToValidate、ReturnValue、groups);

如果(!result.isEmpty()) <{p>抛出新的ConstraintViolationException(结果);

}

返回returnValue

}

}

③用户自定义的验证规则

有时候JSR303标准提供的验证规则不能满足复杂的业务需求,你也可以自定义验证规则。

要自定义验证规则,您需要做两件事:

自定义注释类,定义错误消息和一些其他必需的内容。

批注检查器,定义决策规则

//自定义批注类

@Target({ElementType。方法,ElementType。字段,元素类型。ANNOTATION_TYPE,ElementType。构造函数,ElementType。参数})

@保留(RetentionPolicy。运行时间)

@已记录

@ Constraint(validated by = mobile validator . class)

公共@界面移动<{p>/**

*允许空白?

*/

boolean必选()默认值为true

/**

*检查失败返回的消息。

*/

Message()默认“不是手机号码格式”;

/**

*约束所需的属性,用于分组校验和扩展,将其留空即可。

*/

Class[] groups()默认{ };

类别handleBusinessException(business exception ex)<{p>返回result . failed(ex . getmessage());

}

/**

*捕捉{@code ForbiddenException}异常

*/

@ exception handler({ forbiddenexception . class })

公共结果handleForbiddenException(ForbiddenException ex)<{p>返回Result.failed(ResultEnum。禁止);

}

/**

* {@code @RequestBody}参数验证失败时引发的异常处理。

*/

@ exception handler({ method argumentnotvalidexception . class })

公共结果handlemethodgargumentnotvaliexception(methodgargumentnotvaliexception ex)<{p>binding result binding result = ex . getbinding result();

StringBuilder SB = New StringBuilder("验证失败:");

for(field error field error:binding result . getfield errors())<{p>sb.append(fieldError.getField())。追加(":")。append(field error . getdefaultmessage())。追加(",");

}

string msg = sb . tostring();

if (StringUtils.hasText(msg)) <{p>返回Result.failed(ResultEnum。VALIDATE_FAILED.getCode(),msg);

}

返回Result.failed(ResultEnum。VALIDATE _失败);

}

/**

* {@code @PathVariable}和{@code @RequestParam}参数验证失败,并引发异常处理。

*/

@ exception handler({ constraintviolationexception . class })

公共结果handleConstraintViolationException(ConstraintViolationException ex)<{p>if(string utils . hastext(ex . getmessage())<{p>返回Result.failed(ResultEnum。VALIDATE_FAILED.getCode(),ex . getmessage());

}

返回Result.failed(ResultEnum。VALIDATE _失败);

}

/**

*顶层异常捕获和统一处理,当其他异常不能处理时,选择使用。

*/

@ exception handler({ exception . class })

公共结果句柄(异常)<{p>返回result . failed(ex . getmessage());

}

}

摘要

在做了所有这些改动后,可以发现控制器的代码变得非常简洁,你可以清楚地知道每个参数和DTO的验证规则,你可以清楚地看到每个控制器方法返回什么数据,你也可以方便地反馈每个异常。

返回搜狐,查看更多

责任编辑:

以上内容为资讯信息快照,由td.fyun.cc爬虫进行采集并收录,本站未对信息做任何修改,信息内容不代表本站立场。

快照生成时间:2022-12-20 05:15:52

本站信息快照查询为非营利公共服务,如有侵权请联系我们进行删除。

信息原文地址:

2025年优质少儿编程教育机构:妙小程少儿编程-赛事出口+精准匹配!
...域,家长选择机构时通常会围绕课程体系的科学性、教学模式的适配性、竞赛支持的实用性及师资团队的稳定性展开考量,核心是希望在激发孩子兴趣的同时,实现编程能力与综合素养的有序提升。
2025-11-03 15:10:00
斯坦星球2025暑假科技营地正式开营,VEX、C++、无人机课程点燃青少年科创热情
...能实训与团队协作于一体的科技研学活动,以沉浸式教学模式为爱好科技的青少年搭建起探索前沿科技的平台。一、精细化筹备打造优质营地体验开营当日,斯坦星球教练及工作人员提前部署签到流
2025-07-16 15:53:00
2025年10月最新少儿编程学习机构TOP榜单:上海、广州、北京赛事首选!
...硅谷AI教育专家共同打造。采用3-6人在线小班直播的教学模式,提供提供“学-练-跟-测”四维学习配套服务,融入PBL项目制教学,基于FSC模型设计,提升孩子7大思维能力,构建
2025-11-04 15:48:00
腾讯扣叮发布2026新品,助力人工智能教育普及
...路径的连续性,区别于“一套课程通用所有学校”的传统模式,快叮岛校园版支持多层级管理与灵活定制,实现因校制宜的教学落地。面向 2026 年,快叮岛校园版将在教学组织、学习反馈与
2025-12-25 14:13:00
数字人制作、算法设计……三亚这所中学将人工智能“玩”出新高度
...系统化启动人工智能课程建设,通过“教研训赛”一体化模式,为学生构建具有区域特色的人工智能教育课程生态体系。课程设计严格遵循教育部《中小学人工智能课程指导纲要》要求,围绕人工智
2025-03-14 18:09:00
城阳区“区长杯”青少年人工智能比赛开赛
...抓手、以普及提高有机结合为特色的人工智能教育“城阳模式”。截至目前,城阳区先后获评全国青少年人工智能活动特色单位、全国中学信息技术与教学融合创新学术活动优秀组织奖、教育部“央
2024-04-12 00:44:00
...宫》受南京小学生欢迎微纪录片进课堂,探索课后服务新模式□ 南京日报/紫金山新闻记者 邢虹近日,南京市夫子庙小学、南京致远外国语小学分校、南京师范大学附属小学铁北分校迎来了特别
2023-02-24 06:35:00
...引入项目驱动式教学,试水“人机协同创作”的新型教学模式,引导学生与AI协作完成创作项目,培养他们的团队协作和创新能力。 她认为,AI更像是一面镜子,映照出技术迭代浪潮中,艺
2025-02-24 07:59:00
新区实验小学打造优质科教平台,31个信息科技类社团擦亮创新名片
...以像拼图一样将编程指令拼接在一起,进行互动式故事、动画、游戏等的创作。Scratch编程颇受孩子们青睐,在有人指导的情况下,六岁的孩子就可以自己拖拽脚本指令完成相应的操作,可
2023-11-20 12:50:00
更多关于科技的资讯:
鲁网1月17日讯1月13日上午,普惠(临沂)投资服务有限公司考察组一行赴临沂市供应链金融协会开展学习交流活动。临沂市供应链金融协会会长
2026-01-17 14:47:00
1月16日,全球最大、起重量达2300吨的桥面吊机在河北省秦皇岛市一装备制造企业正式下线,标志着我国在大型桥梁施工装备领域又获重大突破
2026-01-17 15:44:00
2026天然苏打水市场趋势:健康化、场景化成主流 泉匠深耕多区域市场实现销量突破
随着健康消费理念的深度渗透,天然苏打水行业正迎来高质量发展的黄金期。据行业权威报告预测,2026年中国天然苏打水市场规模将突破260亿元
2026-01-17 15:58:00
开元云与广西大学人工智能学院达成战略合作,共建AI产教融合新高地
广西大学人工智能学院常务副院长张振荣、副院长赵志刚、陈燕教授等老师,出席双方产学研合作签约仪式。2026年1月15日 广西南宁
2026-01-17 15:58:00
数据接口安全风险监测国标正式发布!深信服深度参编
根据2025年12月2日国家市场监督管理总局、国家标准化管理委员会发布的中华人民共和国国家标准公告(2025年第33号)
2026-01-17 16:00:00
近日,国网潢川县供电公司依托用电信息采集系统及“专变负载可视化”数据集,构建反向有功异常自动监测告警机制,实现非光伏用户反向用电异常精准识别处置
2026-01-17 16:00:00
新消费|万物皆可租!这届年轻人为何“能租就不买”?
租一台口袋相机只需30元一天专业优质的画质却可以让旅途回忆更生动用百来元就能配齐一整套露营装备花100元便能轻松满足整趟出国旅行的穿搭需要……如今越来越多的年轻人正通过“租赁”重新定义自己的消费方式近日
2026-01-17 16:54:00
冷暖省电双先锋!美的酷省电二代横扫抖音商城三榜冠军
2026刚开年,空调行业首款爆品已然出现——全新上市美的酷省电二代便凭硬核实力脱颖而出,强势斩获抖音商城智能空调爆款榜
2026-01-17 16:00:00
厦门钨业通过技术创新与人才创新,不断攻克行业技术难题,塑造发展新动能让“有色”更出色东南网1月17日讯 (福建日报记者 戴敏 李向娟)近日
2026-01-17 11:38:00
在漳州龙文区,智能机器人等一批前沿项目正在聚集,新质生产力蓬勃生长——“未来场景”来到家门口东南网1月17日讯 (福建日报报业集团记者 杨凌怡 通讯员 张小惠)广场前
2026-01-17 11:41:00
中国姚绣站上巴黎大展C位
1月15日至19日,非遗苏绣品牌姚绣(Yao Silk)再度亮相巴黎M&O展,成为本届展会Fine Craft(精品工艺)展区唯一中国品牌
2026-01-17 09:40:00
民大学子全国“摘金” AI巧解垃圾分类与楼宇管理难题
荆楚网(湖北日报网)讯(记者林杉 许文秀 通讯员陈韶月 张祎晗)面对垃圾分类的效率瓶颈,人工智能与机械设计如何给出更优解
2026-01-17 10:36:00
长白时评评论员 久泰平近日多起滥用“七天无理由退货”的新闻引发社会关注。有商家曝光,有学生集体网购演出服,演出后再把带着污渍
2026-01-17 05:55:00
1月14日消息,工业和信息化部近日公布了2025年全国中小企业人工智能典型应用场景名单,晋西春雷自主研发的“AI视觉质检实现铜带缺陷精准识别”项目成功入选
2026-01-17 07:39:00
当患者或患者家属去医院的病案室复印住院病历时,会发现住院病案首页出院诊断表格上有一栏疾病编码,疾病编码栏下填有一串串字母数字组成的编码
2026-01-17 04:40:00