点击上方“方志朋”,选择“设为星标”

回复”666“获取新整理的面试文章

最近使用Spring Boot 配合 MyBatis 、通用Mapper插件、PageHelper分页插件 连做了几个中小型API项目,做下来觉得这套框架、工具搭配起来开发这种项目确实非常舒服,团队的反响也不错。在项目搭建和开发的过程中也总结了一些小经验,与大家分享一下。

在开发一个API项目之前,搭建项目、引入依赖、配置框架这些基础活自然不用多说,通常为了加快项目的开发进度(早点回家)还需要封装一些常用的类和工具,比如统一的响应结果封装、统一的异常处理、接口签名认证、基础的增删改差方法封装、基础代码生成工具等等,有了这些项目才能开工。

然而,下次再做类似的项目上述那些步骤可能还要搞一遍,虽然通常是拿过来改改,但是还是比较浪费时间。所以,可以利用面向对象抽象、封装的思想,抽取这类项目的共同之处封装成了一个种子项目(估计大部分公司都会有很多类似的种子项目),这样的话下次再开发类似的项目直接在该种子项目上迭代就可以了,减少无意义的重复工作。

在相关项目上线之后,我花了点时间对该种子项目做了一些精简,并且已经把该项目分享到GitHub上面了,如果你正准备做类似项目的话,可以去克隆下来试试。

项目地址&使用文档:https://github.com/lihengming/spring-boot-api-project-seed 。

如果在使用中发现问题或者有什么好建议的话欢迎提issue或pr一起来完善它。更多 Spring Boot 博文可以在本公众号「Java后端」回复技术博文获取。

特征&提供

最佳实践的项目结构、配置文件、精简的POM

注:使用代码生成器生成代码后会创建model、dao、service、web等包。

统一响应结果封装及生成工具

/*** 统一API响应结果封装*/
publicclass Result {privateint code;private String message;private Object data;public Result setCode(ResultCode resultCode) {this.code = resultCode.code;returnthis;}//省略getter、setter方法
}
/*** 响应码枚举,参考HTTP状态码的语义*/
publicenum ResultCode {SUCCESS(200),//成功FAIL(400),//失败UNAUTHORIZED(401),//未认证(签名错误)NOT_FOUND(404),//接口不存在INTERNAL_SERVER_ERROR(500);//服务器内部错误publicint code;ResultCode(int code) {this.code = code;}
}
/*** 响应结果生成工具*/
publicclass ResultGenerator {privatestaticfinal String DEFAULT_SUCCESS_MESSAGE = "SUCCESS";public static Result genSuccessResult() {returnnew Result().setCode(ResultCode.SUCCESS).setMessage(DEFAULT_SUCCESS_MESSAGE);}public static Result genSuccessResult(Object data) {returnnew Result().setCode(ResultCode.SUCCESS).setMessage(DEFAULT_SUCCESS_MESSAGE).setData(data);}public static Result genFailResult(String message) {returnnew Result().setCode(ResultCode.FAIL).setMessage(message);}
}

统一异常处理

public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {exceptionResolvers.add(new HandlerExceptionResolver() {public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {Result result = new Result();if (e instanceof ServiceException) {//业务失败的异常,如“账号或密码错误”result.setCode(ResultCode.FAIL).setMessage(e.getMessage());logger.info(e.getMessage());} elseif (e instanceof NoHandlerFoundException) {result.setCode(ResultCode.NOT_FOUND).setMessage("接口 [" + request.getRequestURI() + "] 不存在");} elseif (e instanceof ServletException) {result.setCode(ResultCode.FAIL).setMessage(e.getMessage());} else {result.setCode(ResultCode.INTERNAL_SERVER_ERROR).setMessage("接口 [" + request.getRequestURI() + "] 内部错误,请联系管理员");String message;if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;message = String.format("接口 [%s] 出现异常,方法:%s.%s,异常摘要:%s",request.getRequestURI(),handlerMethod.getBean().getClass().getName(),handlerMethod.getMethod().getName(),e.getMessage());} else {message = e.getMessage();}logger.error(message, e);}responseResult(response, result);returnnew ModelAndView();}});}

常用基础方法抽象封装

publicinterface Service<T> {void save(T model);//持久化void save(List<T> models);//批量持久化void deleteById(Integer id);//通过主鍵刪除void deleteByIds(String ids);//批量刪除 eg:ids -> “1,2,3,4”void update(T model);//更新T findById(Integer id);//通过ID查找T findBy(String fieldName, Object value) throws TooManyResultsException; //通过Model中某个成员变量名称(非数据表中column的名称)查找,value需符合unique约束List<T> findByIds(String ids);//通过多个ID查找//eg:ids -> “1,2,3,4”List<T> findByCondition(Condition condition);//根据条件查找List<T> findAll();//获取所有
}

提供代码生成器来生成基础代码

publicabstractclass CodeGenerator {...public static void main(String[] args) {genCode("输入表名");}public static void genCode(String... tableNames) {for (String tableName : tableNames) {//根据需求生成,不需要的注掉,模板有问题的话可以自己修改。genModelAndMapper(tableName);genService(tableName);genController(tableName);}}...
}

CodeGenerator 可根据表名生成对应的Model、Mapper、MapperXML、Service、ServiceImpl、Controller(默认提供POST和RESTful两套Controller模板,根据需要在 genController(tableName)方法中自己选择,默认是纯POST的),代码模板可根据实际项目的需求来定制,以便渐少重复劳动。

由于每个公司业务都不太一样,所以只提供了一些简单的通用方法模板,主要是提供一个思路来减少重复代码的编写。在我们公司的实际使用中,其实根据业务的抽象编写了大量的代码模板。

提供简单的接口签名认证

public void addInterceptors(InterceptorRegistry registry) {//接口签名认证拦截器,该签名认证比较简单,实际项目中可以使用Json Web Token或其他更好的方式替代。if (!"dev".equals(env)) { //开发环境忽略签名认证registry.addInterceptor(new HandlerInterceptorAdapter() {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//验证签名boolean pass = validateSign(request);if (pass) {returntrue;} else {logger.warn("签名认证失败,请求接口:{},请求IP:{},请求参数:{}",request.getRequestURI(), getIpAddress(request), JSON.toJSONString(request.getParameterMap()));Result result = new Result();result.setCode(ResultCode.UNAUTHORIZED).setMessage("签名认证失败");responseResult(response, result);returnfalse;}}});}
}
/*** 一个简单的签名认证,规则:* 1. 将请求参数按ascii码排序* 2. 拼接为a=value&b=value...这样的字符串(不包含sign)* 3. 混合密钥(secret)进行md5获得签名,与请求的签名进行比较*/
private boolean validateSign(HttpServletRequest request) {String requestSign = request.getParameter("sign");//获得请求签名,如sign=19e907700db7ad91318424a97c54ed57if (StringUtils.isEmpty(requestSign)) {returnfalse;}List<String> keys = new ArrayList<String>(request.getParameterMap().keySet());keys.remove("sign");//排除sign参数Collections.sort(keys);//排序StringBuilder sb = new StringBuilder();for (String key : keys) {sb.append(key).append("=").append(request.getParameter(key)).append("&");//拼接字符串}String linkString = sb.toString();linkString = StringUtils.substring(linkString, 0, linkString.length() - 1);//去除最后一个'&'String secret = "Potato";//密钥,自己修改String sign = DigestUtils.md5Hex(linkString + secret);//混合密钥md5return StringUtils.equals(sign, requestSign);//比较
}

集成MyBatis、通用Mapper插件、PageHelper分页插件,实现单表业务零SQL

使用Druid Spring Boot Starter 集成Druid数据库连接池与监控

使用FastJsonHttpMessageConverter,提高JSON序列化速度

技术选型&文档

  • Spring Boot:https://www.jianshu.com/p/1a9fd8936bd8

  • MyBatis:http://www.mybatis.org/mybatis-3/zh/index.html

  • MyBatisb通用Mapper插件:https://mapperhelper.github.io/docs/

  • MyBatis PageHelper分页插件:https://pagehelper.github.io/

  • Druid Spring Boot Starter:https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter/

  • Fastjson:https://github.com/Alibaba/fastjson/wiki/%E9%A6%96%E9%A1%B5

来源:简单的土豆

链接:www.jianshu.com/p/99fcead32d35

热门内容:Spring&nbsp;Boot注解大全,一键收藏了!
面试:高频面试题:如何保证缓存与数据库的双写一致性?
SpringBoot内存泄露,排查竟这么难!
面试官给我挖坑:URI中的 “//” 有什么用?
SpringBoot配置文件放在jar外部
高效开发:IntelliJ IDEA天天用,这些Debug技巧你都知道?
MySQL 大表优化方案最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
明天见(。・ω・。

一个基于 Spring Boot 的项目骨架相关推荐

  1. 一个基于 Spring Boot 的项目骨架,拿走即用

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:程序员入职国企,1周上班5小时,晒出薪资感叹:腾讯当CEO也不去个人原创+1博客:点击前往,查看更多 作者:简单 ...

  2. 一个基于 Spring Boot 的项目骨架,少造轮子!

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:牛人 20000 字的 Spring Cloud 总结,太硬核了 最近使用Spring Boot 配合 MyBa ...

  3. 简单介绍基于Spring Boot的项目骨架使用

    前言 从大学开始接触 java 后台开发,到后来了解了更多的编程语言的开发.发现 java 的开发可以说是相较而言很复杂的了,光是 Spring MVC 的配置要是没有经历系统的学习,可能就能劝退一波 ...

  4. 自荐Mall4j项目一个基于spring boot的Java开源商城系统

    前言 Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样 ...

  5. 保姆级的一个基于spring boot开发的前后端分离商城教程

    前言 推荐一个基于spring boot开发前后端分离商城,有完整的代码笔记和视频教程,希望对正在找项目练手的同学有所帮助 本文资料文档领取(在文末) 一.项目背景 5中常见的电商模式 B2B .B2 ...

  6. 一个基于 Spring Boot 的开源社区

    一款基于 Spring Boot 的开源社区:forum-java,类似于微信开放社区.头条开发者社区等等.forum-java 是一个 100% 开源的面向内容的社区论坛. 开源社区有用户端和管理端 ...

  7. 推荐一个基于 Spring Boot+MyBatis Plus+JWT 的问卷系统!

    你好呀,我是 Guide!这里是 JavaGuide 的「优质开源项目推荐」第 8 期,每一期我都会精选 5 个高质量的 Java 开源项目. 时间过的真快,不知不觉「优质开源项目推荐」系列已经持续半 ...

  8. 一个基于Spring Boot的API、RESTful API项目骨架

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:简单的土豆 www.jianshu.com/p/99fcea ...

  9. 一个mapper接口有多个mapper.xml 文件_爱了!分享一个基于Spring Boot的API、RESTful API项目种子(骨架)!...

    点击上方"Java专栏",选择"置顶或者星标" 第一时间阅读精彩文章! 1.☞ 程序员进阶必备资源免费送「21种技术方向!」 点击查看☜ 2.☞ <Jav ...

最新文章

  1. 星星模型 维度_用模型“想象”出来的target来训练,可以提高分类的效果!
  2. java监听所有端口_(变强、变秃)Java从零开始之zookeeper安装
  3. struct 与 class区别
  4. C语言程序练习-L1-017 到底有多二 (15分)
  5. 回归素材(part6)--机器学习系统设计
  6. opencv 叠加两张图_OpenCV基础篇之图片叠加
  7. eclipse菜单解释及中英对照《二》
  8. python具备的功能是_用了Python这么多年,揭秘Python不为人知的7大功能和特点!...
  9. Android:随笔—— ConstraintLayout 效率爆表的技巧
  10. 一个没有停止的android闹钟,一旦开始就要把歌唱完 .
  11. 基础知识——常见文件格式
  12. jdbc c3p0 mysql_JDBC+C3P0+DBCP 基本使用
  13. python shell清屏指令_python shell怎么清屏
  14. 做个聪明人,迅速提高你智商的22条途径
  15. python的加减乘除运算_python四则运算
  16. 大学计算机专业绩点3.7什么水平,大学绩点3.0什么水平 绩点达到多少算优秀
  17. Joint Extraction of Entities and Relations Based on a Novel Tagging Scheme
  18. windows安全模式_别再用苹果装Windows 因为macOS实在是太好用了
  19. 皮革行业经销商在线系统:简化采购审批流程,轻松管控代理商
  20. Android简单计时器详解(Timer)

热门文章

  1. Android开发笔记1.2
  2. 谜题59:什么是差?
  3. 积跬步,聚小流------ps有用小技巧,改变png图标颜色
  4. [转]使用设计模式改善程序结构(二)
  5. java io读书笔记(6) Writing Arrays of Bytes
  6. 水面加上了Perlin Noise
  7. LeetCode实战:LRU缓存机制
  8. 没有提示_华为手机发出莫名的提示音,打开什么也没有?原来是它们在作怪
  9. 「摸鱼」神器来了,Python 实现人脸监测制作神器
  10. 告别CNN?一张图等于16x16个字,计算机视觉也用上Transformer了