在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
agile-mvcAgile-Framework系列脚手架致力于帮助开发人员从繁重的代码当中解脱出来,致力于”用最简单的代码勾画出最美的艺术“这一不变的理念。Spring-Agile提供Web开发一站式解决方案。此项目包含Web开发相关的各种必要组件及辅助工具集,方便开发者通过Agile 编程模型轻松使用这些组件来开发单体应用及分布式应用。agile-mvc作为agileframework系列框架最初的发展根基,不断开枝散叶,目前已成功衍生出十几个独立、特色化功能开发组件, 参考文档 请查看 WIKI正在编写中 。 主要功能
快速入门开始你的第一个项目是非常容易的。 简单样例工程地址: 步骤 1: 下载包您可以从[最新稳定版本]下载包(https://github.com/mydeathtrial/agile-mvc/releases). 该包已上传至maven中央仓库,可在pom中直接声明引用 以最新版本agile-mvc-2.1.0.M5.jar为例。 步骤 2: 添加maven依赖<!--声明中央仓库--><repositories> <repository> <id>cent</id> <url>https://repo1.maven.org/maven2/</url> </repository></repositories> <!--声明组件依赖--><dependency><groupId>cloud.agileframework</groupId><artifactId>agile-mvc</artifactId><version>2.1.0.M5</version></dependency> 步骤 3: 开箱即用声明agile-mvc依赖后,组件通过spring-boot-starter方式自动加载生效,无需额外配置。组件额外配置,启动后控制台会出现Agile启动标识: _____/\\\\\\\\\________/\\\\\\\\\\\\__/\\\\\\\\\\\__/\\\______________/\\\\\\\\\\\\\\\_ ___/\\\///////\\\____/\\\//////////__\/////\\\///__\/\\\_____________\/\\\///////////__ __/\\\_______\/\\\__/\\\_________________\/\\\_____\/\\\_____________\/\\\_____________ _\/\\\_______\/\\\_\/\\\____/\\\\\\\_____\/\\\_____\/\\\_____________\/\\\\\\\\\\\_____ _\/\\\\\\\\\\\\\\\_\/\\\___\/////\\\_____\/\\\_____\/\\\_____________\/\\\///////______ _\/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_____\/\\\_____________\/\\\_____________ _\/\\\_______\/\\\_\/\\\_______\/\\\_____\/\\\_____\/\\\_____________\/\\\_____________ _\/\\\_______\/\\\_\//\\\\\\\\\\\\/___/\\\\\\\\\\\_\/\\\\\\\\\\\\\\\_\/\\\\\\\\\\\\\\\_ _\///________\///___\////////////____\///////////__\///////////////__\///////////////__ :: 敏捷开发框架 Agile Framework :: (version:1.0) 警告:2.0.0版本中由于首次于中央仓库发包,忙中出错,默认配置文件加载功能存在设计不足,默认的配置文件加载仅扫描以springboot应用类所在包为根目录开始扫描,所以自定义包名情况下未能包含框架默认配置包cloud.agileframework.conf,导致默认配置未能加载。所以中央仓库2.0.0版本使用过程中需增加springmvc对静态资源访问的默认配置,防止静态资源HandlerMapping优先拦截请求,后续版本中去掉了的静态资源的默认配置与限制,修复了该问题: spring: messages: basename: '**/message' mvc: static-path-pattern: /static/** resources: static-locations: classpath:static/ 步骤 4: 声明AgileService代理服务
//传统Service层@Servicepublic class MyService { public Object myBusinessMethod(String param){ //业务编码及持久层能力调用... }}//AgileService代理服务,该注解声明类,仍会被在ComponentScan扫描范围内加载到spring容器中@AgileServicepublic class MyService { //该方法默认生成API http://host:port/api/MyService/myBusinessMethod //该映射地址可以通过@Mapping注解覆盖定义,其用法步骤5中讲解 //该方法入参将由抽象控制器直接提供请求参数解析装配,并提供@Validation注解校验 //该方法默认提供spring事务包裹 //该方法return返回数据,将自动被抽象控制器包装、格式化成统一响应视图,直接返回前端 public Object myBusinessMethod(String param){ //业务编码及持久层能力调用... }} 效果对比 传统Service层:仅提供控制层调用能力AgileService代理服务:1、提供控制层调用能力;2、提供客户端API调用能力;3、参数验证能力;4、默认事务;5、自动包装、格式化成统一响应视图; 步骤 5: AgileService代理服务API地址映射组件为 //AgileService代理服务@AgileServicepublic class MyService { //禁止暴露,该注解也可直接应用于类注解,应用于类注解时,组件将不对声明类内部任何public方法提供能力扩展 @NotAPI public Object myBusinessMethod(String param){ //业务编码及持久层能力调用... } //限制访问方法,默认不限制请求访问方法,可以通过该注解限定访问方法种类 @ApiMethod({RequestMethod.POST,RequestMethod.GET}) public Object myBusinessMethod(String param){ //业务编码及持久层能力调用... } //覆盖默认地址映射,当声明@Mapping注解后,组件将不提供给该方法默认地址映射方案 //该注解使用方法同@RequestMapping完全一致,支持声明地址传参、多地址映射、访问方法等等内容 @Mapping(path = "/test2/{id}") public Object myBusinessMethod(String id){ //业务编码及持久层能力调用... }} 警告:默认情况下组件会拦截除静态资源以外的所有请求路径,所以需要静态资源地址头应该与正常的API地址区分开,默认使用 spring: mvc: static-path-pattern: /static/** 步骤 6: 参数解析组件为
//body入参为例{ "id":111, "param":"第二个参数", "pojo":{ "attr1":1, "attr2":2 }, "collect":[ { "attr1":1, "attr2":2 }, { "attr1":1, "attr2":2 } ]} 声明解析 //AgileService代理服务@AgileServicepublic class MyService { //参数解析过程将依据方法参数名,如下方法的id、param、pojo为key值,于入参集合中提取后做类型转换并填充 //其中多层嵌套参数提取,需要通过参数命名中使用下划线区分参数层级,如pojo下的attr1参数,需要使用pojo_attr1命名 //拍平取参,支持将任意层级参数进行集合拍平处理,如collect_attr1参数 @Mapping(path = "/test2/{id:[\\d]+}") public Object myBusinessMethod(int id, String param, YourPojo pojo, int pojo_attr1, List<Integer> collect_attr1){ //业务编码及持久层能力调用... }} 直调解析(可于请求线程内任意位置调用AgileParam) public class MyService { public Object myBusinessMethod() { Integer id = AgileParam.getInParam("id", Integer.class); String param = AgileParam.getInParam("param", String.class); YourPojo pojo = AgileParam.getInParam("param", YourPojo.class); Integer attr1 = AgileParam.getInParam("pojo.attr1", Integer.class); List<Integer> attr1s = AgileParam.getInParam("collect.attr1", new TypeReference<List<Integer>>() { }); }} 文件上传参数 public class MyService { //file为前端传递的文件key值 public Object myBusinessMethod(MultipartFile file){ } //直接以流方式声明 public Object myBusinessMethod(InputStream file){ } //多文件 public Object myBusinessMethod(MultipartFile[] file){ } //可以是MultipartFile的任意集合类型 public Object myBusinessMethod(Set<MultipartFile> file){ }} 警告:
步骤 7: 参数验证该参数验证适用于 @Validate(value = "file", nullable = false)@Validate(value = "id", customBusiness = {MyValidate.class})@Mapping(path = "/test/{id}")public Object test(int id,MultipartFile[]file){ //业务代码 }//自定义业务验证public static class MyValidate implements ValidateCustomBusiness { //此处params为id值,当验证失败后需要自行组装错误信息List<ValidateMsg>,当错误信息为空集合时,认为参数准确,不进行拦截 @Override public List<ValidateMsg> validate(Object params) { return null; }} 响应报文 { "head": { "ip": "192.168.101.42", "code": "100002", "msg": "参数错误", "status": "OK" }, "result": [ { "message": "不允许为空值", "state": false, "item": "file", "itemValue": null } ]} 步骤 8: 统一响应视图默认统一响应视图分为头(head)体(result)两部分组成,组件对全局异常以及超范围请求均做了拦截, 并且将最终的拦截结果与国际化配置结合组装成统一响应视图 { "head": { "ip": "172.29.128.1", "code": "100000", "msg": "操作失败", "status": "INTERNAL_SERVER_ERROR" }, "result": null} 定制化响应报文
@Componentpublic class CommonResponseFormate extends AbstractResponseFormat { @Override public Map<String, Object> buildResponseData(Head head, Object result) { //head为组件整理后的响应头部信息 //result为响应体信息 //自行定制返回结果状态为Map格式返回,该Map将作为ModelAndView中的Model组装成视图写入response return null; }} 为保证原有
@Controllerpublic class MyController{ @RequestMapping("/test") public ModelAndView test(String a) { //业务代码... //设置响应头head AgileReturn.setHead(RETURN.SUCCESS); //设置响应体result AgileReturn.add("a",a); //构建返回视图 return AgileReturn.build(); }}
@AgileServicepublic class MyService { //任何return结果都将组装成result部分 //头部信息则会根据是否捕获Exception异常界定head内部信息,未捕获情况下均使用正常success头 public Object myBusinessMethod(String param) { //业务编码及持久层能力调用... return xx; } //手动设置响应头,返回类型设为RETURN,该方式存在代码入侵,尽在该方法不存在复用情况下使用为好 public RETURN myBusinessMethod(String param) { //业务代码... //构建返回视图 return RETURN.SUCCESS; } //利用国际化构造响应头head,更多RETURN用法请参照wiki public RETURN myBusinessMethod(String param) { //业务代码... //构建返回视图 return RETURN.byMessage("国际化key", "国际化参数1", "国际化参数2..."); } //手动设置响应体result public void myBusinessMethod(String param) { //业务代码... //设置响应体result AgileReturn.add("a", param); } //通过异常声明响应头 //统一一场拦截器捕捉到异常后,会根据异常类引用名去国际化配置文件中获取响应文与响应编码信息,可阅读步骤11统一异常处理 public void myBusinessMethod(String param) throws YourException { //业务代码... //设置响应体result AgileReturn.add("a", param); throw new YourException(); }} 步骤 9: 自动配置借助agile系列套件common-util中PropertiesUtil的配置加载能力,实现在工程启动阶段自动扫描应用类所在包下以及编译路径下配置文件。 避免杂乱的配置文件位置声明。
连接到目标VM, 地址: ''127.0.0.1:56967',传输: '套接字'', 传输: '{1}'/D:/workspace-agile/agile/target/classes/cloud/agileframework/message.properties/D:/workspace-agile/agile/target/classes/cloud/agileframework/message_en.properties/D:/workspace-agile/agile/target/classes/cloud/agileframework/message_zh.properties/D:/workspace-agile/agile/target/classes/META-INF/additional-spring-configuration-metadata.json/D:/workspace-agile/agile/target/classes/META-INF/spring-configuration-metadata.json/D:/workspace-agile/agile/target/classes/META-INF/spring.factories/D:/workspace-agile/agile/target/classes/static/favicon.ico/framework/application-agile.yml/framework/application-alibaba.yml/framework/application-cache.yml/framework/application-datasource.yml/framework/application-druid.yml/framework/application-ehcache.yml/framework/application-es.yml/framework/application-jpa.yml/framework/application-kafka.yml/framework/application-kaptcha.yml/framework/application-log.yml/framework/application-mvc.yml/framework/application-redis.yml/framework/bootstrap.yml/framework/message.properties/framework/message_en.properties/framework/message_zh.properties/D:/workspace-agile/agile/target/classes/application-agile.yml 配置加载过程不依赖spring,加载后会回填至spring容器,后续PropertiesUtil配置参数提取则优先使用spring容器中有效的environment, 所以该加载过程不影响微服务情况下动态配置管理的使用 步骤 10: 国际化配置借助Agile套件spring-util工具包中的MessageUtil,为spring的国际化配置文件扫描增加了Ant风格配置文件路径在家支持,并兼容原生配置方式。原生spring中不支持spring.messages.basename不支持 spring: messages: encoding: UTF-8 basename: '**/message' 步骤 11: 统一异常处理组件通过@ControllerAdvice与HandlerExceptionResolver实现统一异常处理,会将捕获到的任何异常加工为响应视图,开发者可以针对不同的异常类,定义不同的国际化响应信息。以自定义异常类 com.agile.YourException=100017:无效用户名或密码,请重新登录 其中 { "head": { "ip": "192.168.101.42", "code": "100017", "msg": "无效用户名或密码,请重新登录", "status": "INTERNAL_SERVER_ERROR" }, "result": null} 其中的 |
请发表评论