├── starter ├── starter-core │ ├── go.sum │ ├── README.md │ ├── go.mod │ ├── db.go │ ├── mongo.go │ ├── redis.go │ ├── grpc.go │ └── web.go ├── starter-web │ ├── README.md │ ├── go.mod │ ├── go.sum │ ├── starter-web_test.go │ └── starter-web.go ├── starter-grpc │ ├── README.md │ ├── go.mod │ ├── server │ │ ├── starter.go │ │ └── factory │ │ │ └── factory.go │ └── client │ │ ├── factory │ │ └── factory.go │ │ └── starter.go ├── starter-gin │ ├── README.md │ ├── go.mod │ └── starter-gin.go ├── starter-go-redis │ ├── README.md │ ├── go.mod │ ├── starter-go-redis.go │ ├── go-redis-factory │ │ └── go-redis-factory.go │ └── go.sum ├── starter-echo │ ├── README.md │ ├── go.mod │ └── starter-echo.go ├── starter-go-mongo │ ├── README.md │ ├── go.mod │ ├── starter-go-mongo.go │ └── go-mongo-factory │ │ └── go-mongo-factory.go ├── starter-gorm │ ├── README.md │ ├── go.mod │ └── mysql │ │ └── starter.go └── starter-rabbitmq │ ├── README.md │ ├── go.mod │ ├── producer │ └── producer.go │ ├── go.sum │ ├── server │ └── server.go │ └── consumer │ └── consumer.go ├── spring ├── spring-stl │ ├── README.md │ ├── go.mod │ ├── go.sum │ ├── atomic │ │ └── atomic.go │ ├── util │ │ ├── chan.go │ │ ├── md5.go │ │ ├── list.go │ │ ├── testdata │ │ │ ├── pkg │ │ │ │ ├── bar │ │ │ │ │ └── pkg.go │ │ │ │ └── foo │ │ │ │ │ └── pkg.go │ │ │ └── pkg.go │ │ ├── const.go │ │ ├── bean.go │ │ ├── time.go │ │ ├── net.go │ │ ├── panic.go │ │ ├── value.go │ │ ├── value_test.go │ │ └── sort.go │ ├── json │ │ ├── error.go │ │ └── json.go │ ├── knife │ │ ├── knife_test.go │ │ └── knife.go │ ├── contain │ │ └── contain.go │ ├── flat │ │ ├── flat_test.go │ │ └── flat.go │ ├── errors │ │ ├── errors.go │ │ └── errors_test.go │ ├── apcu │ │ ├── apcu_test.go │ │ └── apcu.go │ ├── assert │ │ └── assert_test.go │ └── cast │ │ └── cast.go ├── spring-rabbitmq │ ├── README.md │ ├── go.mod │ ├── spring-rabbitmq.go │ └── go.sum ├── spring-swag │ ├── README.md │ ├── go.mod │ ├── swagger │ │ ├── swagger.go │ │ └── swagger_test.go │ └── redoc │ │ └── redoc.go ├── spring-core │ ├── gs │ │ ├── testdata │ │ │ ├── config │ │ │ │ ├── application-test.yaml │ │ │ │ ├── application.properties │ │ │ │ └── application.yaml │ │ │ └── pkg │ │ │ │ ├── bar │ │ │ │ └── pkg.go │ │ │ │ └── foo │ │ │ │ └── pkg.go │ │ ├── bootstrap.go │ │ ├── bean │ │ │ └── bean.go │ │ ├── environ │ │ │ └── environ.go │ │ ├── banner.go │ │ └── app_test.go │ ├── conf │ │ ├── testdata │ │ │ └── config │ │ │ │ ├── application.properties │ │ │ │ └── application.yaml │ │ ├── toml │ │ │ └── toml.go │ │ ├── yaml │ │ │ └── yaml.go │ │ ├── prop │ │ │ └── prop.go │ │ ├── reader.go │ │ └── convert.go │ ├── go.mod │ ├── redis │ │ └── redis.go │ ├── tools │ │ └── gen.go │ ├── web │ │ ├── binding.go │ │ ├── swagger.go │ │ ├── filter_test.go │ │ ├── rpc-result_test.go │ │ ├── rpc.go │ │ ├── constants.go │ │ ├── rpc-result.go │ │ └── filter.go │ ├── mybatis │ │ └── mybatis.go │ ├── grpc │ │ └── grpc.go │ ├── mq │ │ ├── producer.go │ │ ├── message.go │ │ └── consumer.go │ ├── go.sum │ └── validator │ │ └── validator.go ├── spring-gin │ ├── go.mod │ └── README.md └── spring-echo │ ├── go.mod │ └── README.md ├── examples ├── spring-boot-grpc │ ├── README.md │ ├── go.mod │ ├── helloworld │ │ ├── helloworld.proto │ │ └── helloworld_grpc.pb.go │ ├── greeter_server │ │ └── main.go │ └── greeter_client │ │ └── main.go ├── spring-boot-junit │ ├── README.md │ ├── go.mod │ ├── test │ │ ├── main_test.go │ │ └── service-hello_test.go │ └── service │ │ ├── service-hello_test.go │ │ └── service-hello.go ├── spring-boot-demo │ ├── README.md │ ├── config │ │ ├── application.ini │ │ ├── application.toml │ │ ├── application.properties │ │ ├── config-map.yaml │ │ ├── application-test.yaml │ │ └── banner.txt │ ├── extension │ │ └── extension.go │ ├── go.mod │ ├── filter │ │ ├── single_filter.go │ │ ├── number_filter.go │ │ └── string_filter.go │ ├── mock │ │ └── mock.go │ ├── app │ │ └── my_runner.go │ ├── main.go │ └── server │ │ └── server.go ├── spring-boot-message │ ├── consumer │ │ ├── config │ │ │ └── application.properties │ │ └── main.go │ ├── producer │ │ ├── config │ │ │ └── application.properties │ │ └── main.go │ └── go.mod ├── spring-web-petstore │ └── go.mod ├── spring-web-filter │ ├── go.mod │ └── abort │ │ ├── abort.go │ │ └── abort_test.go ├── spring-boot-web │ └── go.mod └── spring-web-testcases │ ├── go.mod │ ├── spring-web-filter_test.go │ └── spring-web-rpc_test.go ├── logo@h.png ├── logo@s.png ├── sponsor.png ├── CONTRIBUTORS ├── documents └── 项目贡献指南.docx ├── .travis.yml ├── .gitignore ├── .github ├── FUNDING.yml └── workflows │ └── main.yml ├── run.sh ├── CONTRIBUTING.md └── project.xml /starter/starter-core/go.sum: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spring/spring-stl/README.md: -------------------------------------------------------------------------------- 1 | # spring-stl -------------------------------------------------------------------------------- /starter/starter-web/README.md: -------------------------------------------------------------------------------- 1 | # starter-web -------------------------------------------------------------------------------- /examples/spring-boot-grpc/README.md: -------------------------------------------------------------------------------- 1 | # examples -------------------------------------------------------------------------------- /examples/spring-boot-junit/README.md: -------------------------------------------------------------------------------- 1 | # examples -------------------------------------------------------------------------------- /starter/starter-grpc/README.md: -------------------------------------------------------------------------------- 1 | # starter-grpc -------------------------------------------------------------------------------- /examples/spring-boot-demo/README.md: -------------------------------------------------------------------------------- 1 | # spring-boot-demo -------------------------------------------------------------------------------- /spring/spring-rabbitmq/README.md: -------------------------------------------------------------------------------- 1 | # spring-rabbitmq -------------------------------------------------------------------------------- /starter/starter-gin/README.md: -------------------------------------------------------------------------------- 1 | # go-spring-starter-gin -------------------------------------------------------------------------------- /starter/starter-go-redis/README.md: -------------------------------------------------------------------------------- 1 | # starter-go-redis -------------------------------------------------------------------------------- /starter/starter-echo/README.md: -------------------------------------------------------------------------------- 1 | # go-spring-starter-echo -------------------------------------------------------------------------------- /starter/starter-core/README.md: -------------------------------------------------------------------------------- 1 | # starter-core 2 | 「仅发布」 3 | -------------------------------------------------------------------------------- /starter/starter-go-mongo/README.md: -------------------------------------------------------------------------------- 1 | # go-spring-starter-go-mongo -------------------------------------------------------------------------------- /examples/spring-boot-demo/config/application.ini: -------------------------------------------------------------------------------- 1 | [db] 2 | url="error" -------------------------------------------------------------------------------- /spring/spring-swag/README.md: -------------------------------------------------------------------------------- 1 | # spring-swag 2 | 「仅发布」Swagger 支持模块 3 | -------------------------------------------------------------------------------- /starter/starter-gorm/README.md: -------------------------------------------------------------------------------- 1 | # starter-gorm 2 | 「仅发布」gorm 启动器 3 | -------------------------------------------------------------------------------- /logo@h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/go-spring/HEAD/logo@h.png -------------------------------------------------------------------------------- /logo@s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/go-spring/HEAD/logo@s.png -------------------------------------------------------------------------------- /sponsor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/go-spring/HEAD/sponsor.png -------------------------------------------------------------------------------- /starter/starter-rabbitmq/README.md: -------------------------------------------------------------------------------- 1 | # starter-rabbitmq 2 | [仅发布] RabbitMQ 启动器 3 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | 以下是社区优秀贡献者名单,排名不分先后: 2 | @CoderPoet、@limpo1989 3 | 4 | 特别鸣谢: 5 | @shenqidebaozi -------------------------------------------------------------------------------- /documents/项目贡献指南.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/go-spring/HEAD/documents/项目贡献指南.docx -------------------------------------------------------------------------------- /spring/spring-core/gs/testdata/config/application-test.yaml: -------------------------------------------------------------------------------- 1 | spring.application.name: test.yaml -------------------------------------------------------------------------------- /starter/starter-core/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/starter-core 2 | 3 | go 1.12 4 | -------------------------------------------------------------------------------- /spring/spring-rabbitmq/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/spring-rabbitmq 2 | 3 | go 1.12 4 | -------------------------------------------------------------------------------- /examples/spring-boot-demo/config/application.toml: -------------------------------------------------------------------------------- 1 | [db] 2 | url = "root:root@/information_schema?charset=utf8&parseTime=True&loc=Local" -------------------------------------------------------------------------------- /spring/spring-stl/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/spring-stl 2 | 3 | go 1.14 4 | 5 | require github.com/spf13/cast v1.3.1 6 | -------------------------------------------------------------------------------- /examples/spring-boot-message/consumer/config/application.properties: -------------------------------------------------------------------------------- 1 | amqp.server.url=amqp://guest:guest@localhost:5672/ 2 | amqp.queue.topics=topic-stream-idle -------------------------------------------------------------------------------- /examples/spring-boot-message/producer/config/application.properties: -------------------------------------------------------------------------------- 1 | amqp.server.url=amqp://guest:guest@localhost:5672/ 2 | amqp.queue.topics=topic-stream-idle -------------------------------------------------------------------------------- /examples/spring-boot-demo/config/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=test.properties 2 | spring.profile=test 3 | spring.access=all 4 | 5 | default-value-ref=app 6 | default-value=${default-value-ref} -------------------------------------------------------------------------------- /examples/spring-boot-junit/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/examples/spring-boot-junit 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/go-spring/spring-boot v1.0.5 7 | github.com/magiconair/properties v1.8.1 8 | ) 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.12.x 5 | 6 | before_install: 7 | - go get -t -v ./... 8 | 9 | script: 10 | - ./run.sh test 11 | 12 | after_success: 13 | - bash <(curl -s https://codecov.io/bash) 14 | -------------------------------------------------------------------------------- /spring/spring-core/conf/testdata/config/application.properties: -------------------------------------------------------------------------------- 1 | properties.list[0]=1 2 | properties.list[1]=2 3 | properties.obj.list[0].name=tom 4 | properties.obj.list[0].age=4 5 | properties.obj.list[1].name=jerry 6 | properties.obj.list[1].age=2 -------------------------------------------------------------------------------- /examples/spring-boot-demo/extension/extension.go: -------------------------------------------------------------------------------- 1 | package extension 2 | 3 | import ( 4 | "github.com/go-spring/spring-boot" 5 | ) 6 | 7 | func init() { 8 | SpringBoot.RegisterFileConfigReader(".ini", SpringBoot.ViperReadBuffer("ini")) 9 | } 10 | -------------------------------------------------------------------------------- /examples/spring-boot-demo/config/config-map.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: config-map 5 | data: 6 | application.properties: |- 7 | message=msg from config-map:application.properties 8 | application-test.yaml: |- 9 | message: msg from config-map:application-test.yaml -------------------------------------------------------------------------------- /examples/spring-boot-demo/config/application-test.yaml: -------------------------------------------------------------------------------- 1 | spring.application.name: test.yaml 2 | 3 | default-value-ref: app-test 4 | 5 | # 设置 runner 收集顺序 6 | command-line-runner: 7 | collection: "[*app.MyRunner]" 8 | 9 | # 设置 starter 收集顺序 10 | application-event: 11 | collection: "[*,web-server-starter]" -------------------------------------------------------------------------------- /spring/spring-core/gs/testdata/config/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=test 2 | 3 | # 请使用 yaml 文件定义 4 | #properties.list[0]=1 5 | #properties.list[1]=2 6 | 7 | # 请使用 yaml 文件定义 8 | #properties.obj.list[0].name=tom 9 | #properties.obj.list[0].age=4 10 | #properties.obj.list[1].name=jerry 11 | #properties.obj.list[1].age=2 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | **/*.exe 3 | **/*.exe~ 4 | **/*.dll 5 | **/*.so 6 | **/*.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | **/*.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | **/*.out 13 | 14 | **/.DS_Store 15 | 16 | **/.idea/ 17 | **/vendor/ 18 | 19 | **/covprofile 20 | **/coverage.html -------------------------------------------------------------------------------- /examples/spring-boot-message/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/examples/spring-boot-message 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/go-spring/spring-boot v1.0.5 7 | github.com/go-spring/spring-logger v1.0.5 8 | github.com/go-spring/spring-message v1.0.5 9 | github.com/go-spring/spring-utils v1.0.5 10 | github.com/go-spring/starter-rabbitmq v1.0.5 11 | ) 12 | -------------------------------------------------------------------------------- /examples/spring-web-petstore/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/examples/spring-web-testcases 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/go-openapi/spec v0.19.7 7 | github.com/go-spring/spring-echo v1.0.6-0.20201107052756-a81d9ef9038c 8 | github.com/go-spring/spring-utils v1.0.5 9 | github.com/go-spring/spring-web v1.0.6-0.20201109120017-baa11539c3ba 10 | ) 11 | -------------------------------------------------------------------------------- /spring/spring-core/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/spring-core 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/go-spring/spring-stl v0.0.0-20210724153121-8378c2594815 7 | github.com/magiconair/properties v1.8.1 8 | github.com/pelletier/go-toml v1.2.0 9 | gopkg.in/yaml.v2 v2.2.4 10 | ) 11 | 12 | //replace ( 13 | // github.com/go-spring/spring-stl => ../spring-stl 14 | //) 15 | -------------------------------------------------------------------------------- /starter/starter-go-mongo/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/starter-go-mongo 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10 7 | github.com/go-spring/starter-mongo v1.0.5 8 | go.mongodb.org/mongo-driver v1.4.0 9 | ) 10 | 11 | //replace ( 12 | // github.com/go-spring/spring-core => ../../spring/spring-core 13 | //) 14 | -------------------------------------------------------------------------------- /starter/starter-web/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/starter-web 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10 7 | github.com/go-spring/spring-stl v0.0.0-20210724153121-8378c2594815 8 | ) 9 | 10 | //replace ( 11 | // github.com/go-spring/spring-core => ../../spring/spring-core 12 | // github.com/go-spring/spring-stl => ../../spring/spring-stl 13 | //) 14 | -------------------------------------------------------------------------------- /spring/spring-gin/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/spring-gin 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.6.3 7 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10 8 | github.com/go-spring/spring-stl v0.0.0-20210724153121-8378c2594815 9 | ) 10 | 11 | //replace ( 12 | // github.com/go-spring/spring-core => ../spring-core 13 | // github.com/go-spring/spring-stl => ../spring-stl 14 | //) -------------------------------------------------------------------------------- /examples/spring-web-filter/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/examples/spring-boot-filter 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/go-spring/spring-echo v1.0.6-0.20201107052756-a81d9ef9038c 7 | github.com/go-spring/spring-gin v1.0.6-0.20201108111449-37d99d74f73d 8 | github.com/go-spring/spring-utils v1.0.5 9 | github.com/go-spring/spring-web v1.0.6-0.20201109120017-baa11539c3ba 10 | github.com/magiconair/properties v1.8.1 11 | ) 12 | -------------------------------------------------------------------------------- /starter/starter-gorm/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/starter-gorm 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10 7 | github.com/go-spring/starter-core v0.0.0-20210719133634-d661de98b7a9 8 | github.com/jinzhu/gorm v1.9.15 9 | ) 10 | 11 | //replace ( 12 | // github.com/go-spring/spring-core => ../../spring/spring-core 13 | // github.com/go-spring/starter-core => ../starter-core 14 | //) 15 | -------------------------------------------------------------------------------- /spring/spring-stl/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 3 | github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= 4 | github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 5 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 6 | -------------------------------------------------------------------------------- /starter/starter-rabbitmq/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/starter-rabbitmq 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10 7 | github.com/go-spring/spring-stl v0.0.0-20210724153121-8378c2594815 8 | github.com/streadway/amqp v1.0.0 9 | ) 10 | 11 | //replace ( 12 | // github.com/go-spring/spring-core => ../../spring/spring-core 13 | // github.com/go-spring/spring-stl => ../../spring/spring-stl 14 | //) 15 | -------------------------------------------------------------------------------- /starter/starter-go-redis/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/starter-go-redis 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/go-redis/redis v6.15.9+incompatible 7 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10 8 | github.com/go-spring/starter-core v0.0.0-20210719133634-d661de98b7a9 9 | ) 10 | 11 | //replace ( 12 | // github.com/go-spring/spring-core => ../../spring/spring-core 13 | // github.com/go-spring/starter-core => ../starter-core 14 | //) 15 | -------------------------------------------------------------------------------- /spring/spring-swag/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/spring-swag 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/go-openapi/spec v0.20.2 7 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10 8 | github.com/go-spring/spring-stl v0.0.0-20210724153121-8378c2594815 9 | github.com/swaggo/http-swagger v1.0.0 10 | ) 11 | 12 | //replace ( 13 | // github.com/go-spring/spring-core => ../spring-core 14 | // github.com/go-spring/spring-stl => ../spring-stl 15 | //) 16 | -------------------------------------------------------------------------------- /examples/spring-boot-web/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/examples/spring-boot-web 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/go-spring/spring-boot v1.0.6-0.20201107041159-ef7b31e3a8fa 7 | github.com/go-spring/spring-logger v1.0.6-0.20201031071008-31db8609b202 8 | github.com/go-spring/spring-web v1.0.6-0.20201109120017-baa11539c3ba 9 | github.com/go-spring/starter-echo v1.0.6-0.20201107053801-bac9bdfad30f 10 | github.com/go-spring/starter-gin v1.0.6-0.20201108112112-9d1b4a0067c3 // indirect 11 | ) 12 | -------------------------------------------------------------------------------- /examples/spring-boot-grpc/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/examples/spring-boot-grpc 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/go-spring/spring-boot v1.0.6-0.20201107041159-ef7b31e3a8fa 7 | github.com/go-spring/spring-error v1.0.6-0.20201031064649-3827b7286623 8 | github.com/go-spring/spring-web v1.0.6-0.20201109120017-baa11539c3ba 9 | github.com/go-spring/starter-gin v1.0.6-0.20201108112112-9d1b4a0067c3 10 | github.com/go-spring/starter-grpc v1.0.5 11 | github.com/golang/protobuf v1.3.3 12 | google.golang.org/grpc v1.31.0 13 | ) 14 | -------------------------------------------------------------------------------- /spring/spring-echo/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/spring-echo 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10 7 | github.com/labstack/echo v3.3.10+incompatible 8 | github.com/labstack/gommon v0.3.0 // indirect 9 | golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e // indirect 10 | github.com/go-spring/spring-stl v0.0.0-20210724153121-8378c2594815 11 | ) 12 | 13 | //replace ( 14 | // github.com/go-spring/spring-core => ../spring-core 15 | // github.com/go-spring/spring-stl => ../spring-stl 16 | //) 17 | -------------------------------------------------------------------------------- /starter/starter-grpc/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/starter-grpc 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10 7 | github.com/go-spring/spring-stl v0.0.0-20210724153121-8378c2594815 8 | github.com/go-spring/starter-core v0.0.0-20210719133634-d661de98b7a9 9 | google.golang.org/grpc v1.31.0 10 | ) 11 | 12 | //replace ( 13 | // github.com/go-spring/spring-core => ../../spring/spring-core 14 | // github.com/go-spring/spring-stl => ../../spring/spring-stl 15 | // github.com/go-spring/starter-core => ../starter-core 16 | //) 17 | -------------------------------------------------------------------------------- /starter/starter-gin/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/starter-gin 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10 7 | github.com/go-spring/spring-gin v1.0.6-0.20210725113450-5d9871733c9e 8 | github.com/go-spring/starter-core v0.0.0-20210719133634-d661de98b7a9 9 | github.com/go-spring/starter-web v1.0.6-0.20210725120433-93d719663caf 10 | ) 11 | 12 | //replace ( 13 | // github.com/go-spring/spring-core => ../../spring/spring-core 14 | // github.com/go-spring/spring-gin => ../../spring/spring-gin 15 | // github.com/go-spring/starter-core => ../starter-core 16 | // github.com/go-spring/starter-web => ../starter-web 17 | //) 18 | -------------------------------------------------------------------------------- /starter/starter-echo/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/starter-echo 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/go-spring/spring-echo v1.0.6-0.20210725113450-fbe41d0e09d0 7 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10 8 | github.com/go-spring/starter-core v0.0.0-20210719133634-d661de98b7a9 9 | github.com/go-spring/starter-web v1.0.6-0.20210725120433-93d719663caf 10 | ) 11 | 12 | //replace ( 13 | // github.com/go-spring/spring-core => ../../spring/spring-core 14 | // github.com/go-spring/spring-echo => ../../spring/spring-echo 15 | // github.com/go-spring/starter-core => ../starter-core 16 | // github.com/go-spring/starter-web => ../starter-web 17 | //) 18 | -------------------------------------------------------------------------------- /spring/spring-core/gs/bootstrap.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package gs 18 | -------------------------------------------------------------------------------- /spring/spring-core/redis/redis.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package redis 18 | -------------------------------------------------------------------------------- /spring/spring-core/tools/gen.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package tools 18 | -------------------------------------------------------------------------------- /spring/spring-core/web/binding.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package web 18 | -------------------------------------------------------------------------------- /spring/spring-core/mybatis/mybatis.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mybatis 18 | -------------------------------------------------------------------------------- /examples/spring-web-testcases/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/examples/testcases 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect 7 | github.com/gin-gonic/gin v1.6.3 8 | github.com/go-openapi/spec v0.19.7 9 | github.com/go-spring/spring-echo v1.0.6-0.20201107052756-a81d9ef9038c 10 | github.com/go-spring/spring-gin v1.0.6-0.20201108111449-37d99d74f73d 11 | github.com/go-spring/spring-logger v1.0.6-0.20201031071008-31db8609b202 12 | github.com/go-spring/spring-utils v1.0.5 13 | github.com/go-spring/spring-web v1.0.6-0.20201109120017-baa11539c3ba 14 | github.com/labstack/echo v3.3.10+incompatible 15 | github.com/magiconair/properties v1.8.1 16 | github.com/stretchr/testify v1.4.0 17 | ) 18 | -------------------------------------------------------------------------------- /spring/spring-rabbitmq/spring-rabbitmq.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package SpringRabbitMQ 18 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: https://raw.githubusercontent.com/go-spring/go-spring/master/sponsor.png 13 | -------------------------------------------------------------------------------- /spring/spring-stl/atomic/atomic.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Package atomic 封装基础数据类型的原子操作。 18 | package atomic 19 | -------------------------------------------------------------------------------- /starter/starter-core/db.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package StarterCore 18 | 19 | type DBConfig struct { 20 | Url string `value:"${db.url}"` 21 | } 22 | -------------------------------------------------------------------------------- /starter/starter-core/mongo.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package StarterCore 18 | 19 | type MongoConfig struct { 20 | Url string `value:"${mongo.url:=mongodb://localhost}"` 21 | } 22 | -------------------------------------------------------------------------------- /spring/spring-core/grpc/grpc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package grpc 18 | 19 | type Server struct { 20 | Register interface{} // 服务注册函数 21 | Service interface{} // 服务提供者 22 | } 23 | -------------------------------------------------------------------------------- /spring/spring-stl/util/chan.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | // SafeCloseChan 安全地关闭一个通道。 20 | func SafeCloseChan(ch chan struct{}) { 21 | select { 22 | case <-ch: 23 | // chan 已关闭,无需再次关闭。 24 | default: 25 | close(ch) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /spring/spring-core/mq/producer.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mq 18 | 19 | import "context" 20 | 21 | // Producer 消息生产者。 22 | type Producer interface { 23 | 24 | // SendMessage 传入的消息类型不同用途也不同,需要分别判断。 25 | SendMessage(ctx context.Context, msg Message) error 26 | } 27 | -------------------------------------------------------------------------------- /spring/spring-stl/util/md5.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "crypto/md5" 21 | "encoding/hex" 22 | ) 23 | 24 | // MD5 获取 MD5 计算后的字符串。 25 | func MD5(str string) string { 26 | hash := md5.Sum([]byte(str)) 27 | return hex.EncodeToString(hash[:]) 28 | } 29 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: CI 4 | 5 | # Controls when the action will run. Triggers the workflow on push or pull request 6 | # events but only for the master branch 7 | on: 8 | push: 9 | branches: [ master ] 10 | pull_request: 11 | branches: [ master ] 12 | 13 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 14 | jobs: 15 | # This workflow contains a single job called "build" 16 | build: 17 | # The type of runner that the job will run on 18 | runs-on: ubuntu-latest 19 | 20 | # Steps represent a sequence of tasks that will be executed as part of the job 21 | steps: 22 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 23 | - uses: actions/checkout@v2 24 | 25 | # Runs a single command using the runners shell 26 | - name: run test 27 | run: sh run.sh test -------------------------------------------------------------------------------- /spring/spring-stl/util/list.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "container/list" 21 | ) 22 | 23 | // NewList 使用输入的元素创建列表。 24 | func NewList(v ...interface{}) *list.List { 25 | l := list.New() 26 | for _, val := range v { 27 | l.PushBack(val) 28 | } 29 | return l 30 | } 31 | -------------------------------------------------------------------------------- /starter/starter-grpc/server/starter.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package StarterGrpcServer 18 | 19 | import ( 20 | "github.com/go-spring/spring-core/gs" 21 | "github.com/go-spring/starter-grpc/server/factory" 22 | ) 23 | 24 | func init() { 25 | gs.Provide(GrpcServerFactory.NewStarter).Name("grpc-server-starter") 26 | } 27 | -------------------------------------------------------------------------------- /examples/spring-boot-junit/test/main_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package test 18 | 19 | import ( 20 | "testing" 21 | 22 | _ "github.com/go-spring/examples/spring-boot-junit/service" 23 | "github.com/go-spring/spring-boot" 24 | ) 25 | 26 | func TestEntry(t *testing.T) { 27 | SpringBoot.RunTestApplication(t, 0) 28 | } 29 | -------------------------------------------------------------------------------- /spring/spring-stl/util/testdata/pkg/bar/pkg.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package pkg 18 | 19 | import ( 20 | "fmt" 21 | ) 22 | 23 | // SamePkg Golang 允许不同的路径下存在同名的包。 24 | type SamePkg struct{} 25 | 26 | func (p *SamePkg) Package() { 27 | fmt.Println("github.com/go-spring/spring-stl/util/testdata/pkg/bar/pkg.SamePkg") 28 | } 29 | -------------------------------------------------------------------------------- /spring/spring-stl/util/testdata/pkg/foo/pkg.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package pkg 18 | 19 | import ( 20 | "fmt" 21 | ) 22 | 23 | // SamePkg Golang 允许不同的路径下存在同名的包。 24 | type SamePkg struct{} 25 | 26 | func (p *SamePkg) Package() { 27 | fmt.Println("github.com/go-spring/spring-stl/util/testdata/pkg/foo/pkg.SamePkg") 28 | } 29 | -------------------------------------------------------------------------------- /spring/spring-core/gs/testdata/pkg/bar/pkg.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package pkg 18 | 19 | import ( 20 | "fmt" 21 | ) 22 | 23 | // golang 允许不同的路径下存在相同的包,而且允许存在相同的包。 24 | type SamePkg struct{} 25 | 26 | func (p *SamePkg) Package() { 27 | fmt.Println("github.com/go-spring/spring-core/gs/testdata/pkg/bar/pkg.SamePkg") 28 | } 29 | -------------------------------------------------------------------------------- /starter/starter-core/redis.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package StarterCore 18 | 19 | type RedisConfig struct { 20 | Host string `value:"${redis.host:=127.0.0.1}"` 21 | Port int `value:"${redis.port:=6379}"` 22 | Password string `value:"${redis.password:=}"` 23 | Database int `value:"${redis.database:=0}"` 24 | } 25 | -------------------------------------------------------------------------------- /spring/spring-stl/util/const.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "errors" 21 | ) 22 | 23 | // UnsupportedMethod 如果某个方法禁止被调用则可以抛出此错误。 24 | var UnsupportedMethod = errors.New("unsupported method") 25 | 26 | // UnimplementedMethod 如果某个方法未实现则可以抛出此错误。 27 | var UnimplementedMethod = errors.New("unimplemented method") 28 | -------------------------------------------------------------------------------- /examples/spring-boot-junit/service/service-hello_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package service 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/magiconair/properties/assert" 23 | ) 24 | 25 | func TestHello_Say(t *testing.T) { 26 | h := &Hello{Application: "go-spring"} 27 | assert.Equal(t, h.Say("world"), "hello world from go-spring") 28 | } 29 | -------------------------------------------------------------------------------- /starter/starter-core/grpc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package StarterCore 18 | 19 | // GrpcServerConfig gRPC 服务器配置 20 | type GrpcServerConfig struct { 21 | Port int `value:"${grpc.server.port:=9090}"` 22 | } 23 | 24 | // GrpcEndpointConfig gRPC 服务端点配置 25 | type GrpcEndpointConfig struct { 26 | Address string `value:"${address:=127.0.0.1:9090}"` 27 | } 28 | -------------------------------------------------------------------------------- /spring/spring-core/conf/toml/toml.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package toml 18 | 19 | import ( 20 | "github.com/pelletier/go-toml" 21 | ) 22 | 23 | // Read 将 toml 格式的字节数组解析成 map 数据。 24 | func Read(b []byte) (map[string]interface{}, error) { 25 | tree, err := toml.LoadBytes(b) 26 | if err != nil { 27 | return nil, err 28 | } 29 | return tree.ToMap(), nil 30 | } 31 | -------------------------------------------------------------------------------- /spring/spring-stl/util/testdata/pkg.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package testdata 18 | 19 | func FnNoArgs() {} 20 | 21 | func FnWithArgs(i int) {} 22 | 23 | type Receiver struct{} 24 | 25 | func (r Receiver) FnNoArgs() {} 26 | 27 | func (r Receiver) FnWithArgs(i int) {} 28 | 29 | func (r *Receiver) PtrFnNoArgs() {} 30 | 31 | func (r *Receiver) PtrFnWithArgs(i int) {} 32 | -------------------------------------------------------------------------------- /spring/spring-core/conf/yaml/yaml.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package yaml 18 | 19 | import ( 20 | "gopkg.in/yaml.v2" 21 | ) 22 | 23 | // Read 将 yaml 格式的字节数组解析成 map 数据。 24 | func Read(b []byte) (map[string]interface{}, error) { 25 | m := make(map[string]interface{}) 26 | err := yaml.Unmarshal(b, &m) 27 | if err != nil { 28 | return nil, err 29 | } 30 | return m, nil 31 | } 32 | -------------------------------------------------------------------------------- /spring/spring-echo/README.md: -------------------------------------------------------------------------------- 1 | # spring-echo 2 | 3 | 封装 github.com/labstack/echo 实现的 Web 框架。 4 | 5 | - [创建 Web 容器](#创建-web-容器) 6 | - [NewContainer](#newcontainer) 7 | - [适配 echo 框架](#适配-echo-框架) 8 | - [Handler](#handler) 9 | - [Filter](#filter) 10 | - [EchoContext](#echocontext) 11 | - [WebContext](#webcontext) 12 | 13 | ### 创建 Web 容器 14 | 15 | #### NewContainer 16 | 17 | 创建 echo 实现的 Web 容器。 18 | 19 | func NewContainer(config SpringWeb.ContainerConfig) *Container {} 20 | 21 | ### 适配 echo 框架 22 | 23 | #### Handler 24 | 25 | 适配 echo 形式的处理函数。 26 | 27 | func Handler(fn echo.HandlerFunc) SpringWeb.Handler {} 28 | 29 | #### Filter 30 | 31 | 适配 echo 形式的中间件函数。 32 | 33 | func Filter(fn echo.MiddlewareFunc) SpringWeb.Filter {} 34 | 35 | #### EchoContext 36 | 37 | 将 SpringWeb.Context 转换为 echo.Context。 38 | 39 | func EchoContext(ctx SpringWeb.Context) echo.Context {} 40 | 41 | #### WebContext 42 | 43 | 将 echo.Context 转换为 SpringWeb.Context。 44 | 45 | func WebContext(echoCtx echo.Context) SpringWeb.Context {} -------------------------------------------------------------------------------- /spring/spring-gin/README.md: -------------------------------------------------------------------------------- 1 | # spring-gin 2 | 3 | 封装 github.com/gin-gonic/gin 实现的 Web 框架。 4 | 5 | - [创建 Web 容器](#创建-web-容器) 6 | - [NewContainer](#newcontainer) 7 | - [适配 gin 框架](#适配-gin-框架) 8 | - [Handler](#handler) 9 | - [Filter](#filter) 10 | - [GinContext](#gincontext) 11 | - [WebContext](#webcontext) 12 | 13 | ### 创建 Web 容器 14 | 15 | #### NewContainer 16 | 17 | 创建 gin 实现的 WebContainer。 18 | 19 | func NewContainer(config SpringWeb.ContainerConfig) *Container {} 20 | 21 | ### 适配 gin 框架 22 | 23 | #### Handler 24 | 25 | 适配 gin 形式的处理函数。 26 | 27 | func Handler(fn gin.HandlerFunc) SpringWeb.Handler {} 28 | 29 | #### Filter 30 | 31 | 适配 gin 形式的中间件函数。 32 | 33 | func Filter(fn gin.HandlerFunc) SpringWeb.Filter {} 34 | 35 | #### GinContext 36 | 37 | 将 SpringWeb.WebContext 转换为 *gin.Context。 38 | 39 | func GinContext(webCtx SpringWeb.WebContext) *gin.Context {} 40 | 41 | #### WebContext 42 | 43 | 将 *gin.Context 转换为 SpringWeb.WebContext。 44 | 45 | func WebContext(ginCtx *gin.Context) SpringWeb.WebContext {} -------------------------------------------------------------------------------- /spring/spring-stl/util/bean.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "github.com/go-spring/spring-stl/json" 21 | ) 22 | 23 | // CopyBean 使用 JSON 序列化的方式进行拷贝,支持匿名字段,支持类型转换。 24 | func CopyBean(src interface{}, dest interface{}) error { 25 | bytes, err := json.Marshal(src) 26 | if err != nil { 27 | return err 28 | } 29 | return json.Unmarshal(bytes, dest) 30 | } 31 | -------------------------------------------------------------------------------- /spring/spring-stl/util/time.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "time" 21 | ) 22 | 23 | // CurrentMilliSeconds 返回当前的毫秒时间 24 | func CurrentMilliSeconds() int64 { 25 | return time.Now().UnixNano() / int64(time.Millisecond) 26 | } 27 | 28 | // MilliSeconds 返回对应的毫秒时长 29 | func MilliSeconds(d time.Duration) int64 { 30 | return d.Nanoseconds() / int64(time.Millisecond) 31 | } 32 | -------------------------------------------------------------------------------- /spring/spring-core/web/swagger.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package web 18 | 19 | // Operation 与路由绑定的 API 描述文档 20 | type Operation interface { 21 | 22 | // Process 完成处理参数绑定等过程 23 | Process() error 24 | } 25 | 26 | // Swagger 与容器绑定的 API 描述文档 27 | type Swagger interface { 28 | 29 | // ReadDoc 读取标准格式的描述文档 30 | ReadDoc() string 31 | 32 | // AddPath 添加与容器绑定的路由节点 33 | AddPath(path string, method string, op Operation) 34 | } 35 | -------------------------------------------------------------------------------- /starter/starter-grpc/client/factory/factory.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package GrpcClientFactory 18 | 19 | import ( 20 | "github.com/go-spring/starter-core" 21 | "google.golang.org/grpc" 22 | ) 23 | 24 | // NewClient 根据配置创建 grpc.ClientConnInterface 对象 25 | func NewClient(config StarterCore.GrpcEndpointConfig) (grpc.ClientConnInterface, error) { 26 | return grpc.Dial(config.Address, grpc.WithInsecure()) 27 | } 28 | -------------------------------------------------------------------------------- /starter/starter-go-redis/starter-go-redis.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package StarterGoRedis 18 | 19 | import ( 20 | "github.com/go-redis/redis" 21 | "github.com/go-spring/spring-core/gs" 22 | "github.com/go-spring/spring-core/gs/cond" 23 | "github.com/go-spring/starter-go-redis/go-redis-factory" 24 | ) 25 | 26 | func init() { 27 | gs.Provide(GoRedisFactory.NewClient). 28 | Name("go-redis-client"). 29 | On(cond.OnMissingBean((*redis.Cmdable)(nil))) 30 | } 31 | -------------------------------------------------------------------------------- /examples/spring-boot-junit/service/service-hello.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package service 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/go-spring/spring-boot" 23 | ) 24 | 25 | func init() { 26 | SpringBoot.RegisterBean(new(Hello)) 27 | } 28 | 29 | type Hello struct { 30 | Application string `value:"${spring.application.name:=junit}"` 31 | } 32 | 33 | func (e *Hello) Say(name string) string { 34 | return fmt.Sprintf("hello %s from %s", name, e.Application) 35 | } 36 | -------------------------------------------------------------------------------- /starter/starter-gin/starter-gin.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package StarterGin 18 | 19 | import ( 20 | "github.com/go-spring/spring-core/gs" 21 | "github.com/go-spring/spring-core/web" 22 | "github.com/go-spring/spring-gin" 23 | "github.com/go-spring/starter-core" 24 | _ "github.com/go-spring/starter-web" 25 | ) 26 | 27 | func init() { 28 | gs.Provide(func(config StarterCore.WebServerConfig) web.Container { 29 | return SpringGin.NewContainer(web.ContainerConfig(config)) 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /starter/starter-echo/starter-echo.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package StarterEcho 18 | 19 | import ( 20 | "github.com/go-spring/spring-core/gs" 21 | "github.com/go-spring/spring-core/web" 22 | "github.com/go-spring/spring-echo" 23 | "github.com/go-spring/starter-core" 24 | _ "github.com/go-spring/starter-web" 25 | ) 26 | 27 | func init() { 28 | gs.Provide(func(config StarterCore.WebServerConfig) web.Container { 29 | return SpringEcho.NewContainer(web.ContainerConfig(config)) 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /spring/spring-swag/swagger/swagger.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package swagger 18 | 19 | import ( 20 | "github.com/go-spring/spring-core/web" 21 | "github.com/go-spring/spring-swag" 22 | ) 23 | 24 | func Doc(container web.Container) *SpringSwagger.Swagger { 25 | swagger := SpringSwagger.NewSwagger() 26 | container.Swagger(swagger) 27 | return swagger 28 | } 29 | 30 | func Path(m *web.Mapper) *SpringSwagger.Operation { 31 | op := SpringSwagger.NewOperation("") 32 | m.Operation(op) 33 | return op 34 | } 35 | -------------------------------------------------------------------------------- /starter/starter-go-mongo/starter-go-mongo.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package StarterGoMongo 18 | 19 | import ( 20 | "github.com/go-spring/spring-core/gs" 21 | "github.com/go-spring/spring-core/gs/cond" 22 | "github.com/go-spring/starter-go-mongo/go-mongo-factory" 23 | "go.mongodb.org/mongo-driver/mongo" 24 | ) 25 | 26 | func init() { 27 | gs.Provide(GoMongoFactory.NewClient). 28 | Name("go-mongo-client"). 29 | On(cond.OnMissingBean((*mongo.Client)(nil))). 30 | Destroy(GoMongoFactory.CloseClient) 31 | } 32 | -------------------------------------------------------------------------------- /spring/spring-core/conf/prop/prop.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package prop 18 | 19 | import "github.com/magiconair/properties" 20 | 21 | // Read 将 properties 格式的字节数组解析成 map 数据。 22 | func Read(b []byte) (map[string]interface{}, error) { 23 | 24 | p := properties.NewProperties() 25 | p.DisableExpansion = true 26 | 27 | err := p.Load(b, properties.UTF8) 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | ret := make(map[string]interface{}) 33 | for k, v := range p.Map() { 34 | ret[k] = v 35 | } 36 | return ret, nil 37 | } 38 | -------------------------------------------------------------------------------- /starter/starter-grpc/client/starter.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package StarterGrpcClient 18 | 19 | import ( 20 | "github.com/go-spring/spring-core/gs" 21 | "github.com/go-spring/spring-core/gs/arg" 22 | "github.com/go-spring/starter-core" 23 | "github.com/go-spring/starter-grpc/client/factory" 24 | ) 25 | 26 | func init() { 27 | gs.OnProperty("grpc.endpoint", func(endpoints map[string]StarterCore.GrpcEndpointConfig) { 28 | for endpoint, config := range endpoints { 29 | gs.Provide(GrpcClientFactory.NewClient, arg.Value(config)).Name(endpoint) 30 | } 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /examples/spring-boot-demo/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-spring/examples/spring-boot-demo 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/DATA-DOG/go-sqlmock v1.4.1 7 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect 8 | github.com/elliotchance/redismock v1.5.3 9 | github.com/go-redis/redis v6.15.9+incompatible 10 | github.com/go-spring/spring-boot v1.0.6-0.20201217113358-0e065f5a87ae 11 | github.com/go-spring/spring-core v1.0.6-0.20201217060132-0c182ff5a770 12 | github.com/go-spring/spring-echo v1.0.6-0.20201215104235-b2468c9d7628 13 | github.com/go-spring/spring-logger v1.0.6-0.20201124021239-090e4c0d9eb1 14 | github.com/go-spring/spring-utils v1.0.6-0.20201217054648-d3d6ed16527e 15 | github.com/go-spring/spring-web v1.0.6-0.20201215100012-db5a465baebe 16 | github.com/go-spring/starter-db v1.0.5 17 | github.com/go-spring/starter-go-redis v1.0.5 18 | github.com/go-spring/starter-gorm v1.0.5 19 | github.com/go-spring/starter-web v1.0.6-0.20201222111800-2895789c2981 20 | github.com/jinzhu/gorm v1.9.15 21 | github.com/labstack/echo v3.3.10+incompatible 22 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 23 | go.mongodb.org/mongo-driver v1.4.0 24 | golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b // indirect 25 | ) 26 | -------------------------------------------------------------------------------- /spring/spring-stl/json/error.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package json 18 | 19 | import ( 20 | "reflect" 21 | ) 22 | 23 | // An InvalidUnmarshalError describes an invalid argument passed to Unmarshal. 24 | // (The argument to Unmarshal must be a non-nil pointer.) 25 | type InvalidUnmarshalError struct { 26 | Type reflect.Type 27 | } 28 | 29 | func (e *InvalidUnmarshalError) Error() string { 30 | if e.Type == nil { 31 | return "json: Unmarshal(nil)" 32 | } 33 | 34 | if e.Type.Kind() != reflect.Ptr { 35 | return "json: Unmarshal(non-pointer " + e.Type.String() + ")" 36 | } 37 | return "json: Unmarshal(nil " + e.Type.String() + ")" 38 | } 39 | -------------------------------------------------------------------------------- /spring/spring-stl/util/net.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "net" 21 | "sync" 22 | ) 23 | 24 | var localIPv4Str = "0.0.0.0" 25 | var localIPv4Once = new(sync.Once) 26 | 27 | // LocalIPv4 获取本机的 IPv4 地址。 28 | func LocalIPv4() string { 29 | localIPv4Once.Do(func() { 30 | if ias, err := net.InterfaceAddrs(); err == nil { 31 | for _, address := range ias { 32 | if ipNet, ok := address.(*net.IPNet); ok && !ipNet.IP.IsLoopback() { 33 | if ipNet.IP.To4() != nil { 34 | localIPv4Str = ipNet.IP.String() 35 | return 36 | } 37 | } 38 | } 39 | } 40 | }) 41 | return localIPv4Str 42 | } 43 | -------------------------------------------------------------------------------- /spring/spring-core/gs/bean/bean.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Package bean 定义了 bean 选择器和 Definition 接口。 18 | package bean 19 | 20 | import "reflect" 21 | 22 | // Definition bean 元数据。 23 | type Definition interface { 24 | Type() reflect.Type // 类型 25 | Value() reflect.Value // 值 26 | Interface() interface{} // 源 27 | ID() string // 返回 bean 的 ID 28 | BeanName() string // 返回 bean 的名称 29 | TypeName() string // 返回类型的全限定名 30 | Wired() bool // 返回是否已完成注入 31 | } 32 | 33 | // Selector bean 选择器,可以是 bean ID 字符串,可以是 reflect.Type 对 34 | // 象,可以是形如 (*error)(nil) 的指针,还可以是 Definition 类型的对象。 35 | type Selector interface{} 36 | -------------------------------------------------------------------------------- /spring/spring-stl/knife/knife_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package knife_test 18 | 19 | import ( 20 | "context" 21 | "testing" 22 | 23 | "github.com/go-spring/spring-stl/assert" 24 | "github.com/go-spring/spring-stl/knife" 25 | ) 26 | 27 | func TestKnife(t *testing.T) { 28 | ctx := context.TODO() 29 | 30 | v := knife.Get(ctx, "a") 31 | assert.Nil(t, v) 32 | 33 | knife.Set(ctx, "a", "b") 34 | 35 | v = knife.Get(ctx, "a") 36 | assert.Nil(t, v) 37 | 38 | ctx = knife.New(ctx) 39 | 40 | v = knife.Get(ctx, "a") 41 | assert.Nil(t, v) 42 | 43 | knife.Set(ctx, "a", "b") 44 | 45 | v = knife.Get(ctx, "a") 46 | assert.Equal(t, v, "b") 47 | } 48 | -------------------------------------------------------------------------------- /starter/starter-go-redis/go-redis-factory/go-redis-factory.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package GoRedisFactory 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/go-redis/redis" 23 | "github.com/go-spring/starter-core" 24 | ) 25 | 26 | // NewClient 创建 Redis 客户端 27 | func NewClient(config StarterCore.RedisConfig) (redis.Cmdable, error) { 28 | 29 | address := fmt.Sprintf("%s:%d", config.Host, config.Port) 30 | client := redis.NewClient(&redis.Options{ 31 | Addr: address, 32 | Password: config.Password, 33 | DB: config.Database, 34 | }) 35 | 36 | if err := client.Ping().Err(); err != nil { 37 | return nil, err 38 | } 39 | return client, nil 40 | } 41 | -------------------------------------------------------------------------------- /spring/spring-core/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/go-spring/spring-stl v0.0.0-20210724153121-8378c2594815 h1:9ez++onyyU2hyVoNOKwHoynIcvTxlvkF74LrDfyliLo= 3 | github.com/go-spring/spring-stl v0.0.0-20210724153121-8378c2594815/go.mod h1:RFkTfNPcNYbppU8krHBfGKjnvhR2Z0nQokpl5s0Te84= 4 | github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= 5 | github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 6 | github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= 7 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 8 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 9 | github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= 10 | github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 11 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 12 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 13 | gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= 14 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 15 | -------------------------------------------------------------------------------- /examples/spring-boot-grpc/helloworld/helloworld.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015 gRPC authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | option go_package = "github.com/go-spring/go-spring-rpc/helloworld"; 18 | option java_multiple_files = true; 19 | option java_package = "io.grpc.examples.helloworld"; 20 | option java_outer_classname = "HelloWorldProto"; 21 | 22 | package helloworld; 23 | 24 | // The greeting service definition. 25 | service Greeter { 26 | // Sends a greeting 27 | rpc SayHello (HelloRequest) returns (HelloReply) {} 28 | } 29 | 30 | // The request message containing the user's name. 31 | message HelloRequest { 32 | string name = 1; 33 | } 34 | 35 | // The response message containing the greetings 36 | message HelloReply { 37 | string message = 1; 38 | } 39 | -------------------------------------------------------------------------------- /starter/starter-core/web.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package StarterCore 18 | 19 | import ( 20 | "time" 21 | ) 22 | 23 | // WebServerConfig Web 服务器配置 24 | type WebServerConfig struct { 25 | IP string `value:"${web.server.ip:=}"` // 监听 IP 26 | Port int `value:"${web.server.port:=8080}"` // HTTP 端口 27 | EnableSSL bool `value:"${web.server.ssl.enable:=false}"` // 是否启用 HTTPS 28 | KeyFile string `value:"${web.server.ssl.key:=}"` // SSL 秘钥 29 | CertFile string `value:"${web.server.ssl.cert:=}"` // SSL 证书 30 | BasePath string `value:"${web.server.base-path:=/}"` // 根路径 31 | ReadTimeout time.Duration 32 | WriteTimeout time.Duration 33 | } 34 | -------------------------------------------------------------------------------- /spring/spring-core/conf/reader.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package conf 18 | 19 | import ( 20 | "github.com/go-spring/spring-core/conf/prop" 21 | "github.com/go-spring/spring-core/conf/toml" 22 | "github.com/go-spring/spring-core/conf/yaml" 23 | ) 24 | 25 | func init() { 26 | NewReader(yaml.Read, ".yaml", ".yml") 27 | NewReader(prop.Read, ".properties") 28 | NewReader(toml.Read, ".toml") 29 | } 30 | 31 | var readers = make(map[string]Reader) 32 | 33 | // Reader 属性列表解析器,将字节数组解析成 map 数据。 34 | type Reader func(b []byte) (map[string]interface{}, error) 35 | 36 | // NewReader 注册属性列表解析器,ext 是解析器支持的文件扩展名。 37 | func NewReader(r Reader, ext ...string) { 38 | for _, s := range ext { 39 | readers[s] = r 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /spring/spring-core/gs/testdata/pkg/foo/pkg.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package pkg 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | ) 23 | 24 | // golang 允许不同的路径下存在相同的包,而且允许存在相同的包。 25 | type SamePkg struct{} 26 | 27 | func (p *SamePkg) Package() { 28 | fmt.Println("github.com/go-spring/spring-core/gs/testdata/pkg/foo/pkg.SamePkg") 29 | } 30 | 31 | type appContext struct { 32 | // 导出 fmt.Stringer 接口 33 | // 这种导出方式建议写在最上面 34 | _ fmt.Stringer `export:""` 35 | 36 | // 导出 context.Context 接口 37 | context.Context `export:""` 38 | } 39 | 40 | func NewAppContext() *appContext { 41 | return &appContext{ 42 | Context: context.TODO(), 43 | } 44 | } 45 | 46 | func (_ *appContext) String() string { 47 | return "" 48 | } 49 | -------------------------------------------------------------------------------- /spring/spring-swag/swagger/swagger_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package swagger_test 18 | 19 | import ( 20 | "fmt" 21 | "testing" 22 | 23 | "github.com/go-spring/spring-core/web" 24 | "github.com/go-spring/spring-stl/assert" 25 | "github.com/go-spring/spring-swag/swagger" 26 | ) 27 | 28 | func Test_Doc(t *testing.T) { 29 | c := web.NewAbstractContainer(web.ContainerConfig{}) 30 | swagger.Doc(c).WithID("go-spring").WithHost("https://go-spring.com") 31 | m := c.HandleGet("/idx", web.FUNC(func(ctx web.Context) {})) 32 | swagger.Path(m).WithDescription("welcome to go-spring") 33 | web.RegisterSwaggerHandler(func(router web.Router, doc string) { fmt.Println(doc) }) 34 | _ = c.Start() 35 | assert.True(t, true) 36 | } 37 | -------------------------------------------------------------------------------- /examples/spring-boot-junit/test/service-hello_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package test 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/go-spring/examples/spring-boot-junit/service" 23 | "github.com/go-spring/spring-boot" 24 | "github.com/magiconair/properties/assert" 25 | ) 26 | 27 | func init() { 28 | SpringBoot.RegisterBean(new(ServiceHelloSuite)) 29 | } 30 | 31 | type ServiceHelloSuite struct { 32 | _ SpringBoot.JUnitSuite `export:""` 33 | 34 | Hello *service.Hello `autowire:""` 35 | } 36 | 37 | func (s *ServiceHelloSuite) Test(t *testing.T) { 38 | assert.Equal(t, s.Hello.Say("world"), "hello world from junit") 39 | t.Run("child", func(t *testing.T) { 40 | assert.Equal(t, s.Hello.Say("world"), "hello world from junit") 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /spring/spring-core/validator/validator.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Package validator 提供了参数校验器接口。 18 | package validator 19 | 20 | // Validator 参数校验器接口。 21 | type Validator interface { 22 | Validate(i interface{}) error 23 | } 24 | 25 | var v Validator 26 | 27 | // Init 初始化参数校验器。 28 | func Init(r Validator) { 29 | v = r 30 | } 31 | 32 | // InitFunc 初始化参数校验器。 33 | func InitFunc(r func(i interface{}) error) { 34 | v = funcValidator(r) 35 | } 36 | 37 | // funcValidator 基于简单函数的参数校验器。 38 | type funcValidator func(i interface{}) error 39 | 40 | func (f funcValidator) Validate(i interface{}) error { 41 | return f(i) 42 | } 43 | 44 | // Validate 参数校验。 45 | func Validate(i interface{}) error { 46 | if v != nil { 47 | return v.Validate(i) 48 | } 49 | return nil 50 | } 51 | -------------------------------------------------------------------------------- /spring/spring-stl/contain/contain.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package contain 18 | 19 | import ( 20 | "container/list" 21 | ) 22 | 23 | // Ints 在一个 int 数组中进行查找,找不到返回 -1。 24 | func Ints(arr []int, val int) int { 25 | for i := 0; i < len(arr); i++ { 26 | if arr[i] == val { 27 | return i 28 | } 29 | } 30 | return -1 31 | } 32 | 33 | // Strings 在一个 string 数组中进行查找,找不到返回 -1。 34 | func Strings(arr []string, val string) int { 35 | for i := 0; i < len(arr); i++ { 36 | if arr[i] == val { 37 | return i 38 | } 39 | } 40 | return -1 41 | } 42 | 43 | // List 在列表中查询指定元素,存在则返回列表项指针,不存在返回 nil。 44 | func List(l *list.List, v interface{}) *list.Element { 45 | for e := l.Front(); e != nil; e = e.Next() { 46 | if e.Value == v { 47 | return e 48 | } 49 | } 50 | return nil 51 | } 52 | -------------------------------------------------------------------------------- /spring/spring-stl/util/panic.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "fmt" 21 | ) 22 | 23 | // PanicCond 封装触发 panic 的条件。 24 | type PanicCond struct { 25 | fn func() interface{} 26 | } 27 | 28 | // When 满足给定条件时抛出一个 panic 。 29 | func (p *PanicCond) When(isPanic bool) { 30 | if isPanic { 31 | panic(p.fn()) 32 | } 33 | } 34 | 35 | // NewPanicCond PanicCond 的构造函数。 36 | func NewPanicCond(fn func() interface{}) *PanicCond { 37 | return &PanicCond{fn} 38 | } 39 | 40 | // Panic 抛出一个异常值。 41 | func Panic(err error) *PanicCond { 42 | return NewPanicCond(func() interface{} { return err }) 43 | } 44 | 45 | // Panicf 抛出一段需要格式化的错误字符串。 46 | func Panicf(format string, a ...interface{}) *PanicCond { 47 | return NewPanicCond(func() interface{} { return fmt.Errorf(format, a...) }) 48 | } 49 | -------------------------------------------------------------------------------- /spring/spring-stl/flat/flat_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flat_test 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/go-spring/spring-stl/assert" 23 | "github.com/go-spring/spring-stl/flat" 24 | ) 25 | 26 | func TestFlatMap(t *testing.T) { 27 | m := map[string]interface{}{ 28 | "a": map[string]interface{}{ 29 | "b": map[string]interface{}{ 30 | "c": "d", 31 | }, 32 | "e": []interface{}{ 33 | "f", "g", 34 | }, 35 | "h": "i", 36 | }, 37 | "j": []interface{}{ 38 | "k", "l", 39 | }, 40 | "m": "n", 41 | } 42 | ret := flat.Map(m) 43 | expect := map[string]interface{}{ 44 | "a.b.c": "d", 45 | "a.e[0]": "f", 46 | "a.e[1]": "g", 47 | "a.h": "i", 48 | "j[0]": "k", 49 | "j[1]": "l", 50 | "m": "n", 51 | } 52 | assert.Equal(t, ret, expect) 53 | } 54 | -------------------------------------------------------------------------------- /examples/spring-boot-message/consumer/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/go-spring/spring-boot" 23 | "github.com/go-spring/spring-logger" 24 | "github.com/go-spring/spring-utils" 25 | _ "github.com/go-spring/starter-rabbitmq/consumer" 26 | ) 27 | 28 | func init() { 29 | SpringBoot.RegisterBean(new(binder)).Init(func(b *binder) { 30 | SpringBoot.BindConsumer("topic-stream-idle", b.Idle) 31 | }) 32 | } 33 | 34 | type binder struct { 35 | } 36 | 37 | type IdleReq struct { 38 | Stream string `json:"stream"` 39 | } 40 | 41 | func (b *binder) Idle(ctx context.Context, req *IdleReq) { 42 | webCtx := SpringLogger.NewDefaultLoggerContext(ctx) 43 | webCtx.LogInfo(SpringUtils.ToJson(req)) 44 | } 45 | 46 | func main() { 47 | SpringBoot.RunApplication() 48 | } 49 | -------------------------------------------------------------------------------- /spring/spring-stl/knife/knife.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package knife 18 | 19 | import ( 20 | "context" 21 | "sync" 22 | ) 23 | 24 | const ctxKey = "::knife::" 25 | 26 | func cache(ctx context.Context) *sync.Map { 27 | c, _ := ctx.Value(ctxKey).(*sync.Map) 28 | return c 29 | } 30 | 31 | // New 返回带有缓存空间的 context.Context 对象。 32 | func New(ctx context.Context) context.Context { 33 | return context.WithValue(ctx, ctxKey, new(sync.Map)) 34 | } 35 | 36 | // Get 从 context.Context 对象中获取 key 对应的 val。 37 | func Get(ctx context.Context, key string) interface{} { 38 | if c := cache(ctx); c != nil { 39 | v, _ := c.Load(key) 40 | return v 41 | } 42 | return nil 43 | } 44 | 45 | // Set 将 key 及其 val 保存到 context.Context 对象。 46 | func Set(ctx context.Context, key string, val interface{}) { 47 | if c := cache(ctx); c != nil { 48 | c.Store(key, val) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /starter/starter-rabbitmq/producer/producer.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package StarterRabbitMQProducer 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/go-spring/spring-core/gs" 23 | "github.com/go-spring/spring-core/mq" 24 | "github.com/go-spring/starter-rabbitmq/server" 25 | "github.com/streadway/amqp" 26 | ) 27 | 28 | func init() { 29 | gs.Object(new(Sender)).Name("amqp-sender").Export((*mq.Producer)(nil)) 30 | } 31 | 32 | type Sender struct { 33 | Server *StarterRabbitMQServer.AMQPServer `autowire:""` 34 | } 35 | 36 | func (sender *Sender) SendMessage(ctx context.Context, msg mq.Message) error { 37 | return sender.Server.Channel.Publish( 38 | "", // exchange 39 | msg.Topic(), // routing key 40 | false, // mandatory 41 | false, // immediate 42 | amqp.Publishing{ 43 | ContentType: "text/plain", 44 | Body: msg.Body(), 45 | }) 46 | } 47 | -------------------------------------------------------------------------------- /examples/spring-boot-demo/filter/single_filter.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package filter 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/go-spring/spring-boot" 23 | "github.com/go-spring/spring-core" 24 | "github.com/go-spring/spring-logger" 25 | "github.com/go-spring/spring-web" 26 | ) 27 | 28 | func init() { 29 | // 这种方式可以避免使用 export 语法,就像 StringFilter 和 NumberFilter 那样。 30 | SpringBoot.RegisterFilter(SpringCore.ObjectBean(new(SingleBeanFilter))) 31 | } 32 | 33 | type SingleBeanFilter struct { 34 | DefaultValue string `value:"${default-value:=default}"` 35 | } 36 | 37 | func (f *SingleBeanFilter) Invoke(ctx SpringWeb.WebContext, chain SpringWeb.FilterChain) { 38 | if f.DefaultValue != "app-test" { 39 | panic(fmt.Errorf("${default-value} expect 'app-test' but '%s'", f.DefaultValue)) 40 | } 41 | SpringLogger.WithContext(ctx.Context()).Info("::SingleBeanFilter") 42 | chain.Next(ctx) 43 | } 44 | -------------------------------------------------------------------------------- /examples/spring-web-filter/abort/abort.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package abort 18 | 19 | import ( 20 | "net/http" 21 | "strconv" 22 | 23 | "github.com/go-spring/spring-web" 24 | ) 25 | 26 | type StringArray struct { 27 | Data []string 28 | } 29 | 30 | func (s *StringArray) Push(str string) { 31 | s.Data = append(s.Data, str) 32 | } 33 | 34 | type PushFilter struct { 35 | num int 36 | abort bool 37 | array *StringArray 38 | } 39 | 40 | func NewPushFilter(num int, abort bool, array *StringArray) *PushFilter { 41 | return &PushFilter{num: num, abort: abort, array: array} 42 | } 43 | 44 | func (f *PushFilter) Invoke(ctx SpringWeb.WebContext, chain SpringWeb.FilterChain) { 45 | 46 | if f.abort { // 中断处理过程 47 | panic(SpringWeb.NewHttpError(http.StatusOK)) 48 | } 49 | 50 | f.array.Push(strconv.Itoa(f.num)) 51 | chain.Next(ctx) 52 | 53 | // 返回时没有中断则添加一个数 54 | f.array.Push(strconv.Itoa(f.num)) 55 | } 56 | -------------------------------------------------------------------------------- /starter/starter-web/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10 h1:3wVokv0UL8xf5f99gDK5CXW7+AkBhMPzasfK10d5mIM= 3 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10/go.mod h1:dlmlLZon5quLckxW7TkmY+OYuVUMB9ot28fxTL/3fYA= 4 | github.com/go-spring/spring-stl v0.0.0-20210724153121-8378c2594815 h1:9ez++onyyU2hyVoNOKwHoynIcvTxlvkF74LrDfyliLo= 5 | github.com/go-spring/spring-stl v0.0.0-20210724153121-8378c2594815/go.mod h1:RFkTfNPcNYbppU8krHBfGKjnvhR2Z0nQokpl5s0Te84= 6 | github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= 7 | github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 8 | github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= 9 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 10 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 11 | github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= 12 | github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 13 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 14 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 15 | gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= 16 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 17 | -------------------------------------------------------------------------------- /examples/spring-web-testcases/spring-web-filter_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package testcases_test 18 | 19 | import ( 20 | "container/list" 21 | "context" 22 | "testing" 23 | 24 | "github.com/go-spring/examples/testcases" 25 | "github.com/go-spring/spring-echo" 26 | "github.com/go-spring/spring-logger" 27 | "github.com/go-spring/spring-utils" 28 | "github.com/go-spring/spring-web" 29 | "github.com/stretchr/testify/assert" 30 | ) 31 | 32 | func TestFilterChain(t *testing.T) { 33 | 34 | logCtx := SpringLogger.NewDefaultLoggerContext(context.Background()) 35 | webCtx := &SpringEcho.Context{ 36 | LoggerContext: logCtx, 37 | } 38 | 39 | l := list.New() 40 | 41 | filters := []SpringWeb.Filter{ 42 | testcases.NewNumberFilter(2, l), 43 | testcases.NewNumberFilter(5, l), 44 | } 45 | 46 | chain := SpringWeb.NewDefaultFilterChain(filters) 47 | chain.Next(webCtx) 48 | 49 | assert.Equal(t, SpringUtils.NewList(2, 5, 5, 2), l) 50 | } 51 | -------------------------------------------------------------------------------- /examples/spring-boot-message/producer/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "context" 21 | "time" 22 | 23 | "github.com/go-spring/spring-boot" 24 | "github.com/go-spring/spring-message" 25 | "github.com/go-spring/spring-utils" 26 | _ "github.com/go-spring/starter-rabbitmq/producer" 27 | ) 28 | 29 | func init() { 30 | SpringBoot.RegisterBean(new(producer)) 31 | } 32 | 33 | type producer struct { 34 | _ SpringBoot.CommandLineRunner `export:""` 35 | 36 | Producer SpringMessage.Producer `autowire:""` 37 | } 38 | 39 | func (r *producer) Run(appCtx SpringBoot.ApplicationContext) { 40 | appCtx.SafeGoroutine(func() { 41 | time.Sleep(time.Millisecond * 100) 42 | msg := SpringMessage.NewMessage().WithTopic("topic-stream-idle").WithBody([]byte(`{"stream":"live"}`)) 43 | err := r.Producer.SendMessage(context.Background(), msg) 44 | SpringUtils.Panic(err).When(err != nil) 45 | SpringBoot.Exit() 46 | }) 47 | } 48 | 49 | func main() { 50 | SpringBoot.RunApplication() 51 | } 52 | -------------------------------------------------------------------------------- /spring/spring-core/gs/testdata/config/application.yaml: -------------------------------------------------------------------------------- 1 | yaml: 2 | list: 3 | - 1 4 | - 2 5 | obj: 6 | list: 7 | - name: "jim" 8 | age: 12 9 | - name: "bob" 10 | age: 8 11 | 12 | point_list: 13 | - (2,3) 14 | - (5,3) 15 | 16 | db: 17 | - username: root 18 | password: 123456 19 | url: 1.1.1.1 20 | port: 3306 21 | db: db1 22 | - username: root 23 | password: 123456 24 | url: 1.1.1.1 25 | port: 3306 26 | db: db2 27 | 28 | tagged: 29 | db: 30 | - tag.username: root 31 | tag.password: 123456 32 | tag.url: 1.1.1.1 33 | tag.port: 3306 34 | db: db1 35 | - tag.username: root 36 | tag.password: 123456 37 | tag.url: 1.1.1.1 38 | tag.port: 3306 39 | db: db2 40 | 41 | prefix: 42 | db: 43 | - username: root 44 | password: 123456 45 | url: 1.1.1.1 46 | port: 3306 47 | db: db1 48 | - username: root 49 | password: 123456 50 | url: 1.1.1.1 51 | port: 3306 52 | db: db2 53 | 54 | camera: 55 | floor1: camera_floor1 56 | floor2: camera_floor2 57 | floor3: camera_floor3 58 | 59 | db_map: 60 | d1: 61 | username: root 62 | password: 123456 63 | url: 1.1.1.1 64 | port: 3306 65 | db: db1 66 | d2: 67 | username: root 68 | password: 123456 69 | url: 1.1.1.1 70 | port: 3306 71 | db: db2 72 | 73 | prefix_map: 74 | db_map: 75 | d1: 76 | username: root 77 | password: 123456 78 | url: 1.1.1.1 79 | port: 3306 80 | db: db1 81 | d2: 82 | username: root 83 | password: 123456 84 | url: 1.1.1.1 85 | port: 3306 86 | db: db2 -------------------------------------------------------------------------------- /spring/spring-core/web/filter_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package web_test 18 | 19 | import ( 20 | "fmt" 21 | "net/http" 22 | "testing" 23 | 24 | "github.com/go-spring/spring-core/web" 25 | "github.com/go-spring/spring-stl/util" 26 | ) 27 | 28 | func TestFuncFilter(t *testing.T) { 29 | 30 | funcFilter := web.FuncFilter(func(ctx web.Context, chain web.FilterChain) { 31 | fmt.Println("@FuncFilter") 32 | chain.Next(ctx) 33 | }) 34 | 35 | handlerFilter := web.HandlerFilter(web.FUNC(func(ctx web.Context) { 36 | fmt.Println("@HandlerFilter") 37 | })) 38 | 39 | web.NewDefaultFilterChain([]web.Filter{funcFilter, handlerFilter}).Next(nil) 40 | } 41 | 42 | type Counter struct{} 43 | 44 | func (ctr *Counter) ServeHTTP(http.ResponseWriter, *http.Request) {} 45 | 46 | func TestWrapH(t *testing.T) { 47 | 48 | c := &Counter{} 49 | fmt.Println(util.FileLine(c.ServeHTTP)) 50 | 51 | var h http.Handler 52 | h = &Counter{} 53 | fmt.Println(util.FileLine(h.ServeHTTP)) 54 | 55 | fmt.Println(web.WrapH(&Counter{}).FileLine()) 56 | } 57 | -------------------------------------------------------------------------------- /spring/spring-core/conf/testdata/config/application.yaml: -------------------------------------------------------------------------------- 1 | yaml: 2 | list: 3 | - 1 4 | - 2 5 | obj: 6 | list: 7 | - name: "jim" 8 | age: 12 9 | - name: "bob" 10 | age: 8 11 | 12 | point: 13 | list: 14 | - (2,3) 15 | - (5,3) 16 | 17 | db: 18 | - username: root 19 | password: 123456 20 | url: 1.1.1.1 21 | port: 3306 22 | db: db1 23 | - username: root 24 | password: 123456 25 | url: 1.1.1.1 26 | port: 3306 27 | db: db2 28 | 29 | tagged: 30 | db: 31 | - tag: 32 | username: root 33 | password: 123456 34 | url: 1.1.1.1 35 | port: 3306 36 | db: db1 37 | - tag: 38 | username: root 39 | password: 123456 40 | url: 1.1.1.1 41 | port: 3306 42 | db: db2 43 | 44 | prefix: 45 | db: 46 | - username: root 47 | password: 123456 48 | url: 1.1.1.1 49 | port: 3306 50 | db: db1 51 | - username: root 52 | password: 123456 53 | url: 1.1.1.1 54 | port: 3306 55 | db: db2 56 | 57 | camera: 58 | floor1: camera_floor1 59 | floor2: camera_floor2 60 | floor3: camera_floor3 61 | 62 | db_map: 63 | d1: 64 | username: root 65 | password: 123456 66 | url: 1.1.1.1 67 | port: 3306 68 | db: db1 69 | d2: 70 | username: root 71 | password: 123456 72 | url: 1.1.1.1 73 | port: 3306 74 | db: db2 75 | 76 | prefix_map: 77 | db_map: 78 | d1: 79 | username: root 80 | password: 123456 81 | url: 1.1.1.1 82 | port: 3306 83 | db: db1 84 | d2: 85 | username: root 86 | password: 123456 87 | url: 1.1.1.1 88 | port: 3306 89 | db: db2 -------------------------------------------------------------------------------- /starter/starter-go-mongo/go-mongo-factory/go-mongo-factory.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package GoMongoFactory 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/go-spring/spring-core/log" 23 | "github.com/go-spring/starter-mongo" 24 | "go.mongodb.org/mongo-driver/mongo" 25 | "go.mongodb.org/mongo-driver/mongo/options" 26 | "go.mongodb.org/mongo-driver/mongo/readpref" 27 | ) 28 | 29 | // NewClient 创建 MongoDB 客户端 30 | func NewClient(config StarterMongo.Config) (*mongo.Client, error) { 31 | log.Info("open mongo db ", config.Url) 32 | ctx := context.Background() 33 | 34 | client, err := mongo.Connect(ctx, options.Client().ApplyURI(config.Url)) 35 | if err != nil { 36 | return nil, err 37 | } 38 | 39 | if err = client.Ping(ctx, readpref.Primary()); err != nil { 40 | return nil, err 41 | } 42 | return client, err 43 | } 44 | 45 | // CloseClient 关闭 MongoDB 客户端 46 | func CloseClient(client *mongo.Client) { 47 | log.Info("close mongo db") 48 | if err := client.Disconnect(context.Background()); err != nil { 49 | log.Error(err) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /examples/spring-boot-demo/filter/number_filter.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package filter 18 | 19 | import ( 20 | "container/list" 21 | 22 | "github.com/go-spring/spring-boot" 23 | "github.com/go-spring/spring-logger" 24 | "github.com/go-spring/spring-web" 25 | ) 26 | 27 | func init() { 28 | l := list.New() 29 | SpringBoot.RegisterNameBean("f2", NewNumberFilter(2, l)) 30 | SpringBoot.RegisterNameBean("f5", NewNumberFilter(5, l)) 31 | SpringBoot.RegisterNameBean("f7", NewNumberFilter(7, l)) 32 | } 33 | 34 | type NumberFilter struct { 35 | _ SpringWeb.Filter `export:""` 36 | 37 | l *list.List 38 | N int 39 | } 40 | 41 | func NewNumberFilter(n int, l *list.List) *NumberFilter { 42 | return &NumberFilter{ 43 | l: l, 44 | N: n, 45 | } 46 | } 47 | 48 | func (f *NumberFilter) Invoke(ctx SpringWeb.WebContext, chain SpringWeb.FilterChain) { 49 | log := SpringLogger.WithContext(ctx.Context()) 50 | 51 | defer func() { 52 | log.Info("::after", f.N) 53 | f.l.PushBack(f.N) 54 | }() 55 | 56 | log.Info("::before", f.N) 57 | f.l.PushBack(f.N) 58 | 59 | chain.Next(ctx) 60 | } 61 | -------------------------------------------------------------------------------- /examples/spring-boot-grpc/greeter_server/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2015 gRPC authors. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | // Package main implements a server for Greeter service. 20 | package main 21 | 22 | import ( 23 | "context" 24 | "log" 25 | 26 | pb "github.com/go-spring/examples/spring-boot-grpc/helloworld" 27 | "github.com/go-spring/spring-boot" 28 | _ "github.com/go-spring/starter-grpc/server" 29 | ) 30 | 31 | func init() { 32 | SpringBoot.RegisterGRpcServer(pb.RegisterGreeterServer, 33 | "helloworld.Greeter", 34 | new(GreeterServer), 35 | ).ConditionOnOptionalPropertyValue("greeter-server.enable", true) 36 | } 37 | 38 | type GreeterServer struct { 39 | AppName string `value:"${spring.application.name}"` 40 | } 41 | 42 | func (s *GreeterServer) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { 43 | log.Printf("Received: %v", in.GetName()) 44 | return &pb.HelloReply{Message: "Hello " + in.GetName() + " from " + s.AppName}, nil 45 | } 46 | 47 | func main() { 48 | SpringBoot.SetProperty("spring.application.name", "GreeterServer") 49 | SpringBoot.SetProperty("grpc.server.port", 50051) 50 | SpringBoot.RunApplication() 51 | } 52 | -------------------------------------------------------------------------------- /spring/spring-rabbitmq/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/go-spring/go-spring-parent v1.0.4-0.20200615061648-3687ec727ddf/go.mod h1:/ABXFJozlTW7YrEs2U1EmTtWCG0gufSgDQnCfkOnkWs= 4 | github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= 5 | github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 6 | github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 7 | github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= 8 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 9 | github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 10 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 11 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 12 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 13 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 14 | github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= 15 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 16 | golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 17 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 18 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 19 | -------------------------------------------------------------------------------- /starter/starter-rabbitmq/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10 h1:3wVokv0UL8xf5f99gDK5CXW7+AkBhMPzasfK10d5mIM= 3 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10/go.mod h1:dlmlLZon5quLckxW7TkmY+OYuVUMB9ot28fxTL/3fYA= 4 | github.com/go-spring/spring-stl v0.0.0-20210724153121-8378c2594815 h1:9ez++onyyU2hyVoNOKwHoynIcvTxlvkF74LrDfyliLo= 5 | github.com/go-spring/spring-stl v0.0.0-20210724153121-8378c2594815/go.mod h1:RFkTfNPcNYbppU8krHBfGKjnvhR2Z0nQokpl5s0Te84= 6 | github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= 7 | github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 8 | github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= 9 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 10 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 11 | github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= 12 | github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 13 | github.com/streadway/amqp v1.0.0 h1:kuuDrUJFZL1QYL9hUNuCxNObNzB0bV/ZG5jV3RWAQgo= 14 | github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= 15 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 16 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 17 | gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= 18 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 19 | -------------------------------------------------------------------------------- /spring/spring-stl/flat/flat.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flat 18 | 19 | import ( 20 | "fmt" 21 | ) 22 | 23 | // Struct 将结构体的公开字段打平。 24 | func Struct(v interface{}) map[string]interface{} { 25 | return make(map[string]interface{}) 26 | } 27 | 28 | // Map 将嵌套形式的 map 打平,map 必须是 map[string]interface{} 类型。 29 | func Map(m map[string]interface{}) map[string]interface{} { 30 | p := make(map[string]interface{}) 31 | flatMap("", m, p) 32 | return p 33 | } 34 | 35 | func flatValue(key string, v interface{}, out map[string]interface{}) { 36 | switch value := v.(type) { 37 | case map[string]interface{}: 38 | flatMap(key+".", value, out) 39 | case []interface{}: 40 | flatSlice(key, value, out) 41 | default: 42 | out[key] = v 43 | } 44 | } 45 | 46 | func flatSlice(prefix string, arr []interface{}, out map[string]interface{}) { 47 | for i, v := range arr { 48 | key := fmt.Sprintf("%s[%d]", prefix, i) 49 | flatValue(key, v, out) 50 | } 51 | } 52 | 53 | func flatMap(prefix string, m map[string]interface{}, out map[string]interface{}) { 54 | for k, v := range m { 55 | flatValue(prefix+k, v, out) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 当前目录是否是 Go 项目目录 4 | function isProjectDir(){ 5 | if [ -f $1"/go.mod" ]; then 6 | return $((1)) 7 | fi 8 | return $((0)) 9 | } 10 | 11 | # 找到 Go 项目目录并执行命令 12 | function run(){ 13 | for element in `ls $1` 14 | do 15 | dir_or_file=$1"/"$element 16 | if [ -d $dir_or_file ]; then 17 | isProjectDir $dir_or_file 18 | if [ $? -eq 0 ]; then 19 | run $dir_or_file $2 20 | cd $dir_or_file 21 | else 22 | echo $dir_or_file 23 | cd $dir_or_file 24 | case $2 in 25 | "test") 26 | # 执行当前目录及子目录下的测试用例 27 | go test -count=1 ./... ;; 28 | "lint") 29 | # https://github.com/golangci/golangci-lint 30 | golangci-lint run ;; 31 | *) 32 | ;; 33 | esac 34 | fi 35 | fi 36 | done 37 | } 38 | 39 | # 启动项目的 doc 页面 40 | function doc() { 41 | 42 | project=$2 43 | array=(${project//-/ }) 44 | dir=${array[0]} 45 | if [[ $dir != "spring" && $dir != "starter" ]]; then 46 | exit 47 | fi 48 | 49 | WORKSPACE=$1"/"$dir"/"$project 50 | echo $WORKSPACE 51 | echo ";; 首次启动加载时间较长,请耐心等待并手动刷新 doc 页面" 52 | 53 | MODULE_NAME=$project 54 | PACKAGE_PATH=github.com/go-spring 55 | export GOPATH=/tmp/godoc-${MODULE_NAME} 56 | MODULE_PATH=${GOPATH}/src/${PACKAGE_PATH} 57 | 58 | rm -rf $MODULE_PATH/$MODULE_NAME &> /dev/null 59 | mkdir -p $GOPATH/bin 60 | mkdir -p $MODULE_PATH 61 | ln -sf $WORKSPACE ${MODULE_PATH}/${MODULE_NAME} 62 | 63 | cd $MODULE_PATH/$MODULE_NAME 64 | python -m webbrowser "http://localhost:6060/pkg/github.com/go-spring/"${MODULE_NAME} 65 | godoc 66 | } 67 | 68 | # 命令包括: test、lint、doc. 69 | case $1 in 70 | "doc") 71 | doc $(pwd) $2;; 72 | *) 73 | run $(pwd) $1 ;; 74 | esac -------------------------------------------------------------------------------- /spring/spring-stl/errors/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package errors 18 | 19 | import ( 20 | "errors" 21 | "fmt" 22 | "runtime" 23 | ) 24 | 25 | var ( 26 | New = errors.New 27 | Is = errors.Is 28 | As = errors.As 29 | Unwrap = errors.Unwrap 30 | ) 31 | 32 | // ToString 返回 error 的字符串。 33 | func ToString(err error) string { 34 | if err == nil { 35 | return "" 36 | } 37 | return err.Error() 38 | } 39 | 40 | type withCause struct { 41 | cause interface{} 42 | } 43 | 44 | // WithCause 封装一个异常源。 45 | func WithCause(r interface{}) error { 46 | return &withCause{cause: r} 47 | } 48 | 49 | func (c *withCause) Error() string { 50 | return fmt.Sprint(c.cause) 51 | } 52 | 53 | // Cause 获取封装的异常源。 54 | func Cause(err error) interface{} { 55 | if c, ok := err.(*withCause); ok { 56 | return c.cause 57 | } 58 | return err 59 | } 60 | 61 | // WithFileLine 返回错误发生的文件行号,skip 是相对于当前函数的深度。 62 | func WithFileLine(err error, skip int) error { 63 | _, file, line, _ := runtime.Caller(skip + 1) 64 | str := fmt.Sprintf("%s:%d", file, line) 65 | if err != nil { 66 | str += ": " + err.Error() 67 | } 68 | return New(str) 69 | } 70 | -------------------------------------------------------------------------------- /spring/spring-core/conf/convert.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package conf 18 | 19 | import ( 20 | "errors" 21 | "reflect" 22 | "time" 23 | 24 | "github.com/go-spring/spring-stl/cast" 25 | "github.com/go-spring/spring-stl/util" 26 | ) 27 | 28 | var converters = map[reflect.Type]interface{}{} 29 | 30 | func init() { 31 | 32 | // time.Time 转换函数,支持非常多的日期格式,参见 cast.StringToDate()。 33 | Convert(func(s string) (time.Time, error) { return cast.ToTimeE(s) }) 34 | 35 | // time.Duration 转换函数,支持 "ns", "us" (or "µs"), "ms", "s", "m", "h" 等。 36 | Convert(func(s string) (time.Duration, error) { return cast.ToDurationE(s) }) 37 | } 38 | 39 | func validConverter(t reflect.Type) bool { 40 | return t.Kind() == reflect.Func && 41 | t.NumIn() == 1 && 42 | t.In(0).Kind() == reflect.String && 43 | t.NumOut() == 2 && 44 | util.IsValueType(t.Out(0)) && 45 | util.IsErrorType(t.Out(1)) 46 | } 47 | 48 | // Convert 注册类型转换器,转换器的函数原型为 func(string)(type,error) 。 49 | func Convert(fn interface{}) { 50 | t := reflect.TypeOf(fn) 51 | if !validConverter(t) { 52 | panic(errors.New("fn must be func(string)(type,error)")) 53 | } 54 | converters[t.Out(0)] = fn 55 | } 56 | -------------------------------------------------------------------------------- /examples/spring-boot-demo/filter/string_filter.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package filter 18 | 19 | import ( 20 | "github.com/go-spring/spring-boot" 21 | "github.com/go-spring/spring-logger" 22 | "github.com/go-spring/spring-web" 23 | ) 24 | 25 | func init() { 26 | SpringBoot.RegisterNameBean("server", NewStringFilter("server")) 27 | SpringBoot.RegisterNameBean("container", NewStringFilter("container")) 28 | SpringBoot.RegisterNameBean("router", NewStringFilter("router")) 29 | SpringBoot.RegisterNameBean("router//ok", NewStringFilter("router//ok")) 30 | SpringBoot.RegisterNameBean("router//echo", NewStringFilter("router//echo")) 31 | } 32 | 33 | type StringFilter struct { 34 | _ SpringWeb.Filter `export:""` 35 | 36 | s string 37 | } 38 | 39 | func NewStringFilter(s string) *StringFilter { 40 | return &StringFilter{s: s} 41 | } 42 | 43 | func (f *StringFilter) Invoke(ctx SpringWeb.WebContext, chain SpringWeb.FilterChain) { 44 | log := SpringLogger.WithContext(ctx.Context()) 45 | 46 | defer func() { log.Info("after ", f.s, " code:", ctx.ResponseWriter().Status()) }() 47 | log.Info("before ", f.s) 48 | SpringLogger.Info(f.s) 49 | 50 | chain.Next(ctx) 51 | } 52 | -------------------------------------------------------------------------------- /spring/spring-core/gs/environ/environ.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Package environ 提供了 go-spring 所有内置属性的定义,以及一种允许使用环境变量 18 | // 进行属性覆盖的机制。 19 | package environ 20 | 21 | const ( 22 | Version = "go-spring@v1.0.5" 23 | Website = "https://go-spring.com/" 24 | ) 25 | 26 | // IncludeEnvPatterns 只加载符合条件的环境变量。 27 | const IncludeEnvPatterns = "INCLUDE_ENV_PATTERNS" 28 | 29 | // ExcludeEnvPatterns 排除符合条件的环境变量。 30 | const ExcludeEnvPatterns = "EXCLUDE_ENV_PATTERNS" 31 | 32 | // EnablePandora 是否允许 gs.Pandora 接口。 33 | const EnablePandora = "enable-pandora" 34 | 35 | // SpringPidFile 保存进程 ID 的文件。 36 | const SpringPidFile = "spring.pid.file" 37 | 38 | // SpringConfigLocations 配置文件的位置,支持逗号分隔。 39 | const SpringConfigLocations = "spring.config.locations" 40 | 41 | // SpringConfigExtensions 配置文件的扩展名,支持逗号分隔。 42 | const SpringConfigExtensions = "spring.config.extensions" 43 | 44 | // SpringBannerVisible 是否显示 banner。 45 | const SpringBannerVisible = "spring.banner.visible" 46 | 47 | // SpringProfilesActive 当前应用的 profile 配置。 48 | const SpringProfilesActive = "spring.profiles.active" 49 | 50 | // SpringApplicationName 当前应用的名称。 51 | const SpringApplicationName = "spring.application.name" 52 | -------------------------------------------------------------------------------- /examples/spring-boot-demo/config/banner.txt: -------------------------------------------------------------------------------- 1 | .';!|%%%%%||!:'` 2 | '%#@$;` .`:!|$@#@%: 3 | ;@&: `|@@; 4 | :@&!`..'!&@&@|. .;%%%%%!. :&&: `:;:` 5 | :$: ;&: :!. .;: '|;. .;|: '&#|` '$@: 6 | '%: .;;::$; :: :: .;' `;` '$; ;%` 7 | ;|. ;####&' :' ': :: :: |$!|||: !|. 8 | :%` |###$` '' `$####&' '' '' . '' ;####| :|` 9 | |%. :%` '' ;########|:' '. ;######%''. ;#%. ;|. 10 | '$%`'%: '' ':`$#####!:' .'. .|%$#####!'. !| ;%` 11 | '&! :` ;&&!.`' '' '$#####!:' .%;`%@; 12 | :%` :' ': :' `: ;$' 13 | |! `!' :;.`%####@; :; :: `%: 14 | '|' .;%%|!!%%: '&#######@: `!: :|' |! 15 | ;|. .;; ;@####%``!' .``. ;|. 16 | || :: . `:. :|` 17 | |; '' ... .'. '|' 18 | .|; `|%$|` : : :%|!` `|: 19 | `|: .'. : : '` `|; 20 | `|: .'. : ; '' `|: 21 | `|: :;.:; !; :: '|' 22 | `|: :|` 23 | `|: ;|. -------------------------------------------------------------------------------- /examples/spring-boot-grpc/greeter_client/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2015 gRPC authors. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | // Package main implements a client for Greeter service. 20 | package main 21 | 22 | import ( 23 | pb "github.com/go-spring/examples/spring-boot-grpc/helloworld" 24 | "github.com/go-spring/spring-boot" 25 | "github.com/go-spring/spring-web" 26 | _ "github.com/go-spring/starter-gin" 27 | _ "github.com/go-spring/starter-grpc/client" 28 | ) 29 | 30 | const ( 31 | defaultName = "world" 32 | ) 33 | 34 | func init() { 35 | SpringBoot.RegisterBean(new(GreeterClientController)).Init(func(c *GreeterClientController) { 36 | SpringBoot.GetMapping("/", c.index) 37 | }) 38 | } 39 | 40 | type GreeterClientController struct { 41 | GreeterClient pb.GreeterClient `autowire:""` 42 | } 43 | 44 | func (c *GreeterClientController) index(webCtx SpringWeb.WebContext) { 45 | r, err := c.GreeterClient.SayHello(webCtx.Request().Context(), &pb.HelloRequest{Name: defaultName}) 46 | SpringWeb.ERROR.Panic(err).When(err != nil) 47 | webCtx.String("Greeting: " + r.GetMessage()) 48 | } 49 | 50 | func init() { 51 | SpringBoot.RegisterGRpcClient(pb.NewGreeterClient, "greeter-client") 52 | } 53 | 54 | func main() { 55 | SpringBoot.SetProperty("grpc.endpoint.greeter-client.address", "127.0.0.1:50051") 56 | SpringBoot.SetProperty("spring.application.name", "GreeterClient") 57 | SpringBoot.RunApplication() 58 | } 59 | -------------------------------------------------------------------------------- /starter/starter-gorm/mysql/starter.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package StarterMySqlGorm 18 | 19 | import ( 20 | "database/sql" 21 | 22 | "github.com/go-spring/spring-core/gs" 23 | "github.com/go-spring/spring-core/gs/cond" 24 | "github.com/go-spring/spring-core/log" 25 | "github.com/go-spring/starter-core" 26 | "github.com/jinzhu/gorm" 27 | _ "github.com/jinzhu/gorm/dialects/mysql" 28 | ) 29 | 30 | func init() { 31 | 32 | // 如果没有 fromDB 名称的 *gorm.DB 对象则创建 fromConfig 名称的 *gorm.DB 对象 33 | gs.Provide(fromConfig). 34 | Name("mysql-gorm-from-config"). 35 | On(cond.OnMissingBean((*gorm.DB)(nil))). 36 | Destroy(closeDB) 37 | 38 | // 如果已经有 *sql.DB 对象则创建fromDB 名称的 *gorm.DB 对象 39 | gs.Provide(fromDB). 40 | Name("mysql-gorm-from-db"). 41 | On(cond.OnBean((*sql.DB)(nil))). 42 | Destroy(closeDB) 43 | } 44 | 45 | // fromConfig 从配置文件创建 *gorm.DB 客户端 46 | func fromConfig(config StarterCore.DBConfig) (*gorm.DB, error) { 47 | log.Info("open gorm mysql ", config.Url) 48 | return gorm.Open("mysql", config.Url) 49 | } 50 | 51 | // fromDB 从 *sql.DB 对象创建 *gorm.DB 客户端 52 | func fromDB(db *sql.DB) (*gorm.DB, error) { 53 | log.Info("open gorm mysql") 54 | return gorm.Open("mysql", db) 55 | } 56 | 57 | // closeDB 关闭 *gorm.DB 客户端 58 | func closeDB(db *gorm.DB) { 59 | log.Info("close gorm mysql") 60 | if err := db.Close(); err != nil { 61 | log.Error(err) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /starter/starter-go-redis/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= 3 | github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= 4 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10 h1:3wVokv0UL8xf5f99gDK5CXW7+AkBhMPzasfK10d5mIM= 5 | github.com/go-spring/spring-core v1.0.6-0.20210725091854-c92ef2937b10/go.mod h1:dlmlLZon5quLckxW7TkmY+OYuVUMB9ot28fxTL/3fYA= 6 | github.com/go-spring/spring-stl v0.0.0-20210724153121-8378c2594815 h1:9ez++onyyU2hyVoNOKwHoynIcvTxlvkF74LrDfyliLo= 7 | github.com/go-spring/spring-stl v0.0.0-20210724153121-8378c2594815/go.mod h1:RFkTfNPcNYbppU8krHBfGKjnvhR2Z0nQokpl5s0Te84= 8 | github.com/go-spring/starter-core v0.0.0-20210719133634-d661de98b7a9 h1:leSC43dySaQN/u2mcVSPdcFRe74xutRLt/nm50MGEQE= 9 | github.com/go-spring/starter-core v0.0.0-20210719133634-d661de98b7a9/go.mod h1:+LqWXkvuH96lX47uhz+NK6J7MY6bXtIELy/dkYjno80= 10 | github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= 11 | github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 12 | github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= 13 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 14 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 15 | github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= 16 | github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 17 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 18 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 19 | gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= 20 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 21 | -------------------------------------------------------------------------------- /examples/spring-boot-demo/mock/mock.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mock 18 | 19 | import ( 20 | "database/sql" 21 | "time" 22 | 23 | "github.com/DATA-DOG/go-sqlmock" 24 | "github.com/elliotchance/redismock" 25 | "github.com/go-redis/redis" 26 | "github.com/go-spring/spring-boot" 27 | "github.com/go-spring/spring-logger" 28 | ) 29 | 30 | func init() { 31 | 32 | SpringBoot.RegisterBeanFn(mockDB(func(mock sqlmock.Sqlmock) { 33 | mock.ExpectQuery("SELECT ENGINE FROM `ENGINES`").WillReturnRows( 34 | mock.NewRows([]string{"ENGINE"}).AddRow("sql-mock"), 35 | ) 36 | })) 37 | 38 | SpringBoot.RegisterBeanFn(mockRedis(func(mock *redismock.ClientMock) { 39 | mock.On("Set", "key", "ok", time.Second*10).Return(redis.NewStatusResult("", nil)) 40 | mock.On("Get", "key").Return(redis.NewStringResult("ok", nil)) 41 | })) 42 | } 43 | 44 | // mockDB 创建 Mock DB 45 | func mockDB(fn func(sqlmock.Sqlmock)) func() (*sql.DB, error) { 46 | return func() (*sql.DB, error) { 47 | SpringLogger.Info("create sqlmock db") 48 | db, mock, err := sqlmock.New() 49 | if err != nil { 50 | return nil, err 51 | } 52 | fn(mock) 53 | return db, nil 54 | } 55 | } 56 | 57 | // mockRedis 创建 Redis Mock 客户端 58 | func mockRedis(fn func(*redismock.ClientMock)) func() redis.Cmdable { 59 | return func() redis.Cmdable { 60 | mock := redismock.NewMock() 61 | fn(mock) 62 | return mock 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /examples/spring-boot-demo/app/my_runner.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package app 18 | 19 | import ( 20 | "errors" 21 | "time" 22 | 23 | "github.com/go-spring/spring-boot" 24 | "github.com/go-spring/spring-core" 25 | "github.com/go-spring/spring-logger" 26 | ) 27 | 28 | func init() { 29 | SpringBoot.RegisterBean(new(MyRunner)) 30 | } 31 | 32 | type MyRunner struct { 33 | _ SpringBoot.CommandLineRunner `export:""` 34 | } 35 | 36 | func (_ *MyRunner) Run(appCtx SpringBoot.ApplicationContext) { 37 | 38 | appCtx.SafeGoroutine(func() { 39 | SpringLogger.Trace("get all properties:") 40 | for k, v := range appCtx.GetProperties() { 41 | SpringLogger.Tracef("%v=%v", k, v) 42 | } 43 | SpringLogger.Info("exit right now in MyRunner::Run") 44 | }) 45 | 46 | fn := func(ctx SpringBoot.ApplicationContext, version string) { 47 | if version != "v0.0.1" { 48 | panic(errors.New("error")) 49 | } 50 | } 51 | _ = appCtx.Run(fn, "1:${version:=v0.0.1}").On(SpringCore.ConditionOnProfile("test")) 52 | 53 | appCtx.SafeGoroutine(func() { 54 | defer func() { SpringLogger.Info("exit after waiting in MyRunner::Run") }() 55 | 56 | ticker := time.NewTicker(10 * time.Millisecond) 57 | defer ticker.Stop() 58 | 59 | for { 60 | select { 61 | case <-appCtx.Context().Done(): 62 | return 63 | case <-ticker.C: 64 | SpringLogger.Info("MyRunner::Run") 65 | } 66 | } 67 | }) 68 | } 69 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guideline 2 | 3 | Thanks for considering to contribute this project. All issues and pull requests are highly appreciated. 4 | 5 | ## Pull Requests 6 | 7 | Before sending pull request to this project, please read and follow guidelines below. 8 | 9 | 1. Branch: We only accept pull request on `master` branch. 10 | 2. Coding style: Follow the coding style used in `go-spring`. 11 | 3. Commit message: Use English or Chinese and be aware of your spell. 12 | 4. Test: Make sure to test your code. 13 | 14 | NOTE: We assume all your contribution can be licensed under the [Apache License 2.0](https://github.com/go-spring/go-spring/blob/master/LICENSE). 15 | 16 | ## Issues 17 | 18 | We love clearly described issues. :) 19 | 20 | Following information can help us to resolve the issue faster. 21 | 22 | * Version. 23 | * Logs. 24 | * Screenshots. 25 | * Steps to reproduce the issue. 26 | 27 | ## 命名规则 28 | 29 | 明确且统一的命名规则有助于帮助我们形成一致的思考和设计模式,经过长期实践,Go-Spring 归纳出了几条颇为有益的命名规则,如下: 30 | 31 | * package 一般使用名词或者动词,不推荐使用形容词。 32 | * interface 一般使用名词或者形容词,动词短语也可。习惯上以 able、ible、er 等结尾。 33 | * struct 一般使用名词或者动词短语。 34 | * function 如果只返回 bool 值则以 is、has 等打头,否则必须使用动词打头。 35 | 36 | ### 常用变量名 37 | 38 | * 构造函数的变量名和结构体的字段名保持一致。 39 | * arg.Arg 一般情况下命名为 a 或者 arg。 40 | * cond.Condition 一般情况下命名为 c 或者 cond。 41 | * function 一般情况下命名为 f 或者 fn。 42 | * 返回结果一帮情况下命名为 result 或者 ret。 43 | * node 一般命名为 n。 44 | * element 一般命名为 e。 45 | 46 | ## 编程规约 47 | 48 | * 慎用嵌套(继承),避免暴露不必要的方法。 49 | * 限制每行长度最大不超过 100 个字符。 50 | * 放心使用选项模式。 51 | * 不对外直接暴露指针类型,使用值或者接口。 52 | * 包名不能和 Golang 标准库重名。 53 | * 注释里面的 bean 都是小写格式。 54 | * 函数内部调用的函数一般放在它的上方并且靠近它。 55 | * 几乎所有的 panic 都应该打印其调用栈。 56 | * 和包名同名的文件作为了解包的入口。 57 | 58 | ## 注释 59 | 60 | * 不要在注释上浪费太多文字,不要详细阐述你的思考,写清楚结论即可。 61 | * 具有返回值的函数注释应该以 return 开头。 62 | * 未导出函数尽量做到不使用注释也能知其意,而开放函数必须写注释。 63 | * 代码中一些很少使用的场景必须写清楚其背景! 64 | 65 | ## 优秀经验 66 | 67 | * 不用尽早抽象接口。 68 | * 异常判断今早返回。 69 | * 在使用的地方定义接口,而不是实现的地方。 70 | * 多数情况下不需要新增错误类型,只有深层嵌套的场景才需要。 71 | * 所有可变参数如果函数名不能提供有效信息都应该使用 Option 模式。 72 | 73 | ## 实战 74 | 75 | * 原型 bean 可以使用工厂模式进行注入,高并发场景下应该使用缓存以提高效率。 -------------------------------------------------------------------------------- /spring/spring-stl/apcu/apcu_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package apcu_test 18 | 19 | import ( 20 | "encoding/json" 21 | "testing" 22 | 23 | "github.com/go-spring/spring-stl/apcu" 24 | "github.com/go-spring/spring-stl/assert" 25 | ) 26 | 27 | func TestAPCU(t *testing.T) { 28 | 29 | type Resp struct { 30 | ErrNo int `json:"errno"` 31 | ErrMsg string `json:"errmsg"` 32 | } 33 | 34 | t.Run("", func(t *testing.T) { 35 | apcu.Store("success", `{"errno":200,"errmsg":"OK"}`) 36 | 37 | var resp *Resp 38 | load, err := apcu.Load("success", &resp) 39 | assert.Nil(t, err) 40 | assert.True(t, load) 41 | assert.Equal(t, resp, &Resp{200, "OK"}) 42 | 43 | load, err = apcu.Load("success", &resp) 44 | assert.Nil(t, err) 45 | assert.True(t, load) 46 | assert.Equal(t, resp, &Resp{200, "OK"}) 47 | }) 48 | 49 | apcu.Delete("success") 50 | 51 | t.Run("", func(t *testing.T) { 52 | apcu.Store("success", `{"errno":200,"errmsg":"OK"}`) 53 | 54 | var resp map[string]interface{} 55 | load, err := apcu.Load("success", &resp) 56 | assert.Nil(t, err) 57 | assert.True(t, load) 58 | assert.Equal(t, resp, map[string]interface{}{ 59 | "errno": json.Number("200"), "errmsg": "OK", 60 | }) 61 | 62 | load, err = apcu.Load("success", &resp) 63 | assert.Nil(t, err) 64 | assert.True(t, load) 65 | assert.Equal(t, resp, map[string]interface{}{ 66 | "errno": json.Number("200"), "errmsg": "OK", 67 | }) 68 | }) 69 | } 70 | -------------------------------------------------------------------------------- /starter/starter-rabbitmq/server/server.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // TODO 提取公共部分到 spring-rabbitmq 包 18 | package StarterRabbitMQServer 19 | 20 | import ( 21 | "github.com/go-spring/spring-core/gs" 22 | "github.com/streadway/amqp" 23 | ) 24 | 25 | func init() { 26 | gs.Provide(CreateServer).Name("amqp-server").Destroy(DestroyServer) 27 | } 28 | 29 | type AMQPServerConfig struct { 30 | URL string `value:"${amqp.server.url}"` 31 | QueueTopics []string `value:"${amqp.queue.topics}"` 32 | } 33 | 34 | type AMQPServer struct { 35 | Connection *amqp.Connection 36 | Channel *amqp.Channel 37 | } 38 | 39 | // CreateServer 创建 AMQPServer 对象,采用预先声明的方式避免运行时锁消耗 40 | func CreateServer(config AMQPServerConfig) (*AMQPServer, error) { 41 | 42 | conn, err := amqp.Dial(config.URL) 43 | if err != nil { 44 | return nil, err 45 | } 46 | 47 | ch, err := conn.Channel() 48 | if err != nil { 49 | return nil, err 50 | } 51 | 52 | for _, topic := range config.QueueTopics { 53 | _, err = ch.QueueDeclare( 54 | topic, // name 55 | false, // durable 56 | false, // delete when unused 57 | false, // exclusive 58 | false, // no-wait 59 | nil, // arguments 60 | ) 61 | if err != nil { 62 | return nil, err 63 | } 64 | } 65 | 66 | return &AMQPServer{conn, ch}, nil 67 | } 68 | 69 | // DestroyServer 销毁 AMQPServer 对象 70 | func DestroyServer(server *AMQPServer) { 71 | if server.Channel != nil { 72 | _ = server.Channel.Close() 73 | } 74 | if server.Connection != nil { 75 | _ = server.Connection.Close() 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /spring/spring-core/mq/message.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Package mq 提供了标准的消息队列接口,可以灵活适配各种 MQ 实现。 18 | package mq 19 | 20 | type Message interface { 21 | Topic() string 22 | ID() string 23 | Body() []byte 24 | Extra() map[string]string 25 | } 26 | 27 | type message struct { 28 | topic string // 消息主题 29 | id string // Key 30 | body []byte // Value 31 | extra map[string]string // 额外信息 32 | } 33 | 34 | // NewMessage 创建新的消息对象。 35 | func NewMessage() *message { 36 | return &message{} 37 | } 38 | 39 | // Topic 返回消息的主题。 40 | func (msg *message) Topic() string { 41 | return msg.topic 42 | } 43 | 44 | // WithTopic 设置消息的主题。 45 | func (msg *message) WithTopic(topic string) *message { 46 | msg.topic = topic 47 | return msg 48 | } 49 | 50 | // ID 返回消息的序号。 51 | func (msg *message) ID() string { 52 | return msg.id 53 | } 54 | 55 | // WithID 设置消息的序号。 56 | func (msg *message) WithID(id string) *message { 57 | msg.id = id 58 | return msg 59 | } 60 | 61 | // Body 返回消息的内容。 62 | func (msg *message) Body() []byte { 63 | return msg.body 64 | } 65 | 66 | // WithBody 设置消息的内容。 67 | func (msg *message) WithBody(body []byte) *message { 68 | msg.body = body 69 | return msg 70 | } 71 | 72 | // Extra 返回消息的额外信息。 73 | func (msg *message) Extra() map[string]string { 74 | return msg.extra 75 | } 76 | 77 | // WithExtra 为消息添加额外的信息。 78 | func (msg *message) WithExtra(key, value string) *message { 79 | if msg.extra == nil { 80 | msg.extra = make(map[string]string) 81 | } 82 | msg.extra[key] = value 83 | return msg 84 | } 85 | -------------------------------------------------------------------------------- /spring/spring-stl/util/value.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "reflect" 21 | "runtime" 22 | "strings" 23 | "unsafe" 24 | ) 25 | 26 | const ( 27 | flagStickyRO = 1 << 5 28 | flagEmbedRO = 1 << 6 29 | flagRO = flagStickyRO | flagEmbedRO 30 | ) 31 | 32 | // PatchValue 开放 v 的私有字段,返回修改后的副本。 33 | func PatchValue(v reflect.Value) reflect.Value { 34 | rv := reflect.ValueOf(&v) 35 | flag := rv.Elem().FieldByName("flag") 36 | ptrFlag := (*uintptr)(unsafe.Pointer(flag.UnsafeAddr())) 37 | *ptrFlag = *ptrFlag &^ flagRO 38 | return v 39 | } 40 | 41 | // Indirect 解除 Type 所有层级的指针。 42 | func Indirect(t reflect.Type) reflect.Type { 43 | if t.Kind() != reflect.Ptr { 44 | return t 45 | } 46 | return t.Elem() 47 | } 48 | 49 | // FileLine 获取函数所在文件、行数以及函数名 50 | func FileLine(fn interface{}) (file string, line int, fnName string) { 51 | 52 | fnPtr := reflect.ValueOf(fn).Pointer() 53 | fnInfo := runtime.FuncForPC(fnPtr) 54 | file, line = fnInfo.FileLine(fnPtr) 55 | 56 | s := fnInfo.Name() 57 | if ss := strings.Split(s, "/"); len(ss) > 0 { 58 | s = ss[len(ss)-1] 59 | i := strings.Index(s, ".") 60 | s = s[i+1:] 61 | } 62 | 63 | // 带 Receiver 的方法有 -fm 标记 64 | s = strings.TrimRight(s, "-fm") 65 | return file, line, s 66 | } 67 | 68 | // IsNil 返回 reflect.Value 的值是否为 nil,比原生方法更安全 69 | func IsNil(v reflect.Value) bool { 70 | switch v.Kind() { 71 | case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer: 72 | return v.IsNil() 73 | } 74 | return false 75 | } 76 | -------------------------------------------------------------------------------- /examples/spring-boot-demo/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "os" 21 | 22 | _ "github.com/go-spring/examples/spring-boot-demo/api" 23 | _ "github.com/go-spring/examples/spring-boot-demo/app" 24 | _ "github.com/go-spring/examples/spring-boot-demo/extension" 25 | _ "github.com/go-spring/examples/spring-boot-demo/filter" 26 | _ "github.com/go-spring/examples/spring-boot-demo/mock" 27 | _ "github.com/go-spring/examples/spring-boot-demo/server" 28 | "github.com/go-spring/spring-boot" 29 | _ "github.com/go-spring/starter-go-redis" 30 | _ "github.com/go-spring/starter-gorm/mysql" 31 | ) 32 | 33 | func init() { 34 | // SpringLogger.SetLogger(&SpringLogger.Console{}) 35 | } 36 | 37 | func main() { 38 | 39 | // 配置文件里面也指定了 spring.profile 的值 40 | // _ = os.Setenv(SpringBoot.SpringProfile, "test") 41 | 42 | // 过滤系统环境变量 43 | SpringBoot.ExpectSysProperties("GOPATH") 44 | 45 | // 设置过滤器是否启用 46 | SpringBoot.SetProperty("key_auth", false) 47 | 48 | SpringBoot.SetProperty("db.url", "root:root@/information_schema?charset=utf8&parseTime=True&loc=Local") 49 | 50 | dir, _ := os.Getwd() 51 | SpringBoot.SetProperty("static.root", dir) 52 | 53 | configLocations := []string{ 54 | "config/", "k8s:config/config-map.yaml", 55 | } 56 | 57 | // 可以通过 API 设置 Banner 字符串 58 | // SpringBoot.SetBanner("go-spring-demo@github") 59 | 60 | // 关闭 Banner 功能 61 | // SpringBoot.SetBannerMode(SpringBoot.BannerModeOff) 62 | 63 | // 等效 SpringBoot.RunApplication(configLocations...) 64 | SpringBoot.NewApplication().Run(configLocations...) 65 | } 66 | -------------------------------------------------------------------------------- /spring/spring-core/gs/banner.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package gs 18 | 19 | import ( 20 | "fmt" 21 | "strings" 22 | 23 | "github.com/go-spring/spring-core/gs/environ" 24 | ) 25 | 26 | const DefaultBanner = ` 27 | _______ _______ _______ _______ _______ _________ _ _______ 28 | ( ____ \( ___ ) ( ____ \( ____ )( ____ )\__ __/( ( /|( ____ \ 29 | | ( \/| ( ) | | ( \/| ( )|| ( )| ) ( | \ ( || ( \/ 30 | | | | | | | _____ | (_____ | (____)|| (____)| | | | \ | || | 31 | | | ____ | | | |(_____)(_____ )| _____)| __) | | | (\ \) || | ____ 32 | | | \_ )| | | | ) || ( | (\ ( | | | | \ || | \_ ) 33 | | (___) || (___) | /\____) || ) | ) \ \_____) (___| ) \ || (___) | 34 | (_______)(_______) \_______)|/ |/ \__/\_______/|/ )_)(_______) 35 | ` 36 | 37 | // PrintBanner 打印 banner 到控制台 38 | func PrintBanner(banner string) { 39 | 40 | if banner[0] != '\n' { 41 | fmt.Println() 42 | } 43 | 44 | maxLength := 0 45 | for _, s := range strings.Split(banner, "\n") { 46 | fmt.Printf("\x1b[36m%s\x1b[0m\n", s) // CYAN 47 | if len(s) > maxLength { 48 | maxLength = len(s) 49 | } 50 | } 51 | 52 | if banner[len(banner)-1] != '\n' { 53 | fmt.Println() 54 | } 55 | 56 | var padding []byte 57 | if n := (maxLength - len(environ.Version)) / 2; n > 0 { 58 | padding = make([]byte, n) 59 | for i := range padding { 60 | padding[i] = ' ' 61 | } 62 | } 63 | fmt.Println(string(padding) + environ.Version + "\n") 64 | } 65 | -------------------------------------------------------------------------------- /spring/spring-core/mq/consumer.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mq 18 | 19 | import ( 20 | "context" 21 | "errors" 22 | "reflect" 23 | 24 | "github.com/go-spring/spring-stl/json" 25 | "github.com/go-spring/spring-stl/util" 26 | ) 27 | 28 | // Consumer 消息消费者。 29 | type Consumer interface { 30 | Topics() []string 31 | Consume(ctx context.Context, msg Message) error 32 | } 33 | 34 | // consumer Bind 方式的消息消费者。 35 | type consumer struct { 36 | 37 | // 消息主题列表。 38 | topics []string 39 | 40 | fn interface{} 41 | t reflect.Type 42 | v reflect.Value 43 | e reflect.Type 44 | } 45 | 46 | func (c *consumer) Topics() []string { 47 | return c.topics 48 | } 49 | 50 | func (c *consumer) Consume(ctx context.Context, msg Message) error { 51 | e := reflect.New(c.e.Elem()) 52 | err := json.Unmarshal(msg.Body(), e.Interface()) 53 | if err != nil { 54 | return err 55 | } 56 | out := c.v.Call([]reflect.Value{reflect.ValueOf(ctx), e}) 57 | if err = out[0].Interface().(error); err != nil { 58 | return err 59 | } 60 | return nil 61 | } 62 | 63 | func validBindFn(t reflect.Type) bool { 64 | return util.IsFuncType(t) && 65 | util.ReturnOnlyError(t) && 66 | t.NumIn() == 2 && 67 | util.IsContextType(t.In(0)) && 68 | util.IsStructPtr(t.In(1)) 69 | } 70 | 71 | // Bind 创建 Bind 方式的消费者。 72 | func Bind(fn interface{}, topics ...string) *consumer { 73 | if t := reflect.TypeOf(fn); validBindFn(t) { 74 | return &consumer{ 75 | topics: topics, 76 | fn: fn, 77 | t: t, 78 | v: reflect.ValueOf(fn), 79 | e: t.In(1), 80 | } 81 | } 82 | panic(errors.New("fn should be func(ctx,*struct)error")) 83 | } 84 | -------------------------------------------------------------------------------- /examples/spring-web-filter/abort/abort_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package abort_test 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "net/http" 23 | "testing" 24 | "time" 25 | 26 | "github.com/go-spring/examples/spring-boot-filter/abort" 27 | "github.com/go-spring/spring-echo" 28 | "github.com/go-spring/spring-gin" 29 | "github.com/go-spring/spring-utils" 30 | "github.com/go-spring/spring-web" 31 | "github.com/magiconair/properties/assert" 32 | ) 33 | 34 | func testAbort(t *testing.T, fn func() SpringWeb.WebContainer, 35 | testAbort bool, expect []string) { 36 | 37 | c := fn() 38 | s := &abort.StringArray{} 39 | c.AddFilter(abort.NewPushFilter(1, false, s)) 40 | c.AddFilter(abort.NewPushFilter(2, testAbort, s)) 41 | c.GetMapping("/", func(webCtx SpringWeb.WebContext) { 42 | webCtx.String("hello world") 43 | }) 44 | 45 | c.Start() 46 | time.Sleep(10 * time.Millisecond) 47 | 48 | resp, err := http.Get("http://localhost:8080/") 49 | SpringUtils.Panic(err).When(err != nil) 50 | fmt.Println(resp.Status, s.Data) 51 | assert.Equal(t, s.Data, expect) 52 | 53 | c.Stop(context.Background()) 54 | } 55 | 56 | func test(t *testing.T, fn func() SpringWeb.WebContainer) { 57 | testAbort(t, fn, false, []string{"1", "2", "2", "1"}) 58 | testAbort(t, fn, true, []string{"1"}) 59 | } 60 | 61 | func TestFilterAbort(t *testing.T) { 62 | 63 | // 测试 gin 服务器 64 | test(t, func() SpringWeb.WebContainer { 65 | return SpringGin.NewContainer(SpringWeb.ContainerConfig{Port: 8080}) 66 | }) 67 | 68 | // 测试 echo 服务器 69 | test(t, func() SpringWeb.WebContainer { 70 | return SpringEcho.NewContainer(SpringWeb.ContainerConfig{Port: 8080}) 71 | }) 72 | } 73 | -------------------------------------------------------------------------------- /spring/spring-stl/assert/assert_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package assert_test 18 | 19 | import ( 20 | "errors" 21 | "testing" 22 | 23 | "github.com/go-spring/spring-stl/assert" 24 | ) 25 | 26 | func TestCheck(t *testing.T) { 27 | 28 | var r struct { 29 | True bool 30 | False bool 31 | Nil interface{} 32 | } 33 | 34 | err := assert.Check(assert.Cases{ 35 | {r.True, "r.True want true but is false"}, 36 | {!r.False, "r.False want false but is true"}, 37 | {r.Nil == nil, "r.Nil want nil but not nil"}, 38 | }) 39 | 40 | assert.Error(t, err, "r.True want true but is false") 41 | } 42 | 43 | func checkFailed(t *testing.T) { 44 | if t.Failed() { 45 | t.Fatalf("failed but expect not failed") 46 | } 47 | } 48 | 49 | func TestTrue(t *testing.T) { 50 | assert.True(t, true) 51 | checkFailed(t) 52 | } 53 | 54 | func TestFalse(t *testing.T) { 55 | assert.False(t, false) 56 | checkFailed(t) 57 | } 58 | 59 | func TestNil(t *testing.T) { 60 | assert.Nil(t, nil) 61 | checkFailed(t) 62 | } 63 | 64 | func TestNotNil(t *testing.T) { 65 | assert.NotNil(t, new(int)) 66 | checkFailed(t) 67 | } 68 | 69 | func TestEqual(t *testing.T) { 70 | assert.Equal(t, 0, 0) 71 | checkFailed(t) 72 | } 73 | 74 | func TestNotEqual(t *testing.T) { 75 | assert.NotEqual(t, 1, 0) 76 | checkFailed(t) 77 | } 78 | 79 | func TestPanic(t *testing.T) { 80 | assert.Panic(t, func() { panic("error") }, "error") 81 | checkFailed(t) 82 | } 83 | 84 | func TestMatches(t *testing.T) { 85 | assert.Matches(t, "this is an error", "this is an error") 86 | checkFailed(t) 87 | } 88 | 89 | func TestError(t *testing.T) { 90 | assert.Error(t, errors.New("this is an error"), "an error") 91 | checkFailed(t) 92 | } 93 | -------------------------------------------------------------------------------- /examples/spring-boot-demo/server/server.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package server 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/go-spring/examples/spring-boot-demo/filter" 23 | "github.com/go-spring/spring-boot" 24 | "github.com/go-spring/spring-echo" 25 | "github.com/go-spring/spring-web" 26 | "github.com/go-spring/starter-web" 27 | ) 28 | 29 | func init() { 30 | 31 | // 测试 Config 系列函数的功能 32 | { 33 | SpringBoot.ConfigWithName("config_f2", func(filter *filter.NumberFilter) { 34 | fmt.Println("NumberFilter:", filter.N) 35 | }, "f2").ConditionOnPropertyValue("f2.enable", true) 36 | 37 | SpringBoot.ConfigWithName("config_f5", func(filter *filter.NumberFilter, appName string) { 38 | fmt.Println("NumberFilter:", filter.N, "appName:", appName) 39 | }, "f5", "${spring.application.name}").After("config_f2") 40 | 41 | SpringBoot.Config(func(filter *filter.NumberFilter) { 42 | fmt.Println("NumberFilter:", filter.N) 43 | }, "f7").Before("config_f2").ConditionOnPropertyValue("f7.enable", true) 44 | } 45 | 46 | SpringBoot.RegisterBeanFn(func(config StarterWeb.WebServerConfig) SpringWeb.WebContainer { 47 | cfg := SpringWeb.ContainerConfig{Port: config.Port} 48 | c := SpringEcho.NewContainer(cfg) 49 | c.AddFilter(SpringBoot.FilterBean("container")) 50 | c.Swagger().WithDescription("spring boot test") 51 | return c 52 | }) 53 | 54 | //SpringBoot.RegisterBeanFn(func() *SpringWeb.WebServer { 55 | // return SpringWeb.NewWebServer().AddFilter( 56 | // SpringBoot.FilterBean("server"), 57 | // SpringBoot.FilterBean((*StaticFilter.StaticFilter)(nil)), 58 | // ) 59 | //}) 60 | // 61 | //SpringBoot.RegisterFilterFn(StaticFilter.New, "${static.root:=/}", "${static.url-prefix:=/static}") 62 | } 63 | -------------------------------------------------------------------------------- /spring/spring-stl/util/value_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package util_test 18 | 19 | import ( 20 | "fmt" 21 | "testing" 22 | 23 | "github.com/go-spring/spring-stl/util" 24 | "github.com/go-spring/spring-stl/util/testdata" 25 | ) 26 | 27 | func fnNoArgs() {} 28 | 29 | func fnWithArgs(i int) {} 30 | 31 | type receiver struct{} 32 | 33 | func (r receiver) fnNoArgs() {} 34 | 35 | func (r receiver) fnWithArgs(i int) {} 36 | 37 | func (r *receiver) ptrFnNoArgs() {} 38 | 39 | func (r *receiver) ptrFnWithArgs(i int) {} 40 | 41 | func TestFileLine(t *testing.T) { 42 | 43 | fmt.Println(util.FileLine(fnNoArgs)) 44 | fmt.Println(util.FileLine(fnWithArgs)) 45 | fmt.Println(util.FileLine(receiver{}.fnNoArgs)) 46 | fmt.Println(util.FileLine(receiver{}.fnWithArgs)) 47 | fmt.Println(util.FileLine((&receiver{}).ptrFnNoArgs)) 48 | fmt.Println(util.FileLine((&receiver{}).ptrFnWithArgs)) 49 | fmt.Println(util.FileLine(receiver.fnNoArgs)) 50 | fmt.Println(util.FileLine(receiver.fnWithArgs)) 51 | fmt.Println(util.FileLine((*receiver).ptrFnNoArgs)) 52 | fmt.Println(util.FileLine((*receiver).ptrFnWithArgs)) 53 | 54 | fmt.Println(util.FileLine(testdata.FnNoArgs)) 55 | fmt.Println(util.FileLine(testdata.FnWithArgs)) 56 | fmt.Println(util.FileLine(testdata.Receiver{}.FnNoArgs)) 57 | fmt.Println(util.FileLine(testdata.Receiver{}.FnWithArgs)) 58 | fmt.Println(util.FileLine((&testdata.Receiver{}).PtrFnNoArgs)) 59 | fmt.Println(util.FileLine((&testdata.Receiver{}).PtrFnWithArgs)) 60 | fmt.Println(util.FileLine(testdata.Receiver.FnNoArgs)) 61 | fmt.Println(util.FileLine(testdata.Receiver.FnWithArgs)) 62 | fmt.Println(util.FileLine((*testdata.Receiver).PtrFnNoArgs)) 63 | fmt.Println(util.FileLine((*testdata.Receiver).PtrFnWithArgs)) 64 | } 65 | -------------------------------------------------------------------------------- /examples/spring-web-testcases/spring-web-rpc_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package testcases_test 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "io/ioutil" 23 | "net/http" 24 | "testing" 25 | "time" 26 | 27 | "github.com/go-spring/examples/testcases" 28 | "github.com/go-spring/spring-echo" 29 | "github.com/go-spring/spring-gin" 30 | "github.com/go-spring/spring-web" 31 | "github.com/magiconair/properties/assert" 32 | ) 33 | 34 | func TestRpc(t *testing.T) { 35 | 36 | SpringWeb.Validator = SpringWeb.NewDefaultValidator() 37 | defer func() { SpringWeb.Validator = nil }() 38 | 39 | testContainer := func(c SpringWeb.WebContainer) { 40 | 41 | server := SpringWeb.NewWebServer() 42 | server.AddContainer(c) 43 | 44 | rc := new(testcases.RpcService) 45 | c.GetBinding("/echo", rc.Echo) 46 | 47 | // 启动 web 服务器 48 | server.Start() 49 | 50 | time.Sleep(time.Millisecond * 100) 51 | fmt.Println() 52 | 53 | { 54 | resp, _ := http.Get("http://127.0.0.1:9090/echo?str=") 55 | body, _ := ioutil.ReadAll(resp.Body) 56 | assert.Equal(t, string(body), `Key: 'EchoRequest.Str' Error:Field validation for 'Str' failed on the 'required' tag`) 57 | } 58 | 59 | for i := 0; i < 20; i++ { // 多次测试 echo 和 gin 的性能确实差不多 60 | resp, _ := http.Get("http://127.0.0.1:9090/echo?str=echo") 61 | body, _ := ioutil.ReadAll(resp.Body) 62 | assert.Equal(t, string(body), `{"code":200,"msg":"SUCCESS","data":{"echo":"echo echo"}}`) 63 | } 64 | 65 | server.Stop(context.TODO()) 66 | 67 | time.Sleep(50 * time.Millisecond) 68 | } 69 | 70 | cfg := SpringWeb.ContainerConfig{Port: 9090} 71 | 72 | t.Run("echo container", func(t *testing.T) { 73 | testContainer(SpringEcho.NewContainer(cfg)) 74 | }) 75 | 76 | t.Run("gin container", func(t *testing.T) { 77 | testContainer(SpringGin.NewContainer(cfg)) 78 | }) 79 | } 80 | -------------------------------------------------------------------------------- /spring/spring-stl/json/json.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Package json 提供封装其他 json 序列化框架的接口。 18 | package json 19 | 20 | import ( 21 | "bytes" 22 | "encoding/json" 23 | "errors" 24 | ) 25 | 26 | // MarshalFunc 定义 Marshal 函数原型。 27 | type MarshalFunc func(v interface{}) ([]byte, error) 28 | 29 | // UnmarshalFunc 定义 Unmarshal 函数原型。 30 | type UnmarshalFunc func(data []byte, v interface{}) error 31 | 32 | var ( 33 | marshal MarshalFunc 34 | unmarshal UnmarshalFunc 35 | ) 36 | 37 | // Init 自定义 Marshal 和 Unmarshal 函数,为了防止在一个项目中存在多个 38 | // json 序列化框架,该函数只能在项目 main 函数执行前的 init 阶段设置一次。 39 | func Init(m MarshalFunc, u UnmarshalFunc) { 40 | if m == nil || u == nil { 41 | panic(errors.New("invalid param")) 42 | } 43 | if marshal != nil { 44 | panic(errors.New("marshal not nil")) 45 | } 46 | marshal = m 47 | unmarshal = u 48 | } 49 | 50 | // ToString 将对象序列化为 Json 字符串,错误信息以字符串形式返回。 51 | func ToString(i interface{}) string { 52 | b, err := Marshal(i) 53 | if err != nil { 54 | return err.Error() 55 | } 56 | return string(b) 57 | } 58 | 59 | // Marshal 序列化 json 数据。 60 | func Marshal(v interface{}) ([]byte, error) { 61 | if marshal != nil { 62 | return marshal(v) 63 | } 64 | return json.Marshal(v) 65 | } 66 | 67 | // MarshalIndent 序列化 json 数据并对结果进行美化。 68 | func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { 69 | b, err := Marshal(v) 70 | if err != nil { 71 | return nil, err 72 | } 73 | var buf bytes.Buffer 74 | err = json.Indent(&buf, b, prefix, indent) 75 | if err != nil { 76 | return nil, err 77 | } 78 | return buf.Bytes(), nil 79 | } 80 | 81 | // Unmarshal 反序列化 json 对象。 82 | func Unmarshal(data []byte, v interface{}) error { 83 | if unmarshal != nil { 84 | return unmarshal(data, v) 85 | } 86 | d := json.NewDecoder(bytes.NewReader(data)) 87 | d.UseNumber() 88 | return d.Decode(v) 89 | } 90 | -------------------------------------------------------------------------------- /spring/spring-stl/util/sort.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "container/list" 21 | "errors" 22 | 23 | "github.com/go-spring/spring-stl/contain" 24 | ) 25 | 26 | // GetBeforeItems 获取 sorting 中排在 current 前面的元素 27 | type GetBeforeItems func(sorting *list.List, current interface{}) *list.List 28 | 29 | // TripleSort 三路排序 30 | func TripleSort(sorting *list.List, fn GetBeforeItems) *list.List { 31 | 32 | toSort := list.New() // 待排序列表 33 | sorted := list.New() // 已排序列表 34 | processing := list.New() // 正在处理列表 35 | 36 | toSort.PushBackList(sorting) 37 | 38 | for toSort.Len() > 0 { // 递归选出依赖链条最前端的元素 39 | tripleSortByAfter(sorting, toSort, sorted, processing, nil, fn) 40 | } 41 | return sorted 42 | } 43 | 44 | // tripleSortByAfter 递归选出依赖链条最前端的元素 45 | func tripleSortByAfter(sorting *list.List, toSort *list.List, sorted *list.List, 46 | processing *list.List, current interface{}, fn GetBeforeItems) { 47 | 48 | if current == nil { 49 | current = toSort.Remove(toSort.Front()) 50 | } 51 | 52 | // 将当前元素标记为正在处理 53 | processing.PushBack(current) 54 | 55 | // 获取排在当前元素前面的列表项,然后依次对它们进行排序 56 | for e := fn(sorting, current).Front(); e != nil; e = e.Next() { 57 | c := e.Value 58 | 59 | // 自己不可能是自己前面的元素,除非出现了循环依赖,因此抛出 Panic 60 | if contain.List(processing, c) != nil { 61 | panic(errors.New("found sorting cycle")) 62 | } 63 | 64 | inSorted := contain.List(sorted, c) != nil 65 | inToSort := contain.List(toSort, c) != nil 66 | 67 | if !inSorted && inToSort { // 如果是待排元素则对其进行排序 68 | tripleSortByAfter(sorting, toSort, sorted, processing, c, fn) 69 | } 70 | } 71 | 72 | if e := contain.List(processing, current); e != nil { 73 | processing.Remove(e) 74 | } 75 | 76 | if e := contain.List(toSort, current); e != nil { 77 | toSort.Remove(e) 78 | } 79 | 80 | // 将当前元素标记为已完成 81 | sorted.PushBack(current) 82 | } 83 | -------------------------------------------------------------------------------- /spring/spring-core/web/rpc-result_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package web_test 18 | 19 | import ( 20 | "errors" 21 | "testing" 22 | 23 | "github.com/go-spring/spring-core/web" 24 | "github.com/go-spring/spring-stl/assert" 25 | ) 26 | 27 | func TestRpcError(t *testing.T) { 28 | err := errors.New("this is an error") 29 | 30 | r1 := web.ERROR.Error(err) 31 | assert.Equal(t, r1, &web.RpcResult{ 32 | ErrorCode: web.ErrorCode(web.ERROR), 33 | Err: "/Users/didi/GitHub/go-spring/go-spring/spring/spring-core/web/rpc-result_test.go:30: this is an error", 34 | }) 35 | 36 | r2 := web.ERROR.ErrorWithData(err, "error_with_data") 37 | assert.Equal(t, r2, &web.RpcResult{ 38 | ErrorCode: web.ErrorCode(web.ERROR), 39 | Err: "/Users/didi/GitHub/go-spring/go-spring/spring/spring-core/web/rpc-result_test.go:36: this is an error", 40 | Data: "error_with_data", 41 | }) 42 | 43 | func() { 44 | defer func() { 45 | assert.Equal(t, recover(), &web.RpcResult{ 46 | ErrorCode: web.ErrorCode(web.ERROR), 47 | Err: "/Users/didi/GitHub/go-spring/go-spring/spring/spring-core/web/rpc-result_test.go:50: this is an error", 48 | }) 49 | }() 50 | web.ERROR.Panic(err).When(err != nil) 51 | }() 52 | 53 | func() { 54 | defer func() { 55 | assert.Equal(t, recover(), &web.RpcResult{ 56 | ErrorCode: web.ErrorCode(web.ERROR), 57 | Err: "/Users/didi/GitHub/go-spring/go-spring/spring/spring-core/web/rpc-result_test.go:60: this is an error", 58 | }) 59 | }() 60 | web.ERROR.Panicf(err.Error()).When(true) 61 | }() 62 | 63 | func() { 64 | defer func() { 65 | assert.Equal(t, recover(), &web.RpcResult{ 66 | ErrorCode: web.ErrorCode(web.ERROR), 67 | Err: "/Users/didi/GitHub/go-spring/go-spring/spring/spring-core/web/rpc-result_test.go:70: this is an error", 68 | }) 69 | }() 70 | web.ERROR.PanicImmediately(err) 71 | }() 72 | } 73 | -------------------------------------------------------------------------------- /spring/spring-swag/redoc/redoc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package redoc 18 | 19 | import ( 20 | "html/template" 21 | 22 | "github.com/go-spring/spring-core/web" 23 | "github.com/swaggo/http-swagger" 24 | ) 25 | 26 | func init() { 27 | web.RegisterSwaggerHandler(func(mapping web.Router, doc string) { 28 | hSwagger := httpSwagger.Handler(httpSwagger.URL("/swagger/doc.json")) 29 | 30 | // 注册 swagger-ui 和 doc.json 接口 31 | mapping.GetMapping("/swagger/*", func(webCtx web.Context) { 32 | if webCtx.PathParam("*") == "doc.json" { 33 | webCtx.Blob(web.MIMEApplicationJSONCharsetUTF8, []byte(doc)) 34 | } else { 35 | hSwagger(webCtx.ResponseWriter(), webCtx.Request()) 36 | } 37 | }) 38 | 39 | // 注册 redoc 接口 40 | mapping.GetMapping("/redoc", ReDoc) 41 | }) 42 | } 43 | 44 | // ReDoc redoc 响应函数 45 | func ReDoc(ctx web.Context) { 46 | 47 | index, err := template.New("redoc.html").Parse(redocTempl) 48 | if err != nil { 49 | panic(err) 50 | } 51 | 52 | // 不确定 Execute 是否线程安全,官方文档表示也许是线程安全的,谁知道呢 53 | _ = index.Execute(ctx.ResponseWriter(), map[string]interface{}{ 54 | "URL": "/swagger/doc.json", 55 | }) 56 | } 57 | 58 | const redocTempl = ` 59 | 60 | 61 | 62 | ReDoc 63 | 64 | 65 | 66 | 67 | 68 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | ` 84 | -------------------------------------------------------------------------------- /starter/starter-rabbitmq/consumer/consumer.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package StarterRabbitMQConsumer 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/go-spring/spring-core/gs" 23 | "github.com/go-spring/spring-core/log" 24 | "github.com/go-spring/spring-core/mq" 25 | "github.com/go-spring/spring-stl/util" 26 | "github.com/go-spring/starter-rabbitmq/server" 27 | ) 28 | 29 | func init() { 30 | gs.Object(new(Starter)).Name("amqp-consumer-starter").Export(gs.AppEvent) 31 | } 32 | 33 | type Starter struct { 34 | Server *StarterRabbitMQServer.AMQPServer `autowire:""` 35 | } 36 | 37 | func (starter *Starter) OnStartApp(ctx gs.AppContext) { 38 | 39 | cMap := map[string][]mq.Consumer{} 40 | { 41 | var consumers []mq.Consumer 42 | err := ctx.Get(&consumers) 43 | util.Panic(err).When(err != nil) 44 | 45 | var bindConsumers *gs.Consumers 46 | err = ctx.Get(&bindConsumers) 47 | util.Panic(err).When(err != nil) 48 | 49 | bindConsumers.ForEach(func(c mq.Consumer) { 50 | consumers = append(consumers, c) 51 | }) 52 | 53 | for _, consumer := range consumers { 54 | for _, topic := range consumer.Topics() { 55 | cMap[topic] = append(cMap[topic], consumer) 56 | } 57 | } 58 | } 59 | 60 | go func() { 61 | // TODO 使用 goroutine 池提高消费速率 62 | for topic, consumers := range cMap { 63 | delivery, err := starter.Server.Channel.Consume( 64 | topic, // queue 65 | "", // consumer 66 | true, // auto-ack 67 | false, // exclusive 68 | false, // no-local 69 | false, // no-wait 70 | nil, // args 71 | ) 72 | if err != nil { 73 | log.Error(err) 74 | continue 75 | } 76 | d := <-delivery 77 | msg := mq.NewMessage().WithBody(d.Body).WithTopic(topic) 78 | for _, c := range consumers { 79 | c.Consume(context.TODO(), msg) 80 | } 81 | } 82 | }() 83 | } 84 | 85 | func (starter *Starter) OnStopApp(ctx gs.AppContext) { 86 | 87 | } 88 | -------------------------------------------------------------------------------- /spring/spring-core/web/rpc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package web 18 | 19 | import ( 20 | "errors" 21 | "reflect" 22 | 23 | "github.com/go-spring/spring-stl/util" 24 | ) 25 | 26 | // bindHandler BIND 形式的 Web 处理接口 27 | type bindHandler struct { 28 | fn interface{} 29 | fnType reflect.Type 30 | fnValue reflect.Value 31 | bindType reflect.Type 32 | } 33 | 34 | func (b *bindHandler) Invoke(ctx Context) { 35 | RpcInvoke(ctx, b.call) 36 | } 37 | 38 | func (b *bindHandler) call(ctx Context) interface{} { 39 | 40 | // 反射创建需要绑定请求参数 41 | bindVal := reflect.New(b.bindType.Elem()) 42 | if err := ctx.Bind(bindVal.Interface()); err != nil { 43 | panic(err) 44 | } 45 | 46 | // 执行处理函数,并返回结果 47 | ctxVal := reflect.ValueOf(ctx.Request().Context()) 48 | in := []reflect.Value{ctxVal, bindVal} 49 | return b.fnValue.Call(in)[0].Interface() 50 | } 51 | 52 | func (b *bindHandler) FileLine() (file string, line int, fnName string) { 53 | return util.FileLine(b.fn) 54 | } 55 | 56 | func validBindFn(fnType reflect.Type) bool { 57 | 58 | // 必须是函数,必须有两个入参,必须有一个返回值 59 | if fnType.Kind() != reflect.Func || fnType.NumIn() != 2 || fnType.NumOut() != 1 { 60 | return false 61 | } 62 | 63 | // 第一个入参必须是 context.Context 类型 64 | if !util.IsContextType(fnType.In(0)) { 65 | return false 66 | } 67 | 68 | req := fnType.In(1) // 第二个入参必须是结构体指针 69 | return req.Kind() == reflect.Ptr && req.Elem().Kind() == reflect.Struct 70 | } 71 | 72 | // BIND 转换成 BIND 形式的 Web 处理接口 73 | func BIND(fn interface{}) Handler { 74 | if fnType := reflect.TypeOf(fn); validBindFn(fnType) { 75 | return &bindHandler{ 76 | fn: fn, 77 | fnType: fnType, 78 | fnValue: reflect.ValueOf(fn), 79 | bindType: fnType.In(1), 80 | } 81 | } 82 | panic(errors.New("fn should be func(context.Context, *struct})anything")) 83 | } 84 | 85 | // RpcInvoke 可自定义的 rpc 执行函数 86 | var RpcInvoke = func(ctx Context, fn func(Context) interface{}) { 87 | ctx.JSON(fn(ctx)) 88 | } 89 | -------------------------------------------------------------------------------- /spring/spring-core/web/constants.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package web 18 | 19 | const ( 20 | HeaderContentDisposition = "Content-Disposition" 21 | HeaderContentType = "Content-Type" 22 | HeaderXForwardedProto = "X-Forwarded-Proto" 23 | HeaderXForwardedProtocol = "X-Forwarded-Protocol" 24 | HeaderXForwardedSsl = "X-Forwarded-Ssl" 25 | HeaderXUrlScheme = "X-Url-Scheme" 26 | 27 | CharsetUTF8 = "charset=UTF-8" 28 | 29 | MIMEApplicationJSON = "application/json" 30 | MIMEApplicationJSONCharsetUTF8 = MIMEApplicationJSON + "; " + CharsetUTF8 31 | MIMEApplicationJavaScript = "application/javascript" 32 | MIMEApplicationJavaScriptCharsetUTF8 = MIMEApplicationJavaScript + "; " + CharsetUTF8 33 | MIMEApplicationXML = "application/xml" 34 | MIMEApplicationXMLCharsetUTF8 = MIMEApplicationXML + "; " + CharsetUTF8 35 | MIMETextXML = "text/xml" 36 | MIMETextXMLCharsetUTF8 = MIMETextXML + "; " + CharsetUTF8 37 | MIMEApplicationForm = "application/x-www-form-urlencoded" 38 | MIMEApplicationProtobuf = "application/protobuf" 39 | MIMEApplicationMsgpack = "application/msgpack" 40 | MIMETextHTML = "text/html" 41 | MIMETextHTMLCharsetUTF8 = MIMETextHTML + "; " + CharsetUTF8 42 | MIMETextPlain = "text/plain" 43 | MIMETextPlainCharsetUTF8 = MIMETextPlain + "; " + CharsetUTF8 44 | MIMEMultipartForm = "multipart/form-data" 45 | MIMEOctetStream = "application/octet-stream" 46 | MIMEJsonAPI = "application/vnd.api+json" 47 | MIMEJsonStream = "application/x-json-stream" 48 | MIMEImagePng = "image/png" 49 | MIMEImageJpeg = "image/jpeg" 50 | MIMEImageGif = "image/gif" 51 | ) 52 | -------------------------------------------------------------------------------- /starter/starter-web/starter-web_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package StarterWeb 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/go-spring/spring-core/web" 23 | "github.com/go-spring/spring-stl/assert" 24 | ) 25 | 26 | func TestSort(t *testing.T) { 27 | 28 | container := func(basePath string) web.Container { 29 | return web.NewAbstractContainer(web.ContainerConfig{BasePath: basePath}) 30 | } 31 | 32 | testSort := func(input []string, output []string) bool { 33 | starter := &Starter{} 34 | for _, s := range input { 35 | starter.Containers = append(starter.Containers, container(s)) 36 | } 37 | starter.sortContainers() 38 | for i, c := range starter.Containers { 39 | if output[i] != c.Config().BasePath { 40 | return false 41 | } 42 | } 43 | return true 44 | } 45 | 46 | assert.Equal(t, true, testSort( 47 | []string{"/c/d", "/a/b", "/c", "/a", "/"}, 48 | []string{"/c/d", "/c", "/a/b", "/a", "/"}, 49 | )) 50 | 51 | assert.Equal(t, true, testSort( 52 | []string{"/c/d", "/c", "/a/b", "/a", "/"}, 53 | []string{"/c/d", "/c", "/a/b", "/a", "/"}, 54 | )) 55 | 56 | assert.Equal(t, true, testSort( 57 | []string{"/c/d", "/c", "/a", "/a/b", "/"}, 58 | []string{"/c/d", "/c", "/a/b", "/a", "/"}, 59 | )) 60 | 61 | assert.Equal(t, true, testSort( 62 | []string{"/c/d", "/c", "/a", "/", "/a/b"}, 63 | []string{"/c/d", "/c", "/a/b", "/a", "/"}, 64 | )) 65 | 66 | assert.Equal(t, true, testSort( 67 | []string{"/a", "/c/d", "/a/b", "/c", "/"}, 68 | []string{"/c/d", "/c", "/a/b", "/a", "/"}, 69 | )) 70 | 71 | assert.Equal(t, true, testSort( 72 | []string{"/c/d", "/a", "/a/b", "/c", "/"}, 73 | []string{"/c/d", "/c", "/a/b", "/a", "/"}, 74 | )) 75 | 76 | assert.Equal(t, true, testSort( 77 | []string{"/c/d", "/a/b", "/a", "/c", "/"}, 78 | []string{"/c/d", "/c", "/a/b", "/a", "/"}, 79 | )) 80 | 81 | assert.Equal(t, true, testSort( 82 | []string{"/c/d", "/a/b", "/c", "/", "/a"}, 83 | []string{"/c/d", "/c", "/a/b", "/a", "/"}, 84 | )) 85 | } 86 | -------------------------------------------------------------------------------- /spring/spring-core/gs/app_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package gs_test 18 | 19 | import ( 20 | "errors" 21 | "fmt" 22 | "os" 23 | "sort" 24 | "testing" 25 | "time" 26 | 27 | "github.com/go-spring/spring-core/conf" 28 | "github.com/go-spring/spring-core/gs" 29 | "github.com/go-spring/spring-core/gs/environ" 30 | "github.com/go-spring/spring-stl/assert" 31 | ) 32 | 33 | func startApplication(cfgLocation string) (*gs.App, gs.Pandora) { 34 | 35 | app := gs.NewApp() 36 | gs.Setenv("SPRING_BANNER_VISIBLE", true) 37 | gs.Setenv("SPRING_CONFIG_LOCATION", cfgLocation) 38 | app.Property(environ.EnablePandora, true) 39 | 40 | var p gs.Pandora 41 | type PandoraAware struct{} 42 | app.Provide(func(b gs.Pandora) PandoraAware { 43 | p = b 44 | return PandoraAware{} 45 | }) 46 | 47 | go app.Run() 48 | time.Sleep(100 * time.Millisecond) 49 | return app, p 50 | } 51 | 52 | func TestConfig(t *testing.T) { 53 | 54 | t.Run("config via env", func(t *testing.T) { 55 | os.Clearenv() 56 | gs.Setenv("GS_SPRING_PROFILES_ACTIVE", "dev") 57 | app, p := startApplication("testdata/config/") 58 | defer app.ShutDown(errors.New("run test end")) 59 | assert.Equal(t, p.Prop(environ.SpringProfilesActive), "dev") 60 | }) 61 | 62 | t.Run("config via env 2", func(t *testing.T) { 63 | os.Clearenv() 64 | gs.Setenv("GS_SPRING_PROFILES_ACTIVE", "dev") 65 | app, p := startApplication("testdata/config/") 66 | defer app.ShutDown(errors.New("run test end")) 67 | assert.Equal(t, p.Prop(environ.SpringProfilesActive), "dev") 68 | }) 69 | 70 | t.Run("profile via env&config 2", func(t *testing.T) { 71 | 72 | os.Clearenv() 73 | gs.Setenv("GS_SPRING_PROFILES_ACTIVE", "dev") 74 | app, p := startApplication("testdata/config/") 75 | defer app.ShutDown(errors.New("run test end")) 76 | assert.Equal(t, p.Prop(environ.SpringProfilesActive), "dev") 77 | 78 | var m map[string]string 79 | _ = p.Bind(&m, conf.Key(conf.RootKey)) 80 | for _, k := range sortedKeys(m) { 81 | fmt.Println(k, "=", p.Prop(k)) 82 | } 83 | }) 84 | } 85 | 86 | func sortedKeys(m map[string]string) (keys []string) { 87 | for k := range m { 88 | keys = append(keys, k) 89 | } 90 | sort.Strings(keys) 91 | return 92 | } 93 | -------------------------------------------------------------------------------- /starter/starter-grpc/server/factory/factory.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package GrpcServerFactory 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "net" 23 | "reflect" 24 | "runtime" 25 | 26 | SpringGrpc "github.com/go-spring/spring-core/grpc" 27 | "github.com/go-spring/spring-core/gs" 28 | "github.com/go-spring/spring-core/log" 29 | "github.com/go-spring/spring-stl/util" 30 | "github.com/go-spring/starter-core" 31 | "google.golang.org/grpc" 32 | ) 33 | 34 | // Starter gRPC 服务器启动器 35 | type Starter struct { 36 | config StarterCore.GrpcServerConfig 37 | server *grpc.Server 38 | } 39 | 40 | // NewStarter Starter 的构造函数 41 | func NewStarter(config StarterCore.GrpcServerConfig) *Starter { 42 | return &Starter{ 43 | config: config, 44 | server: grpc.NewServer(), 45 | } 46 | } 47 | 48 | func (starter *Starter) OnStartApp(ctx gs.AppContext) { 49 | 50 | var servers map[string]SpringGrpc.Server 51 | err := ctx.Get(&servers) 52 | util.Panic(err).When(err != nil) 53 | 54 | server := reflect.ValueOf(starter.server) 55 | srvMap := make(map[string]reflect.Value) 56 | for serviceName, rpcServer := range servers { 57 | 58 | service := reflect.ValueOf(rpcServer.Service) 59 | srvMap[serviceName] = service 60 | 61 | _, err = ctx.Wire(rpcServer.Service) 62 | util.Panic(err).When(err != nil) 63 | 64 | fn := reflect.ValueOf(rpcServer.Register) 65 | fn.Call([]reflect.Value{server, service}) 66 | } 67 | 68 | for service, info := range starter.server.GetServiceInfo() { 69 | srv := srvMap[service] 70 | for _, method := range info.Methods { 71 | m, _ := srv.Type().MethodByName(method.Name) 72 | fnPtr := m.Func.Pointer() 73 | fnInfo := runtime.FuncForPC(fnPtr) 74 | file, line := fnInfo.FileLine(fnPtr) 75 | log.Infof("/%s/%s %s:%d ", service, method.Name, file, line) 76 | } 77 | } 78 | 79 | addr := fmt.Sprintf(":%d", starter.config.Port) 80 | listener, err := net.Listen("tcp", addr) 81 | util.Panic(err).When(err != nil) 82 | 83 | ctx.Go(func(_ context.Context) { 84 | if err = starter.server.Serve(listener); err != nil { 85 | log.Error(err) 86 | } 87 | }) 88 | } 89 | 90 | func (starter *Starter) OnStopApp(ctx gs.AppContext) { 91 | starter.server.GracefulStop() 92 | } 93 | -------------------------------------------------------------------------------- /spring/spring-stl/apcu/apcu.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Package apcu 是进程内缓存,是 PHP APCu 的功能迁移。 18 | package apcu 19 | 20 | import ( 21 | "fmt" 22 | "reflect" 23 | "sync" 24 | "time" 25 | 26 | "github.com/go-spring/spring-stl/json" 27 | ) 28 | 29 | var cache sync.Map 30 | 31 | type cacheItem struct { 32 | source interface{} 33 | expireAt time.Time 34 | } 35 | 36 | // OnLoad Load 成功获取到 key 对应的缓存值时发一个通知出来。 37 | var OnLoad func(key string, val interface{}) 38 | 39 | // Load 获取 key 对应的缓存值,支持存入 string 但是按照 json 反序列化后的对象取出。 40 | func Load(key string, out interface{}) (ok bool, err error) { 41 | 42 | v, ok := cache.Load(key) 43 | if !ok { 44 | return false, nil 45 | } 46 | 47 | item := v.(*cacheItem) 48 | if !item.expireAt.IsZero() && time.Now().After(item.expireAt) { 49 | return false, nil 50 | } 51 | 52 | outVal := reflect.ValueOf(out) 53 | if outVal.Kind() != reflect.Ptr || outVal.IsNil() { 54 | return false, &json.InvalidUnmarshalError{Type: outVal.Type()} 55 | } 56 | 57 | defer func() { 58 | if ok && OnLoad != nil { 59 | OnLoad(key, outVal.Interface()) 60 | } 61 | }() 62 | 63 | if srcVal, ok := item.source.(reflect.Value); ok { 64 | if outVal.Type().Elem() == srcVal.Type() { 65 | outVal.Elem().Set(srcVal) 66 | return true, nil 67 | } 68 | } 69 | 70 | if str, ok := item.source.(string); ok { 71 | if err = json.Unmarshal([]byte(str), out); err != nil { 72 | return false, err 73 | } 74 | item.source = outVal.Elem() 75 | return true, nil 76 | } 77 | 78 | return false, fmt.Errorf("type not match %s", outVal.Type()) 79 | } 80 | 81 | // Delete 删除 key 对应的缓存内容。 82 | func Delete(key string) { 83 | cache.Delete(key) 84 | } 85 | 86 | type StoreArg struct { 87 | ttl time.Duration 88 | } 89 | 90 | type StoreOption func(arg *StoreArg) 91 | 92 | // TTL 过期时间 93 | func TTL(ttl time.Duration) StoreOption { 94 | return func(arg *StoreArg) { 95 | arg.ttl = ttl 96 | } 97 | } 98 | 99 | // Store 保存 key 及其对应的 val,支持对 key 设置 ttl 即过期时间。 100 | func Store(key string, val interface{}, opts ...StoreOption) { 101 | arg := StoreArg{} 102 | for _, opt := range opts { 103 | opt(&arg) 104 | } 105 | expireAt := time.Time{} 106 | if arg.ttl > 0 { 107 | expireAt = time.Now().Add(arg.ttl) 108 | } 109 | cache.Store(key, &cacheItem{source: val, expireAt: expireAt}) 110 | } 111 | -------------------------------------------------------------------------------- /starter/starter-web/starter-web.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package StarterWeb 18 | 19 | import ( 20 | "context" 21 | "net/http" 22 | "sort" 23 | "strings" 24 | 25 | "github.com/go-spring/spring-core/gs" 26 | "github.com/go-spring/spring-core/web" 27 | "github.com/go-spring/spring-stl/util" 28 | ) 29 | 30 | func init() { 31 | gs.Object(new(Starter)).Name("starter").Export(gs.AppEvent) 32 | } 33 | 34 | // Starter Web 服务器启动器 35 | type Starter struct { 36 | Containers []web.Container `autowire:""` 37 | } 38 | 39 | // OnStartApp 应用程序启动事件。 40 | func (starter *Starter) OnStartApp(ctx gs.AppContext) { 41 | 42 | starter.sortContainers() 43 | 44 | var webFilters struct { 45 | Filters []web.Filter `autowire:"${web.server.filters}"` 46 | } 47 | 48 | _, err := ctx.Wire(&webFilters) 49 | util.Panic(err).When(err != nil) 50 | 51 | for _, c := range starter.Containers { 52 | c.AddFilter(webFilters.Filters...) 53 | } 54 | 55 | var router web.Router 56 | err = ctx.Get(&router) 57 | util.Panic(err).When(err != nil) 58 | 59 | for _, m := range router.Mappers() { 60 | if c := starter.getContainer(m); c != nil { 61 | c.AddMapper(web.NewMapper(m.Method(), m.Path(), m.Handler())) 62 | } 63 | } 64 | 65 | starter.startContainers(ctx) 66 | } 67 | 68 | // OnStopApp 应用程序结束事件。 69 | func (starter *Starter) OnStopApp(ctx gs.AppContext) { 70 | for _, c := range starter.Containers { 71 | _ = c.Stop(context.Background()) 72 | } 73 | } 74 | 75 | // sortContainers 按照 BasePath 的前缀关系对容器进行排序。 76 | func (starter *Starter) sortContainers() { 77 | sort.Slice(starter.Containers, func(i, j int) bool { 78 | si := starter.Containers[i].Config().BasePath 79 | sj := starter.Containers[j].Config().BasePath 80 | if strings.HasPrefix(si, sj) { 81 | return true 82 | } 83 | return strings.Compare(si, sj) >= 0 84 | }) 85 | } 86 | 87 | func (starter *Starter) getContainer(mapper *web.Mapper) web.Container { 88 | for _, c := range starter.Containers { 89 | if strings.HasPrefix(mapper.Path(), c.Config().BasePath) { 90 | return c 91 | } 92 | } 93 | return nil 94 | } 95 | 96 | func (starter *Starter) startContainers(ctx gs.AppContext) { 97 | for _, container := range starter.Containers { 98 | c := container 99 | ctx.Go(func(_ context.Context) { 100 | if err := c.Start(); err != nil && err != http.ErrServerClosed { 101 | gs.ShutDown(err) 102 | } 103 | }) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /spring/spring-stl/cast/cast.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Package cast 提供了很多类型之间相互转换的函数。 18 | package cast 19 | 20 | import ( 21 | "time" 22 | 23 | "github.com/spf13/cast" 24 | ) 25 | 26 | // ToBool casts an interface{} to a bool. 27 | func ToBool(i interface{}) bool { 28 | v, _ := ToBoolE(i) 29 | return v 30 | } 31 | 32 | // ToBoolE casts an interface{} to a bool. 33 | func ToBoolE(i interface{}) (bool, error) { 34 | return cast.ToBoolE(i) 35 | } 36 | 37 | // ToInt casts an interface{} to an int. 38 | func ToInt(i interface{}) int { 39 | v, _ := ToInt64E(i) 40 | return int(v) 41 | } 42 | 43 | // ToInt64 casts an interface{} to an int64. 44 | func ToInt64(i interface{}) int64 { 45 | v, _ := ToInt64E(i) 46 | return v 47 | } 48 | 49 | // ToInt64E casts an interface{} to an int64. 50 | func ToInt64E(i interface{}) (int64, error) { 51 | return cast.ToInt64E(i) 52 | } 53 | 54 | // ToUint64 casts an interface{} to a uint64. 55 | func ToUint64(i interface{}) uint64 { 56 | v, _ := ToUint64E(i) 57 | return v 58 | } 59 | 60 | // ToUint64E casts an interface{} to a uint64. 61 | func ToUint64E(i interface{}) (uint64, error) { 62 | return cast.ToUint64E(i) 63 | } 64 | 65 | // ToFloat64 casts an interface{} to a float64. 66 | func ToFloat64(i interface{}) float64 { 67 | v, _ := ToFloat64E(i) 68 | return v 69 | } 70 | 71 | // ToFloat64E casts an interface{} to a float64. 72 | func ToFloat64E(i interface{}) (float64, error) { 73 | return cast.ToFloat64E(i) 74 | } 75 | 76 | // ToString casts an interface{} to a string. 77 | func ToString(i interface{}) string { 78 | v, err := ToStringE(i) 79 | if err != nil { 80 | return err.Error() 81 | } 82 | return v 83 | } 84 | 85 | // ToStringE casts an interface{} to a string. 86 | func ToStringE(i interface{}) (string, error) { 87 | return cast.ToStringE(i) 88 | } 89 | 90 | // ToDuration casts an interface{} to a time.Duration. 91 | func ToDuration(i interface{}) time.Duration { 92 | v, _ := ToDurationE(i) 93 | return v 94 | } 95 | 96 | // ToDurationE casts an interface{} to a time.Duration. 97 | func ToDurationE(i interface{}) (time.Duration, error) { 98 | return cast.ToDurationE(i) 99 | } 100 | 101 | // ToTime casts an interface{} to a time.Time. 102 | func ToTime(i interface{}) time.Time { 103 | v, _ := ToTimeE(i) 104 | return v 105 | } 106 | 107 | // ToTimeE casts an interface{} to a time.Time. 108 | func ToTimeE(i interface{}) (time.Time, error) { 109 | return cast.ToTimeE(i) 110 | } 111 | -------------------------------------------------------------------------------- /examples/spring-boot-grpc/helloworld/helloworld_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | 3 | package helloworld 4 | 5 | import ( 6 | context "context" 7 | grpc "google.golang.org/grpc" 8 | codes "google.golang.org/grpc/codes" 9 | status "google.golang.org/grpc/status" 10 | ) 11 | 12 | // This is a compile-time assertion to ensure that this generated file 13 | // is compatible with the grpc package it is being compiled against. 14 | const _ = grpc.SupportPackageIsVersion6 15 | 16 | // GreeterClient is the client API for Greeter service. 17 | // 18 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 19 | type GreeterClient interface { 20 | // Sends a greeting 21 | SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) 22 | } 23 | 24 | type greeterClient struct { 25 | cc grpc.ClientConnInterface 26 | } 27 | 28 | func NewGreeterClient(cc grpc.ClientConnInterface) GreeterClient { 29 | return &greeterClient{cc} 30 | } 31 | 32 | func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { 33 | out := new(HelloReply) 34 | err := c.cc.Invoke(ctx, "/helloworld.Greeter/SayHello", in, out, opts...) 35 | if err != nil { 36 | return nil, err 37 | } 38 | return out, nil 39 | } 40 | 41 | // GreeterServer is the server API for Greeter service. 42 | // All implementations should embed UnimplementedGreeterServer 43 | // for forward compatibility 44 | type GreeterServer interface { 45 | // Sends a greeting 46 | SayHello(context.Context, *HelloRequest) (*HelloReply, error) 47 | } 48 | 49 | // UnimplementedGreeterServer should be embedded to have forward compatible implementations. 50 | type UnimplementedGreeterServer struct { 51 | } 52 | 53 | func (*UnimplementedGreeterServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) { 54 | return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") 55 | } 56 | 57 | func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) { 58 | s.RegisterService(&_Greeter_serviceDesc, srv) 59 | } 60 | 61 | func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 62 | in := new(HelloRequest) 63 | if err := dec(in); err != nil { 64 | return nil, err 65 | } 66 | if interceptor == nil { 67 | return srv.(GreeterServer).SayHello(ctx, in) 68 | } 69 | info := &grpc.UnaryServerInfo{ 70 | Server: srv, 71 | FullMethod: "/helloworld.Greeter/SayHello", 72 | } 73 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 74 | return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) 75 | } 76 | return interceptor(ctx, in, info, handler) 77 | } 78 | 79 | var _Greeter_serviceDesc = grpc.ServiceDesc{ 80 | ServiceName: "helloworld.Greeter", 81 | HandlerType: (*GreeterServer)(nil), 82 | Methods: []grpc.MethodDesc{ 83 | { 84 | MethodName: "SayHello", 85 | Handler: _Greeter_SayHello_Handler, 86 | }, 87 | }, 88 | Streams: []grpc.StreamDesc{}, 89 | Metadata: "examples/helloworld/helloworld/helloworld.proto", 90 | } 91 | -------------------------------------------------------------------------------- /spring/spring-core/web/rpc-result.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package web 18 | 19 | import ( 20 | "fmt" 21 | "math" 22 | 23 | "github.com/go-spring/spring-stl/errors" 24 | "github.com/go-spring/spring-stl/util" 25 | ) 26 | 27 | var ( 28 | ERROR = NewRpcError(-1, "ERROR") 29 | SUCCESS = NewRpcSuccess(200, "SUCCESS") 30 | DEFAULT = NewErrorCode(math.MaxInt32, "DEFAULT") 31 | ) 32 | 33 | // ErrorCode 错误码 34 | type ErrorCode struct { 35 | Code int32 `json:"code"` // 错误码 36 | Msg string `json:"msg"` // 错误信息 37 | } 38 | 39 | // NewErrorCode ErrorCode 的构造函数 40 | func NewErrorCode(code int32, msg string) ErrorCode { 41 | return ErrorCode{Code: code, Msg: msg} 42 | } 43 | 44 | // RpcResult 定义 RPC 返回值 45 | type RpcResult struct { 46 | ErrorCode 47 | 48 | Err string `json:"err,omitempty"` // 错误源 49 | Data interface{} `json:"data,omitempty"` // 返回值 50 | } 51 | 52 | // RpcSuccess 定义一个 RPC 成功值 53 | type RpcSuccess ErrorCode 54 | 55 | // NewRpcSuccess RpcSuccess 的构造函数 56 | func NewRpcSuccess(code int32, msg string) RpcSuccess { 57 | return RpcSuccess(NewErrorCode(code, msg)) 58 | } 59 | 60 | // Data 绑定一个值 61 | func (r RpcSuccess) Data(data interface{}) *RpcResult { 62 | return &RpcResult{ErrorCode: ErrorCode(r), Data: data} 63 | } 64 | 65 | // RpcError 定义一个 RPC 异常值 66 | type RpcError ErrorCode 67 | 68 | // NewRpcError RpcError 的构造函数 69 | func NewRpcError(code int32, msg string) RpcError { 70 | return RpcError(NewErrorCode(code, msg)) 71 | } 72 | 73 | // Error 绑定一个错误 74 | func (r RpcError) Error(err error) *RpcResult { 75 | return r.error(1, err, nil) 76 | } 77 | 78 | // ErrorWithData 绑定一个错误和一个值 79 | func (r RpcError) ErrorWithData(err error, data interface{}) *RpcResult { 80 | return r.error(1, err, data) 81 | } 82 | 83 | // error skip 是相对于当前函数的调用深度 84 | func (r RpcError) error(skip int, err error, data interface{}) *RpcResult { 85 | str := errors.WithFileLine(err, skip+1).Error() 86 | return &RpcResult{ErrorCode: ErrorCode(r), Err: str, Data: data} 87 | } 88 | 89 | // Panic 抛出一个异常值 90 | func (r RpcError) Panic(err error) *util.PanicCond { 91 | return util.NewPanicCond(func() interface{} { 92 | return r.error(2, err, nil) 93 | }) 94 | } 95 | 96 | // Panicf 抛出一段需要格式化的错误字符串 97 | func (r RpcError) Panicf(format string, a ...interface{}) *util.PanicCond { 98 | return util.NewPanicCond(func() interface{} { 99 | return r.error(2, fmt.Errorf(format, a...), nil) 100 | }) 101 | } 102 | 103 | // PanicImmediately 立即抛出一个异常值 104 | func (r RpcError) PanicImmediately(err error) { 105 | panic(r.error(1, err, nil)) 106 | } 107 | -------------------------------------------------------------------------------- /spring/spring-core/web/filter.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package web 18 | 19 | import ( 20 | "regexp" 21 | ) 22 | 23 | // Filter 过滤器接口 24 | type Filter interface { 25 | // Invoke 通过 chain.Next() 驱动链条向后执行 26 | Invoke(ctx Context, chain FilterChain) 27 | } 28 | 29 | // FuncFilter 函数实现的过滤器 30 | type FuncFilter func(ctx Context, chain FilterChain) 31 | 32 | func (f FuncFilter) Invoke(ctx Context, chain FilterChain) { 33 | f(ctx, chain) 34 | } 35 | 36 | // handlerFilter 包装 Web 处理接口的过滤器 37 | type handlerFilter struct { 38 | fn Handler 39 | } 40 | 41 | // HandlerFilter 把 Web 处理接口转换成过滤器 42 | func HandlerFilter(fn Handler) Filter { 43 | return &handlerFilter{fn: fn} 44 | } 45 | 46 | func (h *handlerFilter) Invoke(ctx Context, _ FilterChain) { 47 | h.fn.Invoke(ctx) 48 | } 49 | 50 | // FilterChain 过滤器链条接口 51 | type FilterChain interface { 52 | Next(ctx Context) 53 | } 54 | 55 | // DefaultFilterChain 默认的过滤器链条 56 | type DefaultFilterChain struct { 57 | filters []Filter // 过滤器列表 58 | next int // 下一个等待执行的过滤器的序号 59 | } 60 | 61 | // NewDefaultFilterChain DefaultFilterChain 的构造函数 62 | func NewDefaultFilterChain(filters []Filter) *DefaultFilterChain { 63 | return &DefaultFilterChain{filters: filters} 64 | } 65 | 66 | func (chain *DefaultFilterChain) Next(ctx Context) { 67 | 68 | // 链条执行到此结束 69 | if chain.next >= len(chain.filters) { 70 | return 71 | } 72 | 73 | // 执行下一个过滤器 74 | f := chain.filters[chain.next] 75 | chain.next++ 76 | f.Invoke(ctx, chain) 77 | } 78 | 79 | type urlPatterns struct { 80 | m map[*regexp.Regexp][]Filter 81 | } 82 | 83 | func (p *urlPatterns) Get(path string) []Filter { 84 | for pattern, filters := range p.m { 85 | if pattern.MatchString(path) { 86 | return filters 87 | } 88 | } 89 | return nil 90 | } 91 | 92 | // URLPatterns 根据 Filter 的 URL 匹配表达式进行分组。 93 | func URLPatterns(filters []Filter) (*urlPatterns, error) { 94 | 95 | filterMap := make(map[string][]Filter) 96 | for _, filter := range filters { 97 | var patterns []string 98 | if p, ok := filter.(interface{ URLPatterns() []string }); ok { 99 | patterns = p.URLPatterns() 100 | } else { 101 | patterns = []string{"/*"} 102 | } 103 | for _, pattern := range patterns { 104 | filterMap[pattern] = append(filterMap[pattern], filter) 105 | } 106 | } 107 | 108 | filterPatterns := make(map[*regexp.Regexp][]Filter) 109 | for pattern, filter := range filterMap { 110 | exp, err := regexp.Compile(pattern) 111 | if err != nil { 112 | return nil, err 113 | } 114 | filterPatterns[exp] = filter 115 | } 116 | return &urlPatterns{m: filterPatterns}, nil 117 | } 118 | -------------------------------------------------------------------------------- /spring/spring-stl/errors/errors_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package errors_test 18 | 19 | import ( 20 | "fmt" 21 | "testing" 22 | 23 | "github.com/go-spring/spring-stl/assert" 24 | "github.com/go-spring/spring-stl/errors" 25 | "github.com/go-spring/spring-stl/util" 26 | ) 27 | 28 | func TestPanicCond_When(t *testing.T) { 29 | util.Panic(errors.New("test error")).When(false) 30 | 31 | t.Run("Panic", func(t *testing.T) { 32 | defer func() { 33 | assert.Equal(t, recover(), errors.New("reason: panic")) 34 | }() 35 | util.Panic(fmt.Errorf("reason: %s", "panic")).When(true) 36 | }) 37 | 38 | t.Run("Panicf", func(t *testing.T) { 39 | defer func() { 40 | assert.Equal(t, recover(), errors.New("reason: panicf")) 41 | }() 42 | util.Panicf("reason: %s", "panicf").When(true) 43 | }) 44 | } 45 | 46 | func TestWithCause(t *testing.T) { 47 | 48 | t.Run("cause is string", func(t *testing.T) { 49 | err := errors.WithCause("this is a string") 50 | v := errors.Cause(err) 51 | assert.Equal(t, v, "this is a string") 52 | }) 53 | 54 | t.Run("cause is error", func(t *testing.T) { 55 | err := errors.WithCause(errors.New("this is an error")) 56 | v := errors.Cause(err) 57 | assert.Equal(t, v, errors.New("this is an error")) 58 | }) 59 | 60 | t.Run("cause is int", func(t *testing.T) { 61 | err := errors.WithCause(123456) 62 | v := errors.Cause(err) 63 | assert.Equal(t, v, 123456) 64 | }) 65 | } 66 | 67 | func panic2Error(v interface{}) (err error) { 68 | defer func() { 69 | if r := recover(); r != nil { 70 | err = errors.WithCause(r) 71 | } 72 | }() 73 | panic(v) 74 | } 75 | 76 | func TestPanic2Error(t *testing.T) { 77 | 78 | t.Run("panic is string", func(t *testing.T) { 79 | err := panic2Error("this is a string") 80 | v := errors.Cause(err) 81 | assert.Equal(t, v, "this is a string") 82 | }) 83 | 84 | t.Run("panic is error", func(t *testing.T) { 85 | err := panic2Error(errors.New("this is an error")) 86 | v := errors.Cause(err) 87 | assert.Equal(t, v, errors.New("this is an error")) 88 | }) 89 | 90 | t.Run("panic is int", func(t *testing.T) { 91 | err := panic2Error(123456) 92 | v := errors.Cause(err) 93 | assert.Equal(t, v, 123456) 94 | }) 95 | } 96 | 97 | func TestErrorWithFileLine(t *testing.T) { 98 | 99 | err := errors.WithFileLine(errors.New("this is an error"), 0) 100 | assert.Error(t, err, ".*:99: this is an error") 101 | 102 | fnError := func(e error) error { 103 | return errors.WithFileLine(e, 1) 104 | } 105 | 106 | err = fnError(errors.New("this is an error")) 107 | assert.Error(t, err, ".*:106: this is an error") 108 | } 109 | -------------------------------------------------------------------------------- /project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | spring-gin 5 | spring/spring-gin 6 | https://github.com/go-spring/spring-gin.git 7 | master 8 | 9 | 10 | spring-echo 11 | spring/spring-echo 12 | https://github.com/go-spring/spring-echo.git 13 | master 14 | 15 | 16 | starter-web 17 | starter/starter-web 18 | https://github.com/go-spring/starter-web.git 19 | master 20 | 21 | 22 | starter-gin 23 | starter/starter-gin 24 | https://github.com/go-spring/starter-gin.git 25 | master 26 | 27 | 28 | starter-echo 29 | starter/starter-echo 30 | https://github.com/go-spring/starter-echo.git 31 | master 32 | 33 | 34 | starter-go-redis 35 | starter/starter-go-redis 36 | https://github.com/go-spring/starter-go-redis.git 37 | master 38 | 39 | 40 | starter-go-mongo 41 | starter/starter-go-mongo 42 | https://github.com/go-spring/starter-go-mongo.git 43 | master 44 | 45 | 46 | starter-grpc 47 | starter/starter-grpc 48 | https://github.com/go-spring/starter-grpc.git 49 | master 50 | 51 | 52 | starter-rabbitmq 53 | starter/starter-rabbitmq 54 | https://github.com/go-spring/starter-rabbitmq.git 55 | main 56 | 57 | 58 | starter-gorm 59 | starter/starter-gorm 60 | https://github.com/go-spring/starter-gorm.git 61 | main 62 | 63 | 64 | spring-swag 65 | spring/spring-swag 66 | https://github.com/go-spring/spring-swag.git 67 | main 68 | 69 | 70 | starter-core 71 | starter/starter-core 72 | https://github.com/go-spring/starter-core.git 73 | main 74 | 75 | 76 | spring-stl 77 | spring/spring-stl 78 | https://github.com/go-spring/spring-stl.git 79 | main 80 | 81 | 82 | spring-rabbitmq 83 | spring/spring-rabbitmq 84 | https://github.com/go-spring/spring-rabbitmq.git 85 | master 86 | 87 | 88 | spring-core 89 | spring/spring-core 90 | https://github.com/go-spring/spring-core.git 91 | master 92 | 93 | --------------------------------------------------------------------------------