当前位置: 首页 > 科技观察

SpringBoot项目应该包含什么?

时间:2023-03-21 17:05:27 科技观察

前言创建一个全新的项目,或者将旧的庞大项目拆分成多个项目。在新建项目时,往往需要做一些重复性的工作,比如复制常用的工具类、常用的代码等等。所以你可以做一个基础工程,方便使用。体验新项目时,直接在基础项目上简单配置即可开发业务代码。基本项目应该包含什么。Swagger在线接口文档。CodeGenerator代码生成器。团结回归。通用分页对象。常用工具。全局异常拦截。错误枚举。自定义异常。多环境配置文件。Maven多环境配置。日志配置。詹金斯文件。swagger写接口文档通常是一件很头疼的事情,但是swagger就是用来帮我们解决这个问题的。接口文档可以在线生成,可以在页面上进行测试。可以很清楚的显示请求的数据已经响应了数据。当然,这一切都需要在代码中进行配置。“注意事项:接口文件只能在测试/开发环境打开,其他环境请关闭。”常用的Swagger注解@Api用于Controller@ApiOperation用于Controller中的方法。@ApiResponses用于标识接口返回的数据类型。@ApiModel用于标识类的名称@ApiModelProperty用于标识属性case的名称@RestController@Api(tags="User")@AllArgsConstructor@RequestMapping("/user")publicclassUserController{privateIUserServiceuserService;/***获取用户列表*@paramlistUserForm表单数据*@return用户列表*/@ApiOperation("获取用户列表")@GetMapping("/listUser")@ApiResponses(@ApiResponse(code=200,message="操作成功",response=UserVo.class))publicResultVolistUser(@ValidatedListUserFormlistUserForm){returnResultVoUtil.success(userService.listUser(listUserForm));}}@Data@ApiModel("获取用户列表需要的表单数据")@EqualsAndHashCode(callSuper=false)publicclassListUserFormextendsPageForm{/***用户状态*/@ApiModelProperty("用户状态")@NotEmpty(message="用户状态不能为空")@Range(min=-1,max=1,message="用户状态错误")privateStringstatus;}对应swagger的配置可以查看SwaggerConfiguration。基础项目中的java。点此查看详细教程。关注公众号Java技术栈,回复boot获取SpringBoot系列教程。CodeGenerator代码生成器。mybatis_plus代码生成器可以帮助我们生成entity、service、serviceImpl、mapper、mapper.xml。省去了创建大量实体类的麻烦。如果你还没有听说过,可以点击这里参考这篇文章。由于配置太长,这里就不贴了。对应的CodeGenerator的配置可以查看基础工程中的CodeGenerator.java。常用包统一返回。ResultVo统一了所有接口响应数据的格式。@Data@ApiModel("固定返回格式")publicclassResultVo{/***错误码*/@ApiModelProperty("错误码")privateIntegercode;/***提示信息*/@ApiModelProperty("提示信息")privateStringmessage;/***具体内容*/@ApiModelProperty("Responsedata")privateObjectdata;}抽象形式BaseFormpublicabstractclassBaseForm{/***获取实例*@return返回实体类*/publicabstractTbuildEntity();}可能有小伙伴有疑问,这个类有什么用。看看下面的代码。/***添加用户*@paramuserForm表单数据*@returntrueorfalse*/@OverridepublicbooleanaddUser(AddUserFormuserForm){Useruser=newUser();user.setNickname(userForm.getNickname());user.setBirthday(userForm.getBirthday());user.setUsername(userForm.getUsername());user.setPassword(userForm.getPassword());returnsave(user);}重构,感觉清爽一点。/***添加用户*@paramuserForm表单数据*@returntrueorfalse*/@OverridepublicbooleanaddUser(AddUserFormuserForm){Useruser=newUser();BeanUtils.copyProperties(this,user);returnsave(user);}重构使用BaseFormAddUserForm继承BaseForm并重写buildEntity@Data@EqualsAndHashCode(callSuper=false)publicclassAddUserFormextendsBaseForm{/***nickname*/privateStringnickname;/***birthday*/privateDatebirthday;/***username*/privateStringusername;/***Password*/privateStringpassword;/***构造实体*@return实体对象*/@OverridepublicUserbuildEntity(){Useruser=newUser();BeanUtils.copyProperties(this,user);returnuser;}}/***添加用户*@paramuserFormformdata*@returntrueorfalse*/@OverridepublicbooleanaddUser(AddUserFormuserForm){returnsave(userForm.buildEntity());}上面的代码是不是感觉很眼熟?很多情况下,将接收到的参数更改为对应的实体类,然后“保存”或“更新”。所以对于这种形式,可以继承baseform,实现buildEntity(),可以更加面向对象。该服务不需要关心表单如何转换为实体。它只需要在使用的时候调用buildEntity(),尤其是在form->entity比较复杂的时候,这样做可以减少服务中的代码。让代码逻辑看起来更清晰。一般的分页对象在涉及查询的时候,大部分都需要用到分页,所以需要对分页对象进行封装。可以关注PageForm.calcCurrent()、PageVo.setCurrentAndSize()、PageVo.setTotal()这几个方法。PageForm@Data@ApiModel(value="页面数据",description="分页所需的表单数据")publicclassPageForm>{/***页码*/@ApiModelProperty(value="页码从第一页1")@Min(value=1,message="页码输入错误")privateIntegercurrent;/***每页显示的页数*/@ApiModelProperty(value="页码显示的范围每页1~100")@Range(min=1,max=100,message="每页显示数量输入错误")privateIntegersize;/***计算当前页,方便mysql执行分页查询*@return返回pageForm*/@ApiModelProperty(hidden=true)publicTcalcCurrent(){current=(current-1)*size;return(T)this;}}PageVo@DatapublicclassPageVo{/***分页数据*/@ApiModelProperty(value="Pageddata")privateListrecords;/***记录总数*/@ApiModelProperty(value="Totalnumberofrecords")privateIntegertotal;/***总页数*/@ApiModelProperty(value="Totalnum页数”)privateIntegerpages;/***当前页*/@ApiModelProperty(value="当前页")privateIntegercurrent;/***问题数量*/@ApiModelProperty(value="问题数量")privateIntegersize;/***设置当前页和每个page要显示的数量*@parampageForm分页形式*@return返回分页信息*/@ApiModelProperty(hidden=true)publicPageVosetCurrentAndSize(PageFormpageForm){BeanUtils.copyProperties(pageForm,this);returnthis;}/***设置记录总数*@paramtotaltotal记录数*/@ApiModelProperty(hidden=true)publicvoidsetTotal(Integertotal){this.total=total;this.setPages(this.total%this.size>0?this.total/this.size+1:this.total/this.size);}}CaseListUserForm@Data@ApiModel("获取用户列表需要的表单数据")@EqualsAndHashCode(callSuper=false)publicclassListUserFormextendsPageForm{/***UserStatus*/@ApiModelProperty("用户状态")@NotEmpty(message="用户状态不能为空")@Range(min=-1,max=1,message="用户状态有误")privateStringstatus;}UserServiceImpl/***获取用户列表*@paramlistUserForm表单数据*@return用户列表*/@OverridepublicPageVolistUser(ListUserFormlistUserForm){PageVopageVo=newPageVo().setCurrentAndSize(listUserForm);pageVo.setTotal(countUser(listUserForm.getStatus()));pageVo.setRecords(userMapper.listUser(listUserForm.calcCurrent()));returnpageVo;}/***获取用户数*@paramstatusstatus*@return用户数*/privateIntegercountUser(Stringstatus){returncount(newQueryWrapper().eq("status",status));}UserController/***获取用户列表*@paramlistUserForm表单数据*@return用户列表*/@ApiOperation("获取用户列表")@GetMapping("/listUser")@ApiResponses(@ApiResponse(code=200,message="操作成功",response=UserVo.class))publicResultVolistUser(@ValidatedListUserFormlistUserForm){returnResultVoUtil.success(userService.listUser(listUserForm));}注意PageVo需要设置“当前实例化时的“page”和“每页显示的数字”可以调用setCurrentAndSize()完成分页查询,需要计算偏移量。为什么listUserForm.calcCurrent()会计算偏移量?如果查询的第一页每页显示10条记录,前端传递的参数是current=1&&size=10,此时限制1、10是没有问题的。如果查询的第2页显示10条记录,前端传递的参数是current=2&&size=10,那么limit2,10就有问题,实际应该是limit10,10。这就是calcCurrent()所做的。为什么不用MybatisPlus自带的分页插件呢??内置的分页查询在大量数据下会有性能问题。?常用工具类常用工具类可以根据自己的开发习惯引入。推荐阅读:国人开源了一个小而全的Java异常处理工具库。异常处理的一般流程如下。抛出异常信息->ControllerAdvice捕获格式化输出内容手动抛出CustomException并传递给ReulstEnum-->捕获错误信息并输出错误信息。自定义异常@Data@EqualsAndHashCode(callSuper=false)publicclassCustomExceptionextendsRuntimeException{/***状态码*/privatefinalIntegercode;/***方法名*/privatefinalStringmethod;/***自定义异常**@paramresultEnum返回枚举对象*@parammethod方法*/publicCustomException(ResultEnumresultEnum,Stringmethod){super(resultEnum.getMsg());this.code=resultEnum.getCode();this.method=method;}/***@paramcode状态码*@parammessage错误信息*@parammethodmethod*/publicCustomException(Integercode,Stringmessage,Stringmethod){super(message);this.code=code;this.method=method;}}根据业务添加错误信息枚举。@GetterpublicenumResultEnum{/***未知异常*/UNKNOWN_EXCEPTION(100,"未知异常"),/***添加失败*/ADD_ERROR(103,"添加失败"),/***更新失败*/UPDATE_ERROR(104,"更新失败"),/***删除失败*/DELETE_ERROR(105,"删除失败"),/***搜索失败*/GET_ERROR(106,"查找失败"),;privateIntegercode;privateStringmsg;ResultEnum(Integercode,Stringmsg){this.code=code;this.msg=msg;}/***通过状态码获取枚举对象*@paramcode状态码*@return枚举对象*/publicstaticResultEnumgetByCode(intcode){for(ResultEnumresultEnum:ResultEnum.values()){if(code==resultEnum.getCode()){returnresultEnum;}}returnnull;}}全局异常拦截全局异常拦截使用@ControllerAdvice实现。常用的异常拦截配置参见GlobalExceptionHandling。@Slf4j@RestControllerAdvicepublicclassGlobalExceptionHandling{/***自定义异常*/@ExceptionHandler(value=CustomException.class)publicResultVoprocessException(CustomExceptione){log.error("Location:{}->ErrorMessage:{}",e.getMethod(),e.getLocalizedMessage());returnResultVoUtil.error(Objects.requireNonNull(ResultEnum.getByCode(e.getCode())));}/***一般异常*/@ResponseStatus(HttpStatus.OK)@ExceptionHandler(Exception.class)publicResultVoexception(Exceptione){e.printStackTrace();returnResultVoUtil.error(ResultEnum.UNKNOWN_EXCEPTION);}}CaseController/***删除用户*@paramidusernumber*@返回成功或失败*/@ApiOperation("删除用户")@DeleteMapping("/deleteUser/{id}")publicResultVodeleteUser(@PathVariable("id")Stringid){userService.deleteUser(id);returnResultVoUtil.success();}服务/***删除用户*@paramidid*/@OverridepublicvoiddeleteUser(Stringid){//如果删除失败,则抛出异常。--不建议这样演示if(!removeById(id)){thrownewCustomException(ResultEnum.DELETE_ERROR,MethodUtil.getLineInfo());}}Result"打印出错误码所在文件的行数。方便排查问题。”注意,所有手动抛出的错误信息都应该统一维护在错误信息枚举ResultEnum中。不同的服务使用不同的错误代码。方便区分什么时候报错。快速定位问题。多环境配置SpringBoot多环境配置基本上一个项目有dev、test、pre、prod4个环境,给SpringBoot项目多创建几个配置文件就够了。然后就可以在启动时通过配置spring.profiles.active来选择启动环境了。详细教程请关注公众号Java技术栈回复boot获取系列教程。java-jarBasicProject.jar--spring.profiles.active=prodMaven多环境配置如果想在打包的时候动态指定环境,需要使用Maven的xml来实现。对此请关注公众号Java技术栈,回复mvn获取完整详细教程。配置XMLdevtruedevtesttestprepreprodprod更改application.ymlspring:profiles:#selectenvironmentactive:@activatedProperties@Usagecasemvncleanpackage-Pprodmvncleanpackage-Ppremvncleanpackage-Ptest打包后可以解压查看应用n.yml会发现spring.profiles.active=@activatedProperties@变了。日志配置使用logback日志配置。点击这里参考这篇文章。JenkinsFileJenkinsFile顾名思义必须用于jenkins。主要是根据项目的构建方式和发布到不同环境的方式来配置项目。需要了解管道语法以及如何配置jenkins。如果觉得结局对你有帮助,可以点开观看,谢谢。