{"id":24583583,"url":"https://github.com/programming-with-love/coffee-spring","last_synced_at":"2025-04-28T10:38:49.028Z","repository":{"id":53539417,"uuid":"183462598","full_name":"Programming-With-Love/coffee-spring","owner":"Programming-With-Love","description":":coffee: spring 5.x / spring boot 2.x的restful启动器，节省一杯咖啡的时间，更多的约定，更快的开发","archived":false,"fork":false,"pushed_at":"2021-03-25T15:42:38.000Z","size":816,"stargazers_count":37,"open_issues_count":2,"forks_count":5,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-30T08:41:33.099Z","etag":null,"topics":["restful","spring","spring-boot","spring-boot-starter"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Programming-With-Love.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-04-25T15:33:58.000Z","updated_at":"2023-10-09T09:15:15.000Z","dependencies_parsed_at":"2022-09-11T07:10:12.956Z","dependency_job_id":null,"html_url":"https://github.com/Programming-With-Love/coffee-spring","commit_stats":null,"previous_names":["zidoshare/coffee-spring-boot-builder"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Programming-With-Love%2Fcoffee-spring","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Programming-With-Love%2Fcoffee-spring/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Programming-With-Love%2Fcoffee-spring/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Programming-With-Love%2Fcoffee-spring/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Programming-With-Love","download_url":"https://codeload.github.com/Programming-With-Love/coffee-spring/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251296595,"owners_count":21566637,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["restful","spring","spring-boot","spring-boot-starter"],"created_at":"2025-01-24T04:47:32.684Z","updated_at":"2025-04-28T10:38:49.006Z","avatar_url":"https://github.com/Programming-With-Love.png","language":"Java","readme":"\u003cp align=\"center\"\u003e\n    \u003cimg alt=\"socialify\" src=\"https://socialify.git.ci/zidoshare/coffee-spring/image?description=1\u0026descriptionEditable=spring%205.x%20%2F%20spring%20boot%202.x%E7%9A%84restful%E5%90%AF%E5%8A%A8%E5%99%A8%EF%BC%8C%E8%8A%82%E7%9C%81%E4%B8%80%E6%9D%AF%E5%92%96%E5%95%A1%E7%9A%84%E6%97%B6%E9%97%B4%EF%BC%8C%E6%9B%B4%E5%A4%9A%E7%9A%84%E7%BA%A6%E5%AE%9A%EF%BC%8C%E6%9B%B4%E5%BF%AB%E7%9A%84%E5%BC%80%E5%8F%91\u0026font=Inter\u0026forks=1\u0026language=1\u0026owner=1\u0026pattern=Plus\u0026pulls=1\u0026stargazers=1\u0026theme=Light\"\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"Travis Build Status\" src=\"https://travis-ci.org/zidoshare/coffee-spring.svg?branch=master\"\u003e\n  \u003cimg alt=\"GitHub Build Status\" src=\"https://github.com/zidoshare/coffee-spring/workflows/Java%20CI%20with%20Maven/badge.svg\"\u003e\n  \u003ca href=\"https://github.com/zidoshare/coffee-spring/blob/master/LICENSE\"\u003e\u003cimg alt=\"MIT LICENCE\" src=\"https://img.shields.io/cocoapods/l/Kingfisher.svg?style=flat\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"LANGUAGE JAVA\" src=\"https://img.shields.io/badge/language-java-orange.svg\"\u003e\n  \u003cimg alt=\"JDK 1.8+\" src=\"https://img.shields.io/badge/JDK-1.8+-green.svg\"\u003e\n  \u003cimg alt=\"Spring Boot\" src=\"https://img.shields.io/badge/Spring%20Boot-2.3.9.RELEASE-blue.svg\"\u003e\n\u003c/p\u003e\n\n\u003e spring 5.x / spring boot 2.x的restful启动器，节省一杯咖啡的时间，更多的约定，更快的开发\n\n它承袭Spring/Spring Boot的开发理念，在原Spring Boot基础上做更进一步的约定但又尽可能的不为开发者带来配置负担。\n\n旨在提升小型团队的开发输出能力，**不依赖模板代码**，**不依赖代码生成**的脚手架。\n\n## 优势\n\n* 提供*restful web*应用默认规则\n\n* 开箱即用\n\n* 从框架层培养开发习惯，通过各种注解式工具在spring boot基础上使代码更加高内聚，低耦合\n\n* 继承spring boot理念：基于自动配置，完全没有代码生成，也不需要XML配置。\n\n* 自动配置的认证框架，包含账号密码（手机号验证码）登录/鉴权（全注解鉴权）。\n\n* 全局异常自动捕捉并返回约定响应结果。\n\n* 全局请求日志,帮助快速定位问题所在。\n\n* 定义更多的校验注解，例如：`@Phone`\n\n* 其他常用工具集成\n\n## 环境要求\n\n* java 8+\n* maven 3.3+\n* gradle 5.x / 6.x\n\n## 使用\n\n为使框架尽可能轻量化，项目采用分包开发，尽可能进行单一功能的增强，鉴于开发者可能对某些模块的定制并不满意，你完全可以选择不引入相应功能。\n\n为了保持Spring Boot使用习惯，本项目提供site.zido:coffee-spring-boot-parent包，放置于pom文件中的parent标签下，\n它继承自Spring Boot Starter Parent主要用于维护版本及能够沿用它的相关插件设置，在其基础上增加coffee项目的版本依赖管理。\n```xml\n\u003cparent\u003e\n    \u003cgroupId\u003esite.zido\u003c/groupId\u003e\n    \u003cartifactId\u003ecoffee-spring-boot-parent\u003c/artifactId\u003e\n    \u003cversion\u003e{version}\u003c/version\u003e\n\u003c/parent\u003e\n```\n当然，你也可以使用dependencyManager方式引入site.zido:coffee-dependencies包，用于管理依赖版本。\n\n```xml\n\u003cdependencyManagement\u003e\n    \u003cdependencies\u003e\n        \u003cdependency\u003e\n            \u003c!-- Import dependency management from Spring Boot --\u003e\n            \u003cgroupId\u003esite.zido\u003c/groupId\u003e\n            \u003cartifactId\u003ecoffee-dependencies\u003c/artifactId\u003e\n            \u003cversion\u003e${version}\u003c/version\u003e\n            \u003ctype\u003epom\u003c/type\u003e\n            \u003cscope\u003eimport\u003c/scope\u003e\n        \u003c/dependency\u003e\n    \u003c/dependencies\u003e\n\u003c/dependencyManagement\u003e\n```\n\n当在需要引入项目时，可能会遇到两种情况：\n\n#### 你完全认同本框架对于Spring的相应扩展能力（推荐）\n\n直接引入`coffee-spring-boot-starter`模块。本模块完全采用探测型功能增强，\n也即是说，它会在你引入相应模块时才为之生效，否则不产生任何副作用。示例如下：\n```xml\n\u003cproject\u003e\n    \u003cparent\u003e\n        \u003cgroupId\u003esite.zido\u003c/groupId\u003e\n        \u003cartifactId\u003ecoffee-spring-boot-parent\u003c/artifactId\u003e\n        \u003cversion\u003e{version}\u003c/version\u003e\n    \u003c/parent\u003e\n    \u003cdependencies\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003esite.zido\u003c/groupId\u003e\n            \u003cartifactId\u003ecoffee-spring-boot-starter\u003c/artifactId\u003e\n            \u003cversion\u003e{version}\u003c/version\u003e\n        \u003c/dependency\u003e\n        \u003c!--增强Spring Mvc,添加全局统一返回，异常处理等逻辑--\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n            \u003cartifactId\u003espring-boot-starter-web\u003c/artifactId\u003e\n        \u003c/dependency\u003e\n        \u003c!--增强Spring Security，增加Restful Api支持，增加jwt支持，添加手机号登陆等功能支持--\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n            \u003cartifactId\u003espring-boot-starter-security\u003c/artifactId\u003e\n        \u003c/dependency\u003e\n    \u003c/dependencies\u003e\n\u003c/project\u003e\n```\n#### 你认同部分扩展能力 （推荐）\n可以分别使用各个模块为你提供相关的功能\n\n| 模块名               | 描述                                                                                                  |\n| -------------------- | ----------------------------------------------------------------------------------------------------- |\n| coffee-starter-web        | 基本通用包，包含异常封装，响应体封装，json自动配置，请求日志自动配置等，其他模块均会自动引入该模块    |\n| coffee-starter-rest-security | rest api认证框架，基于spring security封装，在spring security基础上提供rest api支持，默认使用jwt token |\n| coffee-starter-extra         | 提供诸多常用注解式开发工具，包含注解式分布式锁/限流器/防重放等功能                                    |\n\n将`spring-boot-starter-xxx`替换为`coffee-starter-xxx`即可，**不需要再添加对应spring boot模块**，这些模块本身附带有对应依赖。\n```xml\n\u003cproject\u003e\n    \u003cparent\u003e\n        \u003cgroupId\u003esite.zido\u003c/groupId\u003e\n        \u003cartifactId\u003ecoffee-spring-boot-parent\u003c/artifactId\u003e\n        \u003cversion\u003e{version}\u003c/version\u003e\n    \u003c/parent\u003e\n    \u003cdependencies\u003e\n        \u003c!--增强Spring Mvc,添加全局统一返回，异常处理等逻辑--\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003esite.zido\u003c/groupId\u003e\n            \u003cartifactId\u003ecoffee-starter-web\u003c/artifactId\u003e\n            \u003cversion\u003e{version}\u003c/version\u003e\n        \u003c/dependency\u003e\n        \u003c!--增强Spring Security，增加Restful Api支持，增加jwt支持，添加手机号登陆等功能支持--\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003esite.zido\u003c/groupId\u003e\n            \u003cartifactId\u003ecoffee-starter-rest-security\u003c/artifactId\u003e\n            \u003cversion\u003e{version}\u003c/version\u003e\n        \u003c/dependency\u003e\n        \u003c!--额外开发利器--\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003esite.zido\u003c/groupId\u003e\n            \u003cartifactId\u003ecoffee-starter-extra\u003c/artifactId\u003e\n            \u003cversion\u003e{version}\u003c/version\u003e\n        \u003c/dependency\u003e\n    \u003c/dependencies\u003e\n\u003c/project\u003e\n```\n\n## WebMvc模块\n\n为spring web mvc 提供了一系列定制，并为其他模块提供自适应的相关配置。\n\n主要包括：\n\n### 全局统一返回对象\n\n不需要为返回结果添加统一工具类，形如`Result.success(data)`形式。\n\n不需要为统一异常封装而发愁，自行封装还可能漏掉某些异常，导致前端一脸懵逼。\n\n全局统一封装会自动开启，可以通过`spring.coffee.web.global-result=false`来关闭。\n\n从此你的controller方法只需要直接返回业务数据，不需要再进行任何封装，并且可以统一直接修改响应类型。\n\n全局统一返回对象默认为`site.zido.coffee.mvc.rest.Result`。\n\n在开启全局统一返回后，框架会做出如下自适应：\n\n* 封装RestController注解和ResponseBody的返回结果，自动包装为统一返回对象\n* 封装异常响应结果，注意对于字段校验异常，只返回遇到的第一个异常封装字段\n* 如果你的返回类型已经是封装对象，不做任何封装\n* 有时可能会需要返回原对象，可以使用@OriginalResponse注解，如果作用于类上，则所有返回加过不封装。\n\n如果需要返回错误，那么你可以根据异常进行分类，框架提供`CommonBusinessException`代表业务异常，继承它，能得到更加完善的结果并自动加入业务日志中。\n\n```java\npublic class UnknownException extends CommonBusinessException {\n    public UnknownException() {\n        super(400, \"发生意料之外的错误\");\n    }\n}\n```\n\n如果你对返回结果有定制需求，可以实现`HttpResponseBodyFactory`,如下：\n\n```java\npublic class DefaultHttpResponseBodyFactory implements HttpResponseBodyFactory {\n    @Override\n    public boolean isExceptedClass(Class\u003c?\u003e clazz) {\n        return Result.class.isAssignableFrom(clazz);\n    }\n\n    @Override\n    public Object success(Object data) {\n        return Result.success(data);\n    }\n\n    @Override\n    public Object error(int code, String message, Object data) {\n        return Result.error(code, message, data);\n    }\n}\n```\n\n并作为Bean返回，框架会自动迁移到对应的factory中。\n\n### 全局统一异常处理\n\n全局统一异常处理会自动开启，可以通过`spring.coffee.web.global-result=false`来关闭。\n\n全部统一异常处理会使用`HttpResponseBodyFactory`包装异常返回，它跟随全局统一返回处理一起开启。\n\n对于校验类型的异常，默认只显示第一个\n\n如果使用spring-security包，则会自适应为每个异常日志附加当前用户名，方便日志区分是哪个用户在何时发生的异常\n\n## 全局日志\n\n会自当开启全局日志，这通过`AbstractRequestLoggingFilter`实现，会自动打印每个请求日志。\n包含客户端地址，用户名等信息，方便开发者跟踪请求信息。\n\n默认关闭，可以使用`spring.coffee.web.request-log=true`来开启。也可以使用注解`@EnableRequestLogger`\n\n### 其他杂项\n\n* 根据环境切换json序列化标准，如果profiles.active包含prod，也就代表生产环境，此时会将null属性得序列化过滤，否则不会过滤null属性，帮助前端了解这个接口到底有多少字段。这可以通过`spring.coffee.json.auto-switch=false`来手动关闭\n\n## 认证模块 (coffee-auth)\n\n可实现几乎0配置的自动认证模块，基于spring security的自动化配置，\n并添加了spring security曾经不（完全）具有的rest能力，使用jwt作为token规范，\n可自行扩展使用其他token规则\n\n自带登录模块：\n\n* 用户名密码登录(spring security自带，并加入rest相关自动配置)\n* 手机号验证码登录(需自行配置)\n\n### 使用\n\ncoffee为你提供最简单的开箱即用的体验。当集成coffee-security之后，自动开启注解支持。\n此时你需要做的只是返回一个`UserDetailsService`，这与[spring security官方文档](https://spring.io/projects/spring-security)完全相同\n\n如果你需要集成手机号验证码登录，这是默认开启的，但是项目默认你是在开发环境，这会使得你手机号验证码并不会真正的发送，而是输出到控制台。\n为此，如需上线一个必须的Bean是`PhoneCodeService`。\n像这样\n```java\n@Bean\npublic PhoneCodeService phoneCodeService(){\n    return (phone,code) -\u003e {\n        //发送验证码\n    }\n}\n```\n框架已经默认为你处理了手机号校验，验证码生成等逻辑，你无需关心这些细节。\n\n此时验证码会默认被缓存到内存中，并在60秒后失效。如果你集成了spring-redis，框架会进一步将验证码放到redis中，以获得更好的性能体验。\n\n如果你需要自定义存储,可以实现`PhoneCodeCache`接口，并作为bean返回。框架默认会提供内存存储，如下所示：\n\n```java\npublic class MemoryPhoneCodeCache implements PhoneCodeCache {\n    private final ExpireMap\u003cString, String\u003e expireMap;\n\n    public MemoryPhoneCodeCache() {\n        this(new ExpireMap\u003c\u003e(1000));\n    }\n\n    public MemoryPhoneCodeCache(ExpireMap\u003cString, String\u003e expireMap) {\n        this.expireMap = expireMap;\n    }\n\n    @Override\n    public void put(String phone, String code) {\n        expireMap.set(phone, code, 60 * 1000);\n    }\n\n    @Override\n    public String getCode(String phone) {\n        return expireMap.get(phone);\n    }\n}\n```\n\n本质上，coffee-security模块是提供一系列工具给用户自定义，并通过自动配置，实现默认的约定，并不改变spring security的任何现有使用方式。\n如果需要自定义配置，你应该考虑需要继承RestSecurityConfigurationAdapter，\n它在Spring security的WebSecurityConfigurerAdapter基础上加入了一些restful相关配置。\n\n同时，除spring-security原配置属性外，为你的props增加了以下配置属性：\n\n|属性名|属性取值|默认值|说明|\n|------|------|----|----|\n|spring.security.secure-store-type|session、jwt、token|jwt|使用何种方式进行存储认证信息|\n|spring.security.jwt.refresh-support|true/false|false|是否支持refresh-token调用接口刷新|\n|spring.security.jwt.refresh-header|string|Refresh-Token|refresh header名，用于前后端接口交互|\n|spring.security.jwt.refresh-secret|string|随机|refresh-token加密密钥，如果不设置会采用secret所设置的密钥|\n|spring.security.jwt.auto-refresh|true/false|true|是否支持自动刷新token，这种方式会由服务端选择，在合适的时候向response写入新的token，前端予以存储|\n|spring.security.jwt.renew-in-ms|long|十分钟|自动刷新token时，重新生成的间隔毫秒数|\n|spring.security.jwt.expiration|long|一小时|token过期时间|\n|spring.security.jwt.secret|string|随机|token密钥，默认随机生成，注意，这种情况下，重启服务器会需要重新登录，所以推荐手动设置|\n|spring.security.jwt.header|string|Authorization|token header名|\n|spring.security.phone-code-enable|true/false|true|是否支持手机号验证码登录|\n|spring.security.phone-code.key-prefix|string|spring:security:coffee:|验证码被存入缓存时的key前缀|\n|spring.security.phone-code.timeout|long|60秒|过期时间，单位为秒|\n|spring.security.phone-code.process-url|string|\"/users/sms/sessions\"|登录接口url|\n|spring.security.phone-code.code-process-url|string|\"/users/sms/code\"|验证码接口url|","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogramming-with-love%2Fcoffee-spring","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprogramming-with-love%2Fcoffee-spring","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogramming-with-love%2Fcoffee-spring/lists"}