├── .gitignore ├── README.md ├── cloud-central ├── README.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── dreamylost │ │ │ └── CloudApplication.java │ └── resources │ │ ├── application-peer1.properties │ │ ├── application-peer2.properties │ │ └── application.properties │ └── test │ └── java │ └── com │ └── github │ └── dreamylost │ └── CloudApplicationTests.java ├── cloud-config-client ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── dreamylost │ │ │ └── config │ │ │ └── client │ │ │ ├── ClientApplication.java │ │ │ └── TestController.java │ └── resources │ │ ├── application.properties │ │ └── bootstrap.properties │ └── test │ └── java │ └── com │ └── github │ └── dreamylost │ └── config │ └── client │ └── ClientApplicationTests.java ├── cloud-config-server ├── config-repository │ ├── springcloudconfigclientdemo-dev.properties │ ├── springcloudconfigclientdemo-prod.properties │ ├── springcloudconfigclientdemo-test.properties │ └── springcloudconfigclientdemo.properties ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── dreamylost │ │ │ └── config │ │ │ └── server │ │ │ └── ServerApplication.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── github │ └── dreamylost │ └── config │ └── server │ └── SpringCloudConfigDemoApplicationTests.java ├── cloud-hello-provider ├── README.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── dreamylost │ │ │ └── HelloApplication.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── github │ └── dreamylost │ └── HelloApplicationTests.java ├── cloud-ribbon-consumer ├── README.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── dreamylost │ │ │ ├── ConsumerController.java │ │ │ ├── HelloService.java │ │ │ ├── RibbonConsumerApplication.java │ │ │ └── UserService.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── github │ └── dreamylost │ └── RibbonConsumerApplicationTests.java ├── cloud-user-provider ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── dreamylost │ │ │ ├── User.java │ │ │ └── UserApplication.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── github │ └── dreamylost │ └── UserApplicationTests.java ├── cxf ├── README.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── dreamylost │ │ │ ├── Application.java │ │ │ ├── CxfConfig.java │ │ │ ├── SpringController.java │ │ │ ├── dao │ │ │ └── StudentDao.java │ │ │ ├── entity │ │ │ ├── Student.java │ │ │ └── Students.java │ │ │ ├── resource │ │ │ ├── StudentInterface.java │ │ │ └── StudentInterfaceImpl.java │ │ │ ├── service │ │ │ └── StudentService.java │ │ │ └── serviceImpl │ │ │ └── StudentServiceImpl.java │ └── resources │ │ ├── application.properties │ │ ├── cxf-config.xml │ │ ├── demo.sql │ │ ├── mapper │ │ └── StudentMapper.xml │ │ └── mybatis-config.xml │ └── test │ └── java │ └── com │ └── github │ └── dreamylost │ └── CxfSpec.java ├── dubbo-api ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── github │ └── dreamylost │ ├── City.java │ ├── CityDubboService.java │ └── IHelloService.java ├── dubbo-consumer ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── github │ │ └── dreamylost │ │ ├── CityConsumer.java │ │ ├── ConsumerApplication.java │ │ └── HelloConsumer.java │ └── resources │ └── application.properties ├── dubbo-provider ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── github │ │ └── dreamylost │ │ ├── CityDubboServiceImpl.java │ │ ├── HelloServiceImpl.java │ │ └── ProviderApplication.java │ └── resources │ └── application.properties ├── graphql-complete ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── github │ │ └── dreamylost │ │ ├── GraphQLController.java │ │ ├── GraphQLProvider.java │ │ ├── HttpExampleApplication.java │ │ ├── Instrumentation │ │ ├── CustomInstrumentation.java │ │ └── FieldValidationBuilder.java │ │ ├── StarWarsWiring.java │ │ ├── cache │ │ ├── GraphQLCacheHelper.java │ │ └── LRUCache.java │ │ ├── context │ │ ├── Context.java │ │ └── ContextProvider.java │ │ ├── dao │ │ └── StarWarsData.java │ │ ├── domain │ │ ├── Droid.java │ │ ├── Episode.java │ │ ├── FilmCharacter.java │ │ └── Human.java │ │ ├── fetcher │ │ └── GraphQLFetcherHelper.java │ │ ├── resolver │ │ └── GraphQLResolverHelper.java │ │ └── scalar │ │ └── EmailScalar.java │ └── resources │ ├── application.properties │ ├── starWarsSchemaAnnotated.graphqls │ └── static │ └── index.html ├── graphql ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── github │ │ └── dreamylost │ │ ├── Application.java │ │ ├── DateFormatting.java │ │ ├── GraphQLController.java │ │ ├── GraphQLDataFetchers.java │ │ └── GraphQLProvider.java │ └── resources │ ├── application.properties │ ├── schema.graphql │ └── static │ └── index.html ├── mongodb ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── github │ │ └── dreamylost │ │ ├── Application.java │ │ ├── controller │ │ └── TestController.java │ │ ├── entity │ │ └── User.java │ │ ├── repository │ │ └── UserRepository.java │ │ └── service │ │ ├── UserService.java │ │ └── impl │ │ └── UserServiceImpl.java │ └── resources │ └── application.yml ├── pom.xml ├── redis ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── github │ │ └── dreamylost │ │ ├── Application.java │ │ ├── RedisConfig.java │ │ ├── TestController.java │ │ └── User.java │ └── resources │ └── application.yml ├── swagger ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── dreamylost │ │ │ ├── Application.java │ │ │ ├── SwaggerConfig.java │ │ │ └── TestController.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── github │ └── dreamylost │ └── ApplicationTests.java ├── undertow ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── github │ │ └── dreamylost │ │ ├── Application.java │ │ └── TestController.java │ └── resources │ └── application.yml ├── webflow-booking ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── dreamylost │ │ │ └── booking │ │ │ ├── config │ │ │ ├── DataSourceConfig.java │ │ │ ├── DispatcherServletInitializer.java │ │ │ ├── SecurityConfig.java │ │ │ ├── SecurityWebApplicationInitializer.java │ │ │ ├── WebFlowConfig.java │ │ │ └── WebMvcConfig.java │ │ │ ├── controller │ │ │ └── HotelsController.java │ │ │ ├── mode │ │ │ ├── Booking.java │ │ │ ├── Hotel.java │ │ │ ├── SearchCriteria.java │ │ │ └── User.java │ │ │ ├── service │ │ │ ├── BookingService.java │ │ │ └── BookingServiceImpl.java │ │ │ └── util │ │ │ ├── Amenity.java │ │ │ ├── BookingDateRange.java │ │ │ ├── BookingDateRangeValidator.java │ │ │ └── BookingFlowHandler.java │ ├── resources │ │ ├── META-INF │ │ │ └── persistence.xml │ │ ├── import.sql │ │ └── log4j2.xml │ └── webapp │ │ ├── META-INF │ │ └── MANIFEST.MF │ │ ├── WEB-INF │ │ ├── hotels │ │ │ ├── booking │ │ │ │ ├── booking-flow.xml │ │ │ │ ├── enterBookingDetails.jsp │ │ │ │ ├── messages.jsp │ │ │ │ ├── messages.properties │ │ │ │ ├── reviewBooking.jsp │ │ │ │ └── views.xml │ │ │ ├── bookingsTable.jsp │ │ │ ├── list.jsp │ │ │ ├── search.jsp │ │ │ ├── searchForm.jsp │ │ │ ├── show.jsp │ │ │ └── views.xml │ │ ├── intro.jsp │ │ ├── layouts │ │ │ ├── standard.jsp │ │ │ └── views.xml │ │ ├── login.jsp │ │ ├── logoutSuccess.jsp │ │ └── views.xml │ │ ├── images │ │ ├── bg.gif │ │ ├── btn.bg.gif │ │ ├── diplomat.jpg │ │ ├── header.jpg │ │ ├── input.bg.gif │ │ ├── powered-by-spring.png │ │ ├── spring-logo.jpg │ │ ├── springone2gx.jpeg │ │ ├── th.bg.gif │ │ ├── tse.gif │ │ └── webflow-logo.jpg │ │ └── styles │ │ ├── blueprint │ │ ├── icons │ │ │ ├── cross.png │ │ │ ├── key.png │ │ │ └── tick.png │ │ ├── ie.css │ │ ├── plugins │ │ │ ├── buttons │ │ │ │ ├── icons │ │ │ │ │ ├── cross.png │ │ │ │ │ ├── key.png │ │ │ │ │ └── tick.png │ │ │ │ ├── readme.txt │ │ │ │ └── screen.css │ │ │ ├── fancy-type │ │ │ │ ├── readme.txt │ │ │ │ └── screen.css │ │ │ ├── link-icons │ │ │ │ ├── icons │ │ │ │ │ ├── doc.png │ │ │ │ │ ├── email.png │ │ │ │ │ ├── external.png │ │ │ │ │ ├── feed.png │ │ │ │ │ ├── im.png │ │ │ │ │ ├── pdf.png │ │ │ │ │ ├── visited.png │ │ │ │ │ └── xls.png │ │ │ │ ├── readme.txt │ │ │ │ └── screen.css │ │ │ └── rtl │ │ │ │ ├── readme.txt │ │ │ │ └── screen.css │ │ ├── print.css │ │ ├── screen.css │ │ └── src │ │ │ ├── forms.css │ │ │ ├── grid.css │ │ │ ├── grid.png │ │ │ ├── ie.css │ │ │ ├── print.css │ │ │ ├── reset.css │ │ │ └── typography.css │ │ └── booking.css │ └── test │ └── java │ └── com │ └── github │ └── dreamylost │ └── booking │ └── BookingFlowExecutionTests.java ├── webflux-functional ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── dreamylost │ │ │ └── webflux │ │ │ ├── SpringbootWebfluxApplication.java │ │ │ ├── funtctional │ │ │ ├── handler │ │ │ │ └── UserHandler.java │ │ │ └── router │ │ │ │ └── RoutingConfiguration.java │ │ │ ├── model │ │ │ └── User.java │ │ │ └── service │ │ │ ├── IUserService.java │ │ │ └── impl │ │ │ └── UserServiceImpl.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── github │ └── dreamylost │ └── webflux │ └── SpringbootWebfluxApplicationTests.java └── webflux ├── README.md ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── github │ │ └── dreamylost │ │ └── webflux │ │ ├── SpringbootWebfluxApplication.java │ │ ├── User.java │ │ └── WebFluxController.java └── resources │ └── application.yml └── test └── java └── com └── github └── dreamylost └── webflux └── SpringbootWebfluxApplicationTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ 26 | 27 | mvnw 28 | mvnw.cmd 29 | target/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | springboot-exmaples 2 | -- 3 | 4 | $ 表示子模块是依赖父级项目的(子模块本身就是多个模块组成的,如dubbo) 5 | 6 | > cxf 7 | 8 | ``` 9 | 整合SpringBoot MySQL Mybatis CXF/JSR-RS 10 | 实现WebServices 11 | 实现Restful 12 | ``` 13 | 14 | * 使用  15 | ``` 16 | 1.mysql中新建demo库运行resources下sql文件 17 | 2.修改application.properties修改数据源 18 | 3.启动Application.java类 19 | ``` 20 | 21 | > mongodb 22 | 23 | * 使用 24 | ``` 25 | 1.启动Application.java类 26 | 1.新增 127.0.0.1:9000/save 27 | 2.查询单个  127.0.0.1:9000/findByName 28 | 3.查询List  127.0.0.1:9000/find 29 | ``` 30 | 31 | > swagger 32 | 33 | * 使用 34 | ``` 35 | 1.启动Application.java类 36 | 2.访问localhost:8080/swagger-ui.html 37 | ``` 38 | 39 | > graphql 40 | 41 | * 使用 42 | ``` 43 | 1.启动Application.java类 44 | 2.访问http://localhost:8080/ 45 | 3.查询 46 | 调用方法hello:无参方法 47 | { 48 | hello 49 | } 50 | 调用方法echo:有参方法 51 | { 52 | echo(toEcho:"charming") 53 | } 54 | ``` 55 | 56 | > graphql-complete 57 | 58 | * 使用 59 | ``` 60 | 1.启动 Application.java 61 | 2.访问http://localhost:8080/ 62 | 3.查询 63 | 调用droid方法: 64 | { 65 | droid(id: "1001") { 66 | id 67 | } 68 | } 69 | 调用hero方法:枚举参数 70 | { 71 | hero(episode: NEWHOPE) { 72 | id 73 | } 74 | } 75 | 其他方法参考 starWarsSchemaAnnotated.graphqls 76 | ``` 77 | 78 | > dubbo $ 79 | 80 | * 使用 81 | ``` 82 | 1.启动zookeeper 83 | 2.启动dubbo-admin客户端(需自己将官方的war放进tomcat的webapps/ROOT下) tomcat端口 84 | 3.启动生产者(dubbo-provider) 端口8081 85 | 4.启动消费者(duboo-consumer) 端口8082 86 | 5.查询 87 | 1)浏览器输入: http://127.0.0.1:8082/sayHello/dubbo 88 | 2)返回String: Hello dubbo 89 | 3)浏览器输入:http://localhost:8082/getCity 90 | 4)返回JSON对象: 91 | { 92 | "id": 1, 93 | "provinceId": 2, 94 | "cityName": "南昌", 95 | "description": "是我的故乡" 96 | } 97 | 使用dubbo的管理平台(dubbo-admin应用放在ROOT下则路径:http://localhost:8088) 查看结果,初始账户为:root/root 98 | ``` 99 | > spring cloud 100 | 101 | 包含组件说明 102 | 103 | * Eureka 104 | * Ribbon 105 | * Config 106 | * Hystrix 107 | 108 | 模块说明 109 | 110 | * 服务注册中心(cloud-central) 111 | * hello服务提供者(cloud-hello-provider) 112 | * user服务提供者(cloud-user-provider) 113 | * 负载均衡/断路器(cloud-ribbon-consumer) 114 | * 配置中心 服务端(cloud-config-server) 115 | * 配置调用 客户端(cloud-config-client) 116 | 117 | ``` 118 | 1.启动cloud-central,修改 spring.profiles.active=peer2,再运行一个实例 119 | 2.启动cloud-hello-provider 支持启动多实例(随机端口) 120 | 3.启动cloud-user-provider 支持启动多实例(随机端口) 121 | 4.启动cloud-ribbon-consumer 122 | 5.启动cloud-config-server 123 | 6.启动cloud-config-client 124 | ``` 125 | 126 | > undertow 127 | 128 | * 使用 129 | ``` 130 | 1.启动Application.java类 131 | 2.访问 http://localhost:8084/ 132 | ``` 133 | 134 | > redis 135 | 136 | * 使用 137 | ``` 138 | 1.启动redis-server 139 | 2.启动Application.java类 140 | 3.请求http://localhost:8081/?p=参数 141 | 4.连接redis-cli,查看key=hello value=[\"com.github.dreamylost.User\",{\"uid\":123,\"userName\":\"zhangsan\",\"passWord\":\"pwd\"}] 142 | ``` 143 | -------------------------------------------------------------------------------- /cloud-central/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 服务注册中心: Eureka提供的服务端,提供服务注册与发现功能 4 | -------------------------------------------------------------------------------- /cloud-central/src/main/java/com/github/dreamylost/CloudApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | @EnableEurekaServer // 启动服务注册中心 8 | @SpringBootApplication 9 | public class CloudApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(CloudApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cloud-central/src/main/resources/application-peer1.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=cloud-central 2 | server.port=1111 3 | eureka.instance.hostname=peer1 4 | #指向peer2 在etc hosts配置 127.0.0.1 peer2, 5 | #使用ip eureka.instance.prefer-ip-address=true 6 | eureka.client.serviceUrl.defaultZone=http://peer2:1112/eureka/ 7 | spring.profiles.active=peer1 8 | #必须加上,分别为注册自己,寻找服务 9 | eureka.client.register-with-eureka=true 10 | eureka.client.fetch-registry=true 11 | #本地调试,关闭注册中心的自我保护 12 | eureka.server.enable-self-preservation=false -------------------------------------------------------------------------------- /cloud-central/src/main/resources/application-peer2.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=cloud-central 2 | server.port=1112 3 | eureka.instance.hostname=peer2 4 | #指向peer1 5 | eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/ 6 | spring.profiles.active=peer2 7 | eureka.client.register-with-eureka=true 8 | eureka.client.fetch-registry=true 9 | eureka.server.enable-self-preservation=false -------------------------------------------------------------------------------- /cloud-central/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #actuator 2 | #关闭权限,才能访问端点 3 | management.security.enabled=false 4 | 5 | #eureka,默认将自己作为客户端注册自己 6 | server.port=1111 7 | eureka.instance.hostname=localhost 8 | #向注册中心注册自己 9 | #高可用模式下 在 application-peer1.properties 与 application-peer2.properties 中显示 指定 这两个属性值为true即可。 10 | eureka.client.register-with-eureka=true 11 | #不需要检索服务 12 | eureka.client.fetch-registry=true 13 | #访问路径 14 | eureka.client.serverUrl.defaultZone=http://${euraka.instance.hostname}:${server.port}/eureka/ 15 | #修改active,模拟启动2个不同的服务注册中心 16 | spring.profiles.active=peer1 17 | -------------------------------------------------------------------------------- /cloud-central/src/test/java/com/github/dreamylost/CloudApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class CloudApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /cloud-config-client/src/main/java/com/github/dreamylost/config/client/ClientApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.config.client; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | 7 | /** 8 | * 通过bootstrap.properties实现在配置中心获取额外配置来代替本地配置 9 | * 10 | * 而不是在application配置文件中,bootstrap配置文件会比application更加早的加载。 11 | */ 12 | @SpringBootApplication 13 | @EnableDiscoveryClient 14 | public class ClientApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(ClientApplication.class, args); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /cloud-config-client/src/main/java/com/github/dreamylost/config/client/TestController.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.config.client; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.cloud.context.config.annotation.RefreshScope; 6 | import org.springframework.core.env.Environment; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | /** 11 | * @date: 2018-07-11 12 | * @author: liguobin 13 | * @description: 测试配置中心 14 | */ 15 | @RefreshScope//如果代码中需要动态刷新配置,在需要的类上加上该注解就行 16 | @RestController 17 | public class TestController { 18 | 19 | @Value("${from}") 20 | private String form; 21 | 22 | @Autowired 23 | private Environment env; 24 | 25 | @RequestMapping("from") 26 | public String from() { 27 | String env1 = env.getProperty("from", "undefined"); 28 | String env2 = this.form; 29 | return "@Value:" + env1 + "------" + "Env:" + env2; 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /cloud-config-client/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/cloud-config-client/src/main/resources/application.properties -------------------------------------------------------------------------------- /cloud-config-client/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | #对应配置文件的application部分 2 | spring.application.name=cloud-config-client 3 | #profile 4 | spring.cloud.config.profile=test 5 | #label 6 | spring.cloud.config.label=master 7 | #配置中心的地址 8 | #spring.cloud-central.config.uri=http://127.0.0.1:8088/ 9 | server.port=8089 10 | #模拟的是一个客户端向两个服务注册中心【peer1,peer2】进行注册,可以使用随机数端口多次启动项目,模拟多个客户端,构成多个服务向多个服务注册中心进行注册,实现高可用 11 | #但是这里我没有使用随机数/0端口 12 | eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/ 13 | #开启通过服务来访问config的功能,并指定服务名 14 | spring.cloud.config.discovery.enabled=true 15 | spring.cloud.config.discovery.service-id=cloud-config-server 16 | #关闭权限验证,访问actuator端点,使用http://localhost:8089/refresh 刷新git仓库配置 17 | management.security.enabled=false 18 | 19 | -------------------------------------------------------------------------------- /cloud-config-client/src/test/java/com/github/dreamylost/config/client/ClientApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.config.client; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ClientApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /cloud-config-server/config-repository/springcloudconfigclientdemo-dev.properties: -------------------------------------------------------------------------------- 1 | from=git-dev-1.0 -------------------------------------------------------------------------------- /cloud-config-server/config-repository/springcloudconfigclientdemo-prod.properties: -------------------------------------------------------------------------------- 1 | from=git-prod-1.0 -------------------------------------------------------------------------------- /cloud-config-server/config-repository/springcloudconfigclientdemo-test.properties: -------------------------------------------------------------------------------- 1 | from=git-test-1.0 -------------------------------------------------------------------------------- /cloud-config-server/config-repository/springcloudconfigclientdemo.properties: -------------------------------------------------------------------------------- 1 | from=git-default-1.0 -------------------------------------------------------------------------------- /cloud-config-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.github.dreamylost 7 | cloud-config-server 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | cloud-config-server 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 1.5.13.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | Dalston.SR5 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.cloud 31 | spring-cloud-config-server 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-test 37 | test 38 | 39 | 40 | 41 | org.springframework.cloud 42 | spring-cloud-starter-eureka 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.springframework.cloud 50 | spring-cloud-dependencies 51 | ${spring-cloud.version} 52 | pom 53 | import 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | org.springframework.boot 62 | spring-boot-maven-plugin 63 | 64 | 65 | org.apache.maven.plugins 66 | maven-compiler-plugin 67 | 68 | 8 69 | 8 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /cloud-config-server/src/main/java/com/github/dreamylost/config/server/ServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.config.server; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.cloud.config.server.EnableConfigServer; 7 | 8 | /** 9 | * 为了方便不再加分支的config版本控制 10 | * 只记录匹配规则:其中label分支名,profile是环境名 11 | * /{application}/{profile}[/{label}] 12 | * /{application}-{profile}.yml 13 | * /{label}/{application}-{profile}.yml 14 | * /{application}-{profile}.properties 15 | * /{label}/{application}-{profile}.properties 16 | *

17 | * config-repository文件是需要放在git上的配置文件 18 | */ 19 | @SpringBootApplication 20 | @EnableConfigServer//开启SpringCloud Config 服务端功能 21 | @EnableDiscoveryClient 22 | public class ServerApplication { 23 | 24 | public static void main(String[] args) { 25 | SpringApplication.run(ServerApplication.class, args); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /cloud-config-server/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=cloud-config-server 2 | server.port=8088 3 | spring.cloud.config.server.git.uri=https://github.com/jxnu-liguobin/springboot-examples/ 4 | spring.cloud.config.server.git.search-paths=cloud-config-server/config-repository 5 | spring.cloud.config.server.git.username=jxnu-liguobin 6 | spring.cloud.config.server.git.password=xxxxxxx 7 | #cloud是整个仓库项目的服务注册中心,peer1,peer2是os的host文件中配置的域名 8 | eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/ -------------------------------------------------------------------------------- /cloud-config-server/src/test/java/com/github/dreamylost/config/server/SpringCloudConfigDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.config.server; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class SpringCloudConfigDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /cloud-hello-provider/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 服务提供者: 可以是SpringBoot应用,也可以是其他技术平台且遵循Eureka通信机制的应用。 4 | 将自己提供的服务注册到Eureka,以提供其他应用发现和使用 5 | -------------------------------------------------------------------------------- /cloud-hello-provider/src/main/java/com/github/dreamylost/HelloApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.ServiceInstance; 7 | import org.springframework.cloud.client.discovery.DiscoveryClient; 8 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestMethod; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | @RestController 14 | @SpringBootApplication 15 | @EnableDiscoveryClient // 激活发现 16 | public class HelloApplication { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(HelloApplication.class, args); 20 | } 21 | 22 | @Autowired 23 | private DiscoveryClient client; 24 | 25 | @SuppressWarnings("deprecation") 26 | @RequestMapping(value = "/cloud-central-hello-provider", method = RequestMethod.GET) 27 | public String index() { 28 | ServiceInstance instance = client.getLocalServiceInstance(); 29 | System.out.println("生成者:/cloud-central-hello-provider,host:" + instance.getHost() + ", service_id:" + instance.getServiceId()); 30 | return "生产者 <<<" + " Hello World >>>"; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /cloud-hello-provider/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #关闭权限,才能访问端点 2 | management.security.enabled=false 3 | #server.port=8080 4 | #服务命名 5 | spring.application.name=cloud-hello-provider 6 | #指定服务注册中心的地址 7 | eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/ 8 | #修改端口,模拟启动第二个服务8081 9 | #使用随机造成注册与tomcat端口不同,server.port=${random.int[10000,19999]}但是服务注册端口与tomcat端口不同 10 | server.port=0 11 | #使用随机数,生成随机端口,指定服务的实例名 12 | eureka.instance.instanceId=${spring.application.name}:${random.int[10000,19999]} 13 | #使用随机数,生成随机端口,指定服务的实例名 14 | #使用actuator代替默认心跳 15 | eureka.client.healthcheck.enabled=true -------------------------------------------------------------------------------- /cloud-hello-provider/src/test/java/com/github/dreamylost/HelloApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class HelloApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /cloud-ribbon-consumer/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 服务消费者: 消费者从服务注册中心获取服务列表,从而消费者可以知道去何处调用其所需要的服务。 4 | 使用Ribbon,很多时候,客户端既是服务提供者,也是服务消费者 5 | -------------------------------------------------------------------------------- /cloud-ribbon-consumer/src/main/java/com/github/dreamylost/ConsumerController.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestMethod; 6 | import org.springframework.web.bind.annotation.RestController; 7 | import org.springframework.web.client.RestTemplate; 8 | 9 | import java.util.concurrent.ExecutionException; 10 | 11 | /** 12 | * @author 梦境迷离 13 | * @description 14 | * @time 2018年4月5日 15 | */ 16 | @RestController 17 | public class ConsumerController { 18 | 19 | @Autowired 20 | private RestTemplate restTemplate; 21 | 22 | @Autowired 23 | private HelloService helloService; 24 | 25 | @Autowired 26 | private UserService userService; 27 | 28 | 29 | //测试断路器 30 | @RequestMapping(value = "/ribbon-consumer2", method = RequestMethod.GET) 31 | public String helloConsumer2() { 32 | return helloService.hellService(); 33 | } 34 | 35 | 36 | @RequestMapping(value = "/cloud-ribbon-consumer", method = RequestMethod.GET) 37 | public String helloConsumer() { 38 | String string = restTemplate.getForEntity("http://CLOUD-HELLO-PROVIDER/hello", String.class).getBody(); 39 | System.out.println("消费者:" + string); 40 | return "消费者 <<<" + string + " >>>"; 41 | } 42 | 43 | 44 | @RequestMapping(value = "/user-consumer", method = RequestMethod.GET) 45 | public String userConsumer() { 46 | String user = restTemplate.getForEntity("http://CLOUD-USER-PROVIDER/user", String.class).getBody(); 47 | System.out.println("消费者:" + user); 48 | 49 | return "消费者 <<<" + user + " >>>"; 50 | } 51 | 52 | @RequestMapping(value = "/user-consumer2", method = RequestMethod.GET) 53 | public String userConsumer2() throws ExecutionException, InterruptedException { 54 | return userService.userService().get(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /cloud-ribbon-consumer/src/main/java/com/github/dreamylost/HelloService.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.web.client.RestTemplate; 7 | 8 | /** 9 | * Hystrix断路器 10 | *

11 | * 错误回调处理的请求 12 | * 13 | * @author 梦境迷离 14 | * @title: HelloService 15 | * @description: 16 | * @date 2018-07-29 17 | */ 18 | @Service 19 | public class HelloService { 20 | 21 | @Autowired 22 | private RestTemplate restTemplate; 23 | 24 | //同步执行 25 | @HystrixCommand(fallbackMethod = "helloFallback")//使用注解配置服务降级实现方法 26 | public String hellService() { 27 | return restTemplate.getForEntity("http://CLOUD-HELLO-PROVIDER/hello", String.class).getBody(); 28 | } 29 | 30 | //错误回调 31 | public String helloFallback() { 32 | return "error"; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cloud-ribbon-consumer/src/main/java/com/github/dreamylost/RibbonConsumerApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.web.client.RestTemplate; 10 | 11 | @EnableCircuitBreaker//开启断路器 12 | @EnableDiscoveryClient//服务发现 13 | @SpringBootApplication 14 | public class RibbonConsumerApplication { 15 | 16 | @Bean // 创建RestTemplate实例 17 | @LoadBalanced 18 | // 开启客户端负载均衡 19 | RestTemplate restTemplate() { 20 | return new RestTemplate(); 21 | } 22 | 23 | public static void main(String[] args) { 24 | SpringApplication.run(RibbonConsumerApplication.class, args); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /cloud-ribbon-consumer/src/main/java/com/github/dreamylost/UserService.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 4 | import com.netflix.hystrix.contrib.javanica.command.AsyncResult; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.web.client.RestTemplate; 8 | 9 | import java.util.concurrent.Future; 10 | 11 | /** 12 | * Hystrix断路器 13 | *

14 | * 异步方法 15 | * 16 | * @author 梦境迷离 17 | * @title: UserService 18 | * @description: 19 | * @date 2018-07-29 20 | */ 21 | 22 | @Service 23 | public class UserService { 24 | 25 | @Autowired 26 | private RestTemplate restTemplate; 27 | 28 | //异步执行 29 | @HystrixCommand 30 | public Future userService() { 31 | return new AsyncResult() { 32 | @Override 33 | public String invoke() { 34 | return restTemplate.getForEntity("http://CLOUD-USER-SERVICE/user", String.class).getBody(); 35 | } 36 | }; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /cloud-ribbon-consumer/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=cloud-ribbon-consumer 2 | server.port=9000 3 | eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/ 4 | -------------------------------------------------------------------------------- /cloud-ribbon-consumer/src/test/java/com/github/dreamylost/RibbonConsumerApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RibbonConsumerApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /cloud-user-provider/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .settings 9 | .springBeans 10 | .sts4-cache 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | /nbproject/private/ 20 | /build/ 21 | /nbbuild/ 22 | /dist/ 23 | /nbdist/ 24 | /.nb-gradle/ -------------------------------------------------------------------------------- /cloud-user-provider/src/main/java/com/github/dreamylost/User.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | /** 4 | * @author 梦境迷离 5 | * @version V1.0 6 | * @time 018年4月18日 7 | */ 8 | public class User { 9 | 10 | private Integer id; 11 | 12 | private String name; 13 | 14 | @Override 15 | public String toString() { 16 | return "User [id=" + id + ", name=" + name + "]"; 17 | } 18 | 19 | public Integer getId() { 20 | return id; 21 | } 22 | 23 | public void setId(Integer id) { 24 | this.id = id; 25 | } 26 | 27 | public String getName() { 28 | return name; 29 | } 30 | 31 | public void setName(String name) { 32 | this.name = name; 33 | } 34 | 35 | public User(Integer id, String name) { 36 | super(); 37 | this.id = id; 38 | this.name = name; 39 | } 40 | 41 | public User() { 42 | super(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /cloud-user-provider/src/main/java/com/github/dreamylost/UserApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.ServiceInstance; 7 | import org.springframework.cloud.client.discovery.DiscoveryClient; 8 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestMethod; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | @RestController 14 | @EnableDiscoveryClient 15 | @SpringBootApplication 16 | public class UserApplication { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(UserApplication.class, args); 20 | } 21 | 22 | @Autowired 23 | private DiscoveryClient client; 24 | 25 | @SuppressWarnings("deprecation") 26 | @RequestMapping(value = "/user", method = RequestMethod.GET) 27 | public String user() { 28 | ServiceInstance instance = client.getLocalServiceInstance(); 29 | System.out.println("生产者:/user,host:" + instance.getHost() + ", service_id:" + instance.getServiceId()); 30 | User user = new User(1, "张三"); 31 | return "生产者 <<< " + user.toString()+" >>>"; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /cloud-user-provider/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #服务命名 2 | #关闭权限,才能访问端点 3 | management.security.enabled=false 4 | #server.port=8080 5 | spring.application.name=cloud-user-provider 6 | #指定服务注册中心的地址 7 | eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/ 8 | #修改端口,模拟启动第二个服务8081 9 | #使用随机造成注册与tomcat端口不同,server.port=${random.int[10000,19999]}但是服务注册端口与tomcat端口不同 10 | server.port=0 11 | #使用随机数,生成随机端口,指定服务的实例名 12 | eureka.instance.instanceId=${spring.application.name}:${random.int[10000,19999]} 13 | #使用actuator代替默认心跳 14 | eureka.client.healthcheck.enabled=true -------------------------------------------------------------------------------- /cloud-user-provider/src/test/java/com/github/dreamylost/UserApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class UserApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /cxf/README.md: -------------------------------------------------------------------------------- 1 | # 整合SpringBoot Mysql Mybatis CXF/JSR-RS 2 | 3 | # 1、mysql中新建demo库运行resources下sql文件 4 | # 2、修改application.properties修改数据源 5 | # 3、启动主类 6 | -------------------------------------------------------------------------------- /cxf/src/main/java/com/github/dreamylost/Application.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.context.annotation.ImportResource; 7 | import org.springframework.stereotype.Controller; 8 | 9 | /** 10 | * 启动类 11 | * 12 | * @author: liguobin 13 | * @Description: 14 | * @时间: 2018-3-7 下午3:41:24 15 | * @version: V1.0 16 | */ 17 | @Controller 18 | @MapperScan("com.github.dreamylost.dao") 19 | @SpringBootApplication 20 | // / 没有这个rest失效 只存在soap 21 | @ImportResource(locations = {"classpath:cxf-config.xml"}) 22 | public class Application { 23 | 24 | public static void main(String[] args) { 25 | SpringApplication.run(Application.class, args); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /cxf/src/main/java/com/github/dreamylost/CxfConfig.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; 4 | import com.github.dreamylost.serviceImpl.StudentServiceImpl; 5 | import org.apache.cxf.Bus; 6 | import org.apache.cxf.bus.spring.SpringBus; 7 | import org.apache.cxf.jaxws.EndpointImpl; 8 | import org.apache.cxf.transport.servlet.CXFServlet; 9 | import org.springframework.beans.factory.annotation.Qualifier; 10 | import org.springframework.boot.web.servlet.ServletRegistrationBean; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.Configuration; 13 | 14 | import javax.xml.ws.Endpoint; 15 | 16 | /** 17 | * @author liguobin 18 | * @version V1.0 19 | * @time 2018-3-7 下午4:11:57 20 | */ 21 | @Configuration 22 | public class CxfConfig { 23 | 24 | @Bean 25 | public ServletRegistrationBean newServlet() { 26 | return new ServletRegistrationBean(new CXFServlet(), "/cxf/*"); 27 | } 28 | 29 | @Bean(name = Bus.DEFAULT_BUS_ID) 30 | public SpringBus springBus() { 31 | return new SpringBus(); 32 | } 33 | 34 | /** 35 | * @return 36 | */ 37 | @Bean 38 | @Qualifier("studentServiceImpl") // 注入webService 39 | public Endpoint endpoint(StudentServiceImpl studentServiceImpl) { 40 | EndpointImpl endpoint = new EndpointImpl(springBus(), studentServiceImpl); 41 | endpoint.publish("/webService");// 暴露webService api 42 | return endpoint; 43 | } 44 | 45 | @Bean("jsonProvider") // 构造一个json转化bean,用于将student转化为json 46 | public JacksonJsonProvider getJacksonJsonProvider() { 47 | return new JacksonJsonProvider(); 48 | 49 | } 50 | } -------------------------------------------------------------------------------- /cxf/src/main/java/com/github/dreamylost/SpringController.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.github.dreamylost.entity.Student; 5 | import com.github.dreamylost.entity.Students; 6 | import com.github.dreamylost.service.StudentService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.web.bind.annotation.PathVariable; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RequestMethod; 12 | import org.springframework.web.bind.annotation.ResponseBody; 13 | 14 | import javax.ws.rs.Consumes; 15 | import javax.ws.rs.Produces; 16 | import javax.ws.rs.core.MediaType; 17 | 18 | /** 19 | * Spring 前端控制 20 | *

21 | * 通过这个返回正确,作对比 22 | * 23 | * @author: liguobin 24 | * @Description: 25 | * @时间: 2018-3-7 下午3:35:17 26 | * @version: V1.0 27 | */ 28 | @Controller 29 | public class SpringController { 30 | 31 | @Autowired 32 | private StudentService studentRestfulService; 33 | 34 | @ResponseBody 35 | @Produces({MediaType.APPLICATION_JSON + "charset='utf-8'"}) 36 | @RequestMapping(value = "get/{id}", method = RequestMethod.GET) 37 | public String getStudent(@PathVariable("id") Integer id) { 38 | Student student = studentRestfulService.getStudent(id); 39 | Object json = JSONObject.toJSON(student); 40 | return json.toString(); 41 | } 42 | 43 | /** 44 | * @param ids 45 | * @return 46 | * @参数:{"ids":{"id":[1,2,3,4] 47 | */ 48 | @ResponseBody 49 | @Produces({MediaType.APPLICATION_JSON + "charset='utf-8'"}) 50 | @Consumes({MediaType.APPLICATION_JSON}) 51 | @RequestMapping(value = "gets/{ids}", method = RequestMethod.GET) 52 | public String getAll(@PathVariable("ids") String ids) { 53 | Students students = studentRestfulService.getAllStudent(ids); 54 | Object json = JSONObject.toJSON(students); 55 | return json.toString(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /cxf/src/main/java/com/github/dreamylost/dao/StudentDao.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.dao; 2 | 3 | import com.github.dreamylost.entity.Student; 4 | import org.apache.ibatis.annotations.Param; 5 | 6 | /** 7 | * dao层数据操作接口 8 | * 9 | * @author: liguobin 10 | * @Description: 11 | * @时间: 2018-3-7 下午3:41:43 12 | * @version: V1.0 13 | */ 14 | public interface StudentDao { 15 | 16 | Student getStudentById(@Param("id") Integer id); 17 | } 18 | -------------------------------------------------------------------------------- /cxf/src/main/java/com/github/dreamylost/entity/Student.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.entity; 2 | 3 | import javax.xml.bind.annotation.XmlRootElement; 4 | import java.io.Serializable; 5 | 6 | /** 7 | * 学生实体类 8 | * 9 | * @author: liguobin 10 | * @Description: 11 | * @时间: 2018-3-7 下午3:42:04 12 | * @version: V1.0 13 | */ 14 | @XmlRootElement(name = "Student") 15 | public class Student implements Serializable { 16 | private static final long serialVersionUID = 1L; 17 | private Integer id; 18 | private String name; 19 | private char sex; 20 | private String address; 21 | private Integer age; 22 | 23 | public Student() { 24 | super(); 25 | } 26 | 27 | public Student(Integer id, String name, char sex, String address, 28 | Integer age) { 29 | super(); 30 | this.id = id; 31 | this.name = name; 32 | this.sex = sex; 33 | this.address = address; 34 | this.age = age; 35 | } 36 | 37 | public Integer getId() { 38 | return id; 39 | } 40 | 41 | public void setId(Integer id) { 42 | this.id = id; 43 | } 44 | 45 | public String getName() { 46 | return name; 47 | } 48 | 49 | public void setName(String name) { 50 | this.name = name; 51 | } 52 | 53 | public char getSex() { 54 | return sex; 55 | } 56 | 57 | public void setSex(char sex) { 58 | this.sex = sex; 59 | } 60 | 61 | public String getAddress() { 62 | return address; 63 | } 64 | 65 | public void setAddress(String address) { 66 | this.address = address; 67 | } 68 | 69 | public Integer getAge() { 70 | return age; 71 | } 72 | 73 | public void setAge(Integer age) { 74 | this.age = age; 75 | } 76 | 77 | @Override 78 | public String toString() { 79 | return "Student [id=" + id + ", name=" + name + ", sex=" + sex 80 | + ", address=" + address + ", age=" + age + "]"; 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /cxf/src/main/java/com/github/dreamylost/entity/Students.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.entity; 2 | 3 | import javax.xml.bind.annotation.XmlElement; 4 | import javax.xml.bind.annotation.XmlRootElement; 5 | import java.util.List; 6 | 7 | /** 8 | * 封装多个学生实体类 9 | * 10 | * @author: liguobin 11 | * @Description: 12 | * @时间: 2018-3-7 下午3:42:14 13 | * @version: V1.0 14 | */ 15 | @XmlRootElement(name = "Students") 16 | public class Students { 17 | 18 | private List students; 19 | 20 | public Students(List students) { 21 | super(); 22 | this.students = students; 23 | } 24 | 25 | @XmlElement(name = "Student") 26 | public List getStudents() { 27 | return students; 28 | } 29 | 30 | public Students() { 31 | super(); 32 | } 33 | 34 | public void setStudents(List students) { 35 | this.students = students; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /cxf/src/main/java/com/github/dreamylost/resource/StudentInterface.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.resource; 2 | 3 | import com.github.dreamylost.entity.Student; 4 | import com.github.dreamylost.entity.Students; 5 | 6 | import javax.ws.rs.*; 7 | import javax.ws.rs.core.MediaType; 8 | 9 | /** 10 | * @author: liguobin 11 | * @Description: 12 | * @时间: 2018-3-7 下午3:59:15 13 | * @version: V1.0 14 | */ 15 | @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) 16 | public interface StudentInterface { 17 | 18 | /** 19 | * @param id 20 | * @return 21 | */ 22 | @GET 23 | @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) 24 | @Path("/getone/{id:[0-9]{0,10}}") // 限制id只能是0~9的数组 不超过10位 25 | public Student getStudent(@PathParam("id") Integer id); 26 | 27 | /** 28 | * 查找多个学生 29 | * 30 | * @param ids 31 | * @return 32 | */ 33 | 34 | @GET 35 | @Produces({MediaType.APPLICATION_JSON}) 36 | @Path("/getmany/{ids}") 37 | public Students getAllStudent(@PathParam("ids") String ids); 38 | } 39 | -------------------------------------------------------------------------------- /cxf/src/main/java/com/github/dreamylost/resource/StudentInterfaceImpl.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.resource; 2 | 3 | import com.alibaba.fastjson.JSONArray; 4 | import com.alibaba.fastjson.JSONObject; 5 | import com.github.dreamylost.entity.Student; 6 | import com.github.dreamylost.entity.Students; 7 | import com.github.dreamylost.service.StudentService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | 10 | import javax.ws.rs.GET; 11 | import javax.ws.rs.Path; 12 | import javax.ws.rs.PathParam; 13 | import javax.ws.rs.Produces; 14 | import javax.ws.rs.core.MediaType; 15 | import java.util.ArrayList; 16 | 17 | @Path("/") 18 | public class StudentInterfaceImpl implements StudentInterface { 19 | 20 | @Autowired 21 | private StudentService studentService; 22 | 23 | // 获取json 24 | @Override 25 | @GET 26 | @Path("/getjson/{id:[0-9]{0,10}}") 27 | @Produces({MediaType.APPLICATION_JSON}) 28 | public Student getStudent(@PathParam("id") Integer id) { 29 | return studentService.getStudent(id); 30 | } 31 | 32 | // 获取xml 33 | @GET 34 | @Path("/getxml/{id}") 35 | @Produces({MediaType.APPLICATION_XML}) 36 | public Student getStudent2(@PathParam("id") Integer id) { 37 | return studentService.getStudent(id); 38 | } 39 | 40 | /** 41 | * 返回students集合,此方法没有测试,参数是一个json对象,该对象包含一个name为id的数组 42 | */ 43 | @Override 44 | @GET 45 | @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) 46 | @Path("/getmany/{ids}") 47 | public Students getAllStudent(@PathParam("ids") String ids) { 48 | Students students = new Students(new ArrayList()); 49 | // 得到json对象 50 | JSONObject json = JSONObject.parseObject(ids); 51 | // 获取对象的id列表 52 | JSONArray sid = json.getJSONArray("id"); 53 | 54 | for (int i = 0; i < sid.size(); i++) { 55 | Integer s = sid.getInteger(0); 56 | if (s != null) { 57 | students.getStudents().add(studentService.getStudent(s)); 58 | } else { 59 | continue; 60 | } 61 | } 62 | return students; 63 | 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /cxf/src/main/java/com/github/dreamylost/service/StudentService.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.service; 2 | 3 | import com.github.dreamylost.entity.Student; 4 | import com.github.dreamylost.entity.Students; 5 | 6 | import javax.jws.WebMethod; 7 | import javax.jws.WebParam; 8 | import javax.jws.WebService; 9 | import javax.ws.rs.Consumes; 10 | import javax.ws.rs.Produces; 11 | import javax.ws.rs.core.MediaType; 12 | 13 | /** 14 | * @author liguobin 15 | * @description WebService接口定义 soap 16 | */ 17 | @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) // 返回类型 18 | @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) // 请求类型 19 | @WebService 20 | public interface StudentService { 21 | 22 | /** 23 | * 查找一个学生 24 | * 25 | * @param id 26 | * @return 27 | */ 28 | @WebMethod 29 | public Student getStudent(@WebParam(name = "id") Integer id); 30 | 31 | /** 32 | * 查找多个学生 33 | * 34 | * @param ids 35 | * @return 36 | */ 37 | @WebMethod 38 | public Students getAllStudent(@WebParam(name = "ids") String ids); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /cxf/src/main/java/com/github/dreamylost/serviceImpl/StudentServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.serviceImpl; 2 | 3 | import com.alibaba.fastjson.JSONArray; 4 | import com.alibaba.fastjson.JSONObject; 5 | import com.github.dreamylost.dao.StudentDao; 6 | import com.github.dreamylost.entity.Student; 7 | import com.github.dreamylost.entity.Students; 8 | import com.github.dreamylost.service.StudentService; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Component; 11 | 12 | import javax.jws.WebService; 13 | import java.util.ArrayList; 14 | 15 | /** 16 | * 实现webservice接口,对外暴露 soap 17 | * 18 | * @author: liguobin 19 | * @Description: 20 | * @时间: 2018-3-7 下午3:43:06 21 | * @version: V1.0 22 | */ 23 | @Component//由Spring管理 24 | @WebService(endpointInterface = "com.github.dreamylost.service.StudentService") // webservice接口的全类名 25 | public class StudentServiceImpl implements StudentService { 26 | 27 | /** 28 | * 注入spring bean 29 | */ 30 | @Autowired 31 | private StudentDao studentDao; 32 | 33 | @Override 34 | public Student getStudent(Integer id) { 35 | return studentDao.getStudentById(id); 36 | } 37 | 38 | /** 39 | * 没有测试正确性,不是本文重点 40 | */ 41 | @Override 42 | public Students getAllStudent(String ids) { 43 | Students students = new Students(new ArrayList()); 44 | // 得到json对象 45 | JSONObject json = JSONObject.parseObject(ids); 46 | // 获取对象的id列表 47 | JSONArray sid = json.getJSONArray("id"); 48 | 49 | for (int i = 0; i < sid.size(); i++) { 50 | Integer s = sid.getInteger(0); 51 | if (s != null) { 52 | students.getStudents().add(studentDao.getStudentById(s)); 53 | } else { 54 | continue; 55 | } 56 | } 57 | return students; 58 | 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /cxf/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #server port set 2 | server.port:8082 3 | #mysql datasource set 4 | spring.datasource. 5 | spring.datasource.url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8 6 | spring.datasource.username=root 7 | spring.datasource.password=root 8 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver 9 | mybatis.typeAliasesPackage=com.github.dreamylost.entity 10 | mybatis.mapperLocations=classpath\:mapper/*.xml 11 | mybatis.config-location=classpath\:mybatis-config.xml 12 | spring.jackson.serialization.indent_output=true 13 | logging.level.org.springframework.web=WARN 14 | #logging.file = C\:\\web\\temp\\log\\log.log 15 | logging.level.org.springframework=WARN 16 | logging.level.cn.edu.jxnu.dao=INFO 17 | logging.level.cn.edu.jxnu.resource=WARN 18 | -------------------------------------------------------------------------------- /cxf/src/main/resources/cxf-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /cxf/src/main/resources/demo.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat MySQL Data Transfer 3 | 4 | Source Server : root 5 | Source Server Version : 50540 6 | Source Host : localhost:3306 7 | Source Database : demo 8 | 9 | Target Server Type : MYSQL 10 | Target Server Version : 50540 11 | File Encoding : 65001 12 | 13 | Date: 2018-03-23 16:21:20 14 | */ 15 | 16 | SET FOREIGN_KEY_CHECKS=0; 17 | -- ---------------------------- 18 | -- Table structure for `student` 19 | -- ---------------------------- 20 | DROP TABLE IF EXISTS `student`; 21 | CREATE TABLE `student` ( 22 | `id` int(10) NOT NULL, 23 | `name` varchar(100) DEFAULT NULL, 24 | `sex` char(6) DEFAULT NULL, 25 | `address` varchar(255) DEFAULT NULL, 26 | `age` int(10) DEFAULT NULL, 27 | PRIMARY KEY (`id`) 28 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 29 | 30 | -- ---------------------------- 31 | -- Records of student 32 | -- ---------------------------- 33 | INSERT INTO `student` VALUES ('1', '李斯', '男', '江西南昌', '22'); 34 | -------------------------------------------------------------------------------- /cxf/src/main/resources/mapper/StudentMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | id,name,sex,address,age 16 | 17 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /cxf/src/main/resources/mybatis-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /cxf/src/test/java/com/github/dreamylost/CxfSpec.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import com.github.dreamylost.entity.Student; 4 | import com.github.dreamylost.service.StudentService; 5 | import junit.framework.TestCase; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 11 | import org.springframework.test.context.web.WebAppConfiguration; 12 | 13 | /** 14 | * 单元测试 测试整合 15 | */ 16 | @RunWith(SpringJUnit4ClassRunner.class) 17 | @SpringBootTest(classes = Application.class) 18 | @WebAppConfiguration 19 | public class CxfSpec extends TestCase { 20 | @Autowired 21 | private StudentService studentRestfulService; 22 | 23 | /** 24 | * 测试service与dao层 25 | */ 26 | @Test 27 | public void Test() { 28 | Student s = studentRestfulService.getStudent(1); 29 | System.out.println(s.toString()); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /dubbo-api/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.github.dreamylost 6 | springboot-examples 7 | 1.0-SNAPSHOT 8 | 9 | dubbo-api 10 | -------------------------------------------------------------------------------- /dubbo-api/src/main/java/com/github/dreamylost/City.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @author 梦境迷离 7 | * @title: City 8 | * @description: 城市实体类 9 | * @date 2018-07-08 10 | */ 11 | public class City implements Serializable { 12 | 13 | private static final long serialVersionUID = -1L; 14 | 15 | /** 16 | * 城市编号 17 | */ 18 | private Long id; 19 | 20 | /** 21 | * 省份编号 22 | */ 23 | private Long provinceId; 24 | 25 | /** 26 | * 城市名称 27 | */ 28 | private String cityName; 29 | 30 | /** 31 | * 描述 32 | */ 33 | private String description; 34 | 35 | public Long getId() { 36 | 37 | return id; 38 | } 39 | 40 | public void setId(Long id) { 41 | 42 | this.id = id; 43 | } 44 | 45 | public Long getProvinceId() { 46 | 47 | return provinceId; 48 | } 49 | 50 | public void setProvinceId(Long provinceId) { 51 | 52 | this.provinceId = provinceId; 53 | } 54 | 55 | public String getCityName() { 56 | 57 | return cityName; 58 | } 59 | 60 | 61 | public void setCityName(String cityName) { 62 | 63 | this.cityName = cityName; 64 | 65 | } 66 | 67 | public String getDescription() { 68 | 69 | return description; 70 | } 71 | 72 | public void setDescription(String description) { 73 | 74 | this.description = description; 75 | } 76 | 77 | public City(Long id, Long provinceId, String cityName, String description) { 78 | this.id = id; 79 | this.provinceId = provinceId; 80 | this.cityName = cityName; 81 | this.description = description; 82 | } 83 | 84 | @Override 85 | public String toString() { 86 | return "City{" + 87 | "id=" + id + 88 | ", provinceId=" + provinceId + 89 | ", cityName='" + cityName + '\'' + 90 | ", description='" + description + '\'' + 91 | '}'; 92 | } 93 | } -------------------------------------------------------------------------------- /dubbo-api/src/main/java/com/github/dreamylost/CityDubboService.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | /** 4 | * @author 梦境迷离 5 | * @title: CityDubboService 6 | * @description: 城市接口 7 | * @date 2018-07-08 8 | */ 9 | public interface CityDubboService { 10 | 11 | /** 12 | * 根据城市名称,查询城市信息 13 | * 14 | * @param cityName 15 | */ 16 | City findCityByName(String cityName); 17 | } 18 | -------------------------------------------------------------------------------- /dubbo-api/src/main/java/com/github/dreamylost/IHelloService.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | public interface IHelloService { 4 | 5 | String sayHello(String name); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /dubbo-consumer/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.github.dreamylost 6 | springboot-examples 7 | 1.0-SNAPSHOT 8 | 9 | dubbo-consumer 10 | 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-web 15 | 16 | 17 | 18 | com.alibaba.spring.boot 19 | dubbo-spring-boot-starter 20 | 21 | 22 | 23 | org.apache.zookeeper 24 | zookeeper 25 | 26 | 27 | 28 | org.apache.curator 29 | curator-framework 30 | 31 | 32 | com.github.dreamylost 33 | dubbo-api 34 | 1.0-SNAPSHOT 35 | compile 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /dubbo-consumer/src/main/java/com/github/dreamylost/CityConsumer.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import com.alibaba.dubbo.config.annotation.Reference; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | /** 8 | * @author 梦境迷离 9 | * @title: CityConsumer 10 | * @description: 消费者-得到对象 11 | * @date 2018-07-08 12 | */ 13 | @RestController 14 | public class CityConsumer { 15 | 16 | @Reference 17 | private CityDubboService cityDubboService; 18 | 19 | @RequestMapping("/getCity") 20 | public City TestCity() { 21 | 22 | System.out.println(cityDubboService); 23 | City city = cityDubboService.findCityByName("南昌"); 24 | System.out.println(city); 25 | return city; 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /dubbo-consumer/src/main/java/com/github/dreamylost/ConsumerApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | /** 8 | * @author 梦境迷离 9 | * @title: DubboConsumerLauncher 10 | * @description: 消费者 11 | * @date 2018-07-08 12 | */ 13 | @SpringBootApplication 14 | @EnableDubboConfiguration 15 | public class ConsumerApplication { 16 | 17 | public static void main(String[] args) throws Exception { 18 | SpringApplication.run(ConsumerApplication.class, args); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /dubbo-consumer/src/main/java/com/github/dreamylost/HelloConsumer.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import com.alibaba.dubbo.config.annotation.Reference; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | /** 9 | * @author 梦境迷离 10 | * @title: HelloConsumer 11 | * @description: 消费者-得到字符串 12 | * @date 2018-07-08 13 | */ 14 | @RestController 15 | public class HelloConsumer { 16 | 17 | @Reference 18 | private IHelloService helloService; 19 | 20 | @GetMapping("sayHello/{name}") 21 | public String sayHello(@PathVariable("name") String name) { 22 | return helloService.sayHello(name); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /dubbo-consumer/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8082 2 | spring.application.name=dubbo-consumer-test 3 | spring.dubbo.registry=zookeeper://127.0.0.1:2181?client=curator 4 | spring.dubbo.protocol=dubbo -------------------------------------------------------------------------------- /dubbo-provider/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.github.dreamylost 6 | springboot-examples 7 | 1.0-SNAPSHOT 8 | 9 | dubbo-provider 10 | 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-web 15 | 16 | 17 | 18 | com.alibaba.spring.boot 19 | dubbo-spring-boot-starter 20 | 21 | 22 | 23 | org.apache.zookeeper 24 | zookeeper 25 | 26 | 27 | 28 | org.apache.curator 29 | curator-framework 30 | 31 | 32 | com.github.dreamylost 33 | dubbo-api 34 | 1.0-SNAPSHOT 35 | compile 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /dubbo-provider/src/main/java/com/github/dreamylost/CityDubboServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import com.alibaba.dubbo.config.annotation.Service; 4 | import org.springframework.stereotype.Component; 5 | 6 | /** 7 | * @author 梦境迷离 8 | * @title: CityDubboServiceImpl 9 | * @description: 提供者-City具体实现 10 | * @date 2018-07-08 11 | */ 12 | @Service 13 | @Component// 注册为 Dubbo 服务 14 | public class CityDubboServiceImpl implements CityDubboService { 15 | 16 | @Override 17 | public City findCityByName(String cityName) { 18 | 19 | return new City(1L, 2L, "南昌", "是我的故乡"); 20 | } 21 | } -------------------------------------------------------------------------------- /dubbo-provider/src/main/java/com/github/dreamylost/HelloServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import com.alibaba.dubbo.config.annotation.Service; 4 | import org.springframework.stereotype.Component; 5 | 6 | /** 7 | * @author 梦境迷离 8 | * @title: HelloServiceImpl 9 | * @description: 提供者-Hello具体实现 10 | * @date 2018-07-08 11 | */ 12 | @Service 13 | @Component 14 | public class HelloServiceImpl implements IHelloService { 15 | 16 | @Override 17 | public String sayHello(String name) { 18 | return "Hello " + name + " !"; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /dubbo-provider/src/main/java/com/github/dreamylost/ProviderApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | /** 8 | * @author 梦境迷离 9 | * @title: DubboProviderLauncher 10 | * @description: 提供者(生产者) 11 | * @date 2018-07-08 12 | */ 13 | @SpringBootApplication 14 | @EnableDubboConfiguration 15 | public class ProviderApplication { 16 | 17 | public static void main(String[] args) throws Exception { 18 | SpringApplication.run(ProviderApplication.class, args); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /dubbo-provider/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8081 2 | spring.application.name=dubbo-provider-test 3 | spring.dubbo.registry=zookeeper://127.0.0.1:2181?client=curator 4 | spring.dubbo.protocol=dubbo -------------------------------------------------------------------------------- /graphql-complete/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | com.github.dreamylost 8 | graphql-complete 9 | 0.0.1-SNAPSHOT 10 | 11 | 12 | 13 | org.apache.maven.plugins 14 | maven-compiler-plugin 15 | 16 | 8 17 | 8 18 | 19 | 20 | 21 | 22 | jar 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-parent 27 | 1.5.10.RELEASE 28 | 29 | 30 | 31 | 32 | UTF-8 33 | UTF-8 34 | 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-web 40 | 41 | 42 | com.graphql-java 43 | graphql-java 44 | 10.0 45 | 46 | 47 | com.google.guava 48 | guava 49 | 29.0-jre 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /graphql-complete/src/main/java/com/github/dreamylost/GraphQLController.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.http.MediaType; 7 | import org.springframework.web.bind.annotation.*; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | import java.io.IOException; 12 | import java.util.LinkedHashMap; 13 | import java.util.Map; 14 | 15 | /** 16 | * 处理/graphql请求 17 | * 18 | * @author 梦境迷离 19 | * @time 2020年03月24日17:57:08 20 | */ 21 | @RestController 22 | public class GraphQLController { 23 | 24 | @Autowired 25 | private ObjectMapper objectMapper; 26 | 27 | @Autowired 28 | private GraphQLProvider graphQLProvider; 29 | 30 | //前端js中写死该URI 31 | @RequestMapping(value = "/graphql", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) 32 | @CrossOrigin 33 | public void graphqlGET(@RequestParam("query") String query, 34 | @RequestParam(value = "operationName", required = false) String operationName, 35 | @RequestParam("variables") String variablesJson, 36 | HttpServletResponse httpServletResponse) throws IOException { 37 | if (query == null) { 38 | query = ""; 39 | } 40 | Map variables = new LinkedHashMap<>(); 41 | ; 42 | if (variablesJson != null) { 43 | variables = objectMapper.readValue(variablesJson, new TypeReference>() { 44 | }); 45 | } 46 | graphQLProvider.executeGraphqlQuery(httpServletResponse, operationName, query, variables); 47 | } 48 | 49 | 50 | @SuppressWarnings("unchecked") 51 | @RequestMapping(value = "/graphql", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) 52 | @CrossOrigin 53 | public void graphql(@RequestBody Map body, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException { 54 | String query = (String) body.get("query"); 55 | if (query == null) { 56 | query = ""; 57 | } 58 | String operationName = (String) body.get("operationName"); 59 | Map variables = (Map) body.get("variables"); 60 | if (variables == null) { 61 | variables = new LinkedHashMap<>(); 62 | } 63 | //执行请求, 操作 查询 变量参数 64 | graphQLProvider.executeGraphqlQuery(httpServletResponse, operationName, query, variables); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /graphql-complete/src/main/java/com/github/dreamylost/HttpExampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | //启动本类 7 | //入门的中文文档 https://graphql.org.cn/learn/queries-fields.html 8 | @SpringBootApplication 9 | public class HttpExampleApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(HttpExampleApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /graphql-complete/src/main/java/com/github/dreamylost/Instrumentation/CustomInstrumentation.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.Instrumentation; 2 | 3 | import graphql.ExecutionResult; 4 | import graphql.execution.instrumentation.InstrumentationContext; 5 | import graphql.execution.instrumentation.InstrumentationState; 6 | import graphql.execution.instrumentation.SimpleInstrumentation; 7 | import graphql.execution.instrumentation.SimpleInstrumentationContext; 8 | import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters; 9 | import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters; 10 | import graphql.schema.DataFetcher; 11 | 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | import java.util.concurrent.CompletableFuture; 15 | 16 | /** 17 | * 自定义的instrumentation实现,用以计算请求处理时间 18 | * 19 | * @author 梦境迷离 20 | * @time 2020年03月31日14:22:24 21 | */ 22 | class CustomInstrumentationState implements InstrumentationState { 23 | private Map anyStateYouLike = new HashMap<>(); 24 | 25 | void recordTiming(String key, long time) { 26 | anyStateYouLike.put(key, time); 27 | } 28 | } 29 | 30 | public class CustomInstrumentation extends SimpleInstrumentation { 31 | @Override 32 | public InstrumentationState createState() { 33 | return new CustomInstrumentationState(); 34 | } 35 | 36 | @Override 37 | public InstrumentationContext beginExecution(InstrumentationExecutionParameters parameters) { 38 | long startNanos = System.nanoTime(); 39 | return new SimpleInstrumentationContext() { 40 | @Override 41 | public void onCompleted(ExecutionResult result, Throwable t) { 42 | CustomInstrumentationState state = parameters.getInstrumentationState(); 43 | state.recordTiming(parameters.getQuery(), System.nanoTime() - startNanos); 44 | } 45 | }; 46 | } 47 | 48 | @Override 49 | public DataFetcher instrumentDataFetcher(DataFetcher dataFetcher, InstrumentationFieldFetchParameters parameters) { 50 | return dataFetcher; 51 | } 52 | 53 | @Override 54 | public CompletableFuture instrumentExecutionResult(ExecutionResult executionResult, InstrumentationExecutionParameters parameters) { 55 | return CompletableFuture.completedFuture(executionResult); 56 | } 57 | } -------------------------------------------------------------------------------- /graphql-complete/src/main/java/com/github/dreamylost/Instrumentation/FieldValidationBuilder.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.Instrumentation; 2 | 3 | import graphql.execution.ExecutionPath; 4 | import graphql.execution.instrumentation.fieldvalidation.FieldValidation; 5 | import graphql.execution.instrumentation.fieldvalidation.FieldValidationInstrumentation; 6 | import graphql.execution.instrumentation.fieldvalidation.SimpleFieldValidation; 7 | 8 | import java.util.Optional; 9 | 10 | /** 11 | * @author 梦境迷离 12 | * @version 1.0, 2020/3/31 13 | */ 14 | public class FieldValidationBuilder { 15 | 16 | public static FieldValidationInstrumentation builder() { 17 | //遇到是human的请求,强制验证id长度不能小于4 18 | ExecutionPath fieldPath = ExecutionPath.parse("/human"); 19 | FieldValidation fieldValidation = new SimpleFieldValidation() 20 | .addRule(fieldPath, (fieldAndArguments, environment) -> { 21 | String nameArg = fieldAndArguments.getArgumentValue("id"); 22 | if (nameArg.length() < 4) { 23 | return Optional.of(environment.mkError("Invalid id length", fieldAndArguments)); 24 | } 25 | return Optional.empty(); 26 | }); 27 | 28 | return new FieldValidationInstrumentation(fieldValidation); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /graphql-complete/src/main/java/com/github/dreamylost/StarWarsWiring.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import com.github.dreamylost.cache.GraphQLCacheHelper; 4 | import com.github.dreamylost.dao.StarWarsData; 5 | import com.github.dreamylost.fetcher.GraphQLFetcherHelper; 6 | import com.github.dreamylost.resolver.GraphQLResolverHelper; 7 | import graphql.schema.DataFetcher; 8 | import graphql.schema.GraphQLScalarType; 9 | import graphql.schema.TypeResolver; 10 | import graphql.schema.idl.EnumValuesProvider; 11 | import org.dataloader.BatchLoader; 12 | import org.dataloader.DataLoader; 13 | import org.dataloader.DataLoaderOptions; 14 | import org.dataloader.DataLoaderRegistry; 15 | import org.springframework.context.annotation.Bean; 16 | import org.springframework.stereotype.Component; 17 | 18 | import java.util.List; 19 | import java.util.concurrent.CompletableFuture; 20 | import java.util.stream.Collectors; 21 | 22 | /** 23 | * 数据加载、获取、类型解析,自定义标量类型,为GraphQLProvider提供服务 24 | */ 25 | @Component 26 | public class StarWarsWiring { 27 | 28 | //数据加载 29 | private final DataLoaderRegistry dataLoaderRegistry; 30 | 31 | public StarWarsWiring() { 32 | this.dataLoaderRegistry = new DataLoaderRegistry(); 33 | //对于每个请求,都使用缓存,开启数据共享 34 | DataLoaderOptions options = DataLoaderOptions.newOptions().setCacheMap(GraphQLCacheHelper.getCacheMap()); 35 | //加载所有角色数据,注册到characters 36 | dataLoaderRegistry.register("characters", DataLoader.newDataLoader(characterBatchLoader, options)); 37 | } 38 | 39 | //graphql类型系统中的角色是一个接口,需要确定要返回的具体graphql对象类型 40 | TypeResolver characterTypeResolver = GraphQLResolverHelper.characterTypeResolver; 41 | 42 | //自定义标量 43 | GraphQLScalarType Email = GraphQLResolverHelper.Email; 44 | 45 | //枚举类型解析 46 | EnumValuesProvider episodeResolver = GraphQLResolverHelper.episodeResolver; 47 | 48 | //人类 数据获取 49 | DataFetcher humanDataFetcher = GraphQLFetcherHelper.humanDataFetcher; 50 | 51 | //人类,获取所有 52 | DataFetcher humansDataFetcher = GraphQLFetcherHelper.humansDataFetcher; 53 | 54 | //机器人 数据获取 55 | DataFetcher droidDataFetcher = GraphQLFetcherHelper.droidDataFetcher; 56 | 57 | //英雄 数据获取 58 | DataFetcher heroDataFetcher = GraphQLFetcherHelper.heroDataFetcher; 59 | 60 | //朋友 数据获取 61 | DataFetcher friendsDataFetcher = GraphQLFetcherHelper.friendsDataFetcher; 62 | 63 | //将DataLoaderRegistry作为bean,保留给ContextProvider 64 | @Bean 65 | public DataLoaderRegistry getDataLoaderRegistry() { 66 | return dataLoaderRegistry; 67 | } 68 | 69 | //批量根据id获取角色的信息数据 70 | private List getCharacterDataViaBatchHTTPApi(List keys) { 71 | return keys.stream().map(StarWarsData::getCharacterData).collect(Collectors.toList()); 72 | } 73 | 74 | //批处理,使用多线程 75 | private BatchLoader characterBatchLoader = keys -> { 76 | //我们在这里使用多线程 77 | return CompletableFuture.supplyAsync(() -> getCharacterDataViaBatchHTTPApi(keys)); 78 | }; 79 | 80 | } 81 | -------------------------------------------------------------------------------- /graphql-complete/src/main/java/com/github/dreamylost/cache/GraphQLCacheHelper.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.cache; 2 | 3 | import org.dataloader.CacheMap; 4 | 5 | /** 6 | * @author liguobin@growingio.com 7 | * @version 1.0, 2020/3/31 8 | */ 9 | public class GraphQLCacheHelper { 10 | 11 | 12 | private static final LRUCache lru = new LRUCache(10000); 13 | 14 | //缓存,根据需要使用存储方式。这里都只是为了过编译,实际没有使用 15 | private static final CacheMap crossRequestCacheMap = new CacheMap() { 16 | @Override 17 | public boolean containsKey(String key) { 18 | System.out.println("try get from cache"); 19 | return lru.containsKey(key); 20 | } 21 | 22 | @Override 23 | public Object get(String key) { 24 | System.out.println("get from cache"); 25 | return lru.get(key); 26 | } 27 | 28 | @Override 29 | public CacheMap set(String key, Object value) { 30 | System.out.println("set to cache"); 31 | lru.put(key, value); 32 | return this; 33 | } 34 | 35 | @Override 36 | public CacheMap delete(String key) { 37 | System.out.println("delete from cache"); 38 | lru.remove(key); 39 | return this; 40 | } 41 | 42 | @Override 43 | public CacheMap clear() { 44 | System.out.println("clear cache"); 45 | lru.clear(); 46 | return this; 47 | } 48 | }; 49 | 50 | public static CacheMap getCacheMap() { 51 | return crossRequestCacheMap; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /graphql-complete/src/main/java/com/github/dreamylost/cache/LRUCache.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.cache; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * 给gql使用的缓存 7 | * 8 | * @author 梦境迷离 9 | * @time 2020年03月31日17:34:16:57:08 10 | */ 11 | public class LRUCache { 12 | 13 | private int capacity; 14 | //直接使用LinkedHashMap 15 | private HashMap map = new HashMap<>(); 16 | private Node head = null; 17 | private Node end = null; 18 | 19 | public LRUCache(int capacity) { 20 | this.capacity = capacity; 21 | } 22 | 23 | public Object get(String key) { 24 | if (map.containsKey(key)) { 25 | Node n = map.get(key); 26 | remove(n); 27 | setHead(n); 28 | return n.value; 29 | } 30 | return null; 31 | } 32 | 33 | public boolean containsKey(String key) { 34 | return get(key) != null; 35 | } 36 | 37 | public void clear() { 38 | capacity = 0; 39 | map.clear(); 40 | head = null; 41 | end = null; 42 | } 43 | 44 | private void remove(Node n) { 45 | if (n.pre != null) { 46 | n.pre.next = n.next; 47 | } else { 48 | head = n.next; 49 | } 50 | 51 | if (n.next != null) { 52 | n.next.pre = n.pre; 53 | } else { 54 | end = n.pre; 55 | } 56 | } 57 | 58 | public void remove(String key) { 59 | if (map.containsKey(key)) { 60 | Node old = map.get(key); 61 | remove(old); 62 | } 63 | } 64 | 65 | private void setHead(Node n) { 66 | n.next = head; 67 | n.pre = null; 68 | 69 | if (head != null) 70 | head.pre = n; 71 | 72 | head = n; 73 | 74 | if (end == null) 75 | end = head; 76 | } 77 | 78 | public void put(String key, Object value) { 79 | if (map.containsKey(key)) { 80 | Node old = map.get(key); 81 | old.value = value; 82 | remove(old); 83 | setHead(old); 84 | } else { 85 | Node created = new Node(key, value); 86 | if (map.size() >= capacity) { 87 | map.remove(end.key); 88 | remove(end); 89 | setHead(created); 90 | } else { 91 | setHead(created); 92 | } 93 | map.put(key, created); 94 | } 95 | } 96 | } 97 | 98 | class Node { 99 | 100 | String key; 101 | Object value; 102 | Node pre; 103 | Node next; 104 | 105 | public Node(String key, Object value) { 106 | this.key = key; 107 | this.value = value; 108 | } 109 | } -------------------------------------------------------------------------------- /graphql-complete/src/main/java/com/github/dreamylost/context/Context.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.context; 2 | 3 | import org.dataloader.DataLoader; 4 | import org.dataloader.DataLoaderRegistry; 5 | 6 | /** 7 | * 上下文对象被传递到graphql查询的每个级别,在这种情况下,它包含数据加载器注册表。 8 | * 这使我们能够按请求保留数据加载器,因为它们经常缓存数据,而交叉请求缓存通常不是您想要的。 9 | * 10 | * @author 梦境迷离 11 | * @time 2020年03月24日17:57:08 12 | */ 13 | public class Context { 14 | 15 | final DataLoaderRegistry dataLoaderRegistry; 16 | 17 | Context(DataLoaderRegistry dataLoaderRegistry) { 18 | this.dataLoaderRegistry = dataLoaderRegistry; 19 | } 20 | 21 | public DataLoader getCharacterDataLoader() { 22 | return dataLoaderRegistry.getDataLoader("characters"); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /graphql-complete/src/main/java/com/github/dreamylost/context/ContextProvider.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.context; 2 | 3 | import org.dataloader.DataLoaderRegistry; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * 上下文提供器 9 | * 10 | * @author 梦境迷离 11 | * @time 2020年03月24日17:57:08 12 | */ 13 | @Component 14 | public class ContextProvider { 15 | 16 | @Autowired 17 | private DataLoaderRegistry dataLoaderRegistry; 18 | 19 | public Context newContext() { 20 | return new Context(dataLoaderRegistry); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /graphql-complete/src/main/java/com/github/dreamylost/domain/Droid.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.domain; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 机器人角色 7 | * 8 | * @author 梦境迷离 9 | * @time 2020年03月24日17:57:08 10 | */ 11 | public class Droid implements FilmCharacter { 12 | final String id; 13 | final String name; 14 | final List friends; 15 | // 使用枚举,否则在graphql调用getNameByValue时会匹配不到,一个是数值,一个是枚举 16 | final List appearsIn; 17 | //机器人的主要功能 18 | final String primaryFunction; 19 | 20 | public Droid(String id, String name, List friends, List appearsIn, String primaryFunction) { 21 | this.id = id; 22 | this.name = name; 23 | this.friends = friends; 24 | this.appearsIn = appearsIn; 25 | this.primaryFunction = primaryFunction; 26 | } 27 | 28 | public String getId() { 29 | return id; 30 | } 31 | 32 | public String getName() { 33 | return name; 34 | } 35 | 36 | public List getFriends() { 37 | return friends; 38 | } 39 | 40 | public List getAppearsIn() { 41 | return appearsIn; 42 | } 43 | 44 | public String getPrimaryFunction() { 45 | return primaryFunction; 46 | } 47 | 48 | @Override 49 | public String toString() { 50 | return "Droid{" + 51 | "id='" + id + '\'' + 52 | ", name='" + name + '\'' + 53 | '}'; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /graphql-complete/src/main/java/com/github/dreamylost/domain/Episode.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.domain; 2 | 3 | /** 4 | * 电影 电视剧 枚举类型 5 | * 6 | * @author 梦境迷离 7 | * @time 2020年03月24日17:57:08 8 | */ 9 | public enum Episode { 10 | 11 | NEWHOPE(0), 12 | EMPIRE(1), 13 | JEDI(2); 14 | 15 | Integer value; 16 | 17 | Episode(Integer value) { 18 | this.value = value; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /graphql-complete/src/main/java/com/github/dreamylost/domain/FilmCharacter.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.domain; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 电影角色 7 | * 8 | * @author 梦境迷离 9 | * @time 2020年03月24日17:57:08 10 | */ 11 | public interface FilmCharacter { 12 | 13 | //角色的id 姓名 朋友 出演的电影 14 | String getId(); 15 | 16 | String getName(); 17 | 18 | List getFriends(); 19 | 20 | List getAppearsIn(); 21 | } 22 | -------------------------------------------------------------------------------- /graphql-complete/src/main/java/com/github/dreamylost/domain/Human.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.domain; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 人类角色 7 | * 8 | * @author 梦境迷离 9 | * @time 2020年03月24日17:57:08 10 | */ 11 | public class Human implements FilmCharacter { 12 | final String id; 13 | final String name; 14 | final List friends; 15 | final List appearsIn; 16 | //人类的家园!(是行星) 17 | final String homePlanet; 18 | //自定义标量类型 19 | final String email; 20 | 21 | public Human(String id, String name, List friends, List appearsIn, String homePlanet, String email) { 22 | this.id = id; 23 | this.name = name; 24 | this.friends = friends; 25 | this.appearsIn = appearsIn; 26 | this.homePlanet = homePlanet; 27 | this.email = email; 28 | } 29 | 30 | @Override 31 | public String getId() { 32 | return id; 33 | } 34 | 35 | @Override 36 | public String getName() { 37 | return name; 38 | } 39 | 40 | @Override 41 | public List getFriends() { 42 | return friends; 43 | } 44 | 45 | @Override 46 | public List getAppearsIn() { 47 | return appearsIn; 48 | } 49 | 50 | public String getHomePlanet() { 51 | return homePlanet; 52 | } 53 | 54 | public String getEmail() { 55 | return email; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /graphql-complete/src/main/java/com/github/dreamylost/fetcher/GraphQLFetcherHelper.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.fetcher; 2 | 3 | import com.github.dreamylost.context.Context; 4 | import com.github.dreamylost.domain.FilmCharacter; 5 | import graphql.schema.DataFetcher; 6 | 7 | import java.util.List; 8 | import java.util.stream.Collectors; 9 | 10 | import static java.util.Arrays.asList; 11 | 12 | /** 13 | * @author liguobin@growingio.com 14 | * @version 1.0, 2020/3/31 15 | */ 16 | public class GraphQLFetcherHelper { 17 | 18 | //人类 数据获取 19 | public static DataFetcher humanDataFetcher = environment -> { 20 | String id = environment.getArgument("id"); 21 | Context ctx = environment.getContext(); 22 | return ctx.getCharacterDataLoader().load(id); 23 | }; 24 | 25 | //人类 数据读取器,获取所有s 26 | //实际应用应该实现DataFetcher接口而不是使用DataLoaderRegistry 27 | public static DataFetcher humansDataFetcher = environment -> { 28 | Context ctx = environment.getContext(); 29 | return ctx.getCharacterDataLoader().loadMany(asList("1000", "1001", "1002", "1003")); 30 | }; 31 | 32 | //机器人 数据获取 33 | public static DataFetcher droidDataFetcher = environment -> { 34 | String id = environment.getArgument("id"); 35 | Context ctx = environment.getContext(); 36 | return ctx.getCharacterDataLoader().load(id); 37 | }; 38 | 39 | //英雄 数据获取 40 | public static DataFetcher heroDataFetcher = environment -> { 41 | Context ctx = environment.getContext(); 42 | return ctx.getCharacterDataLoader().load("1002"); // R2D2 43 | }; 44 | 45 | //朋友 数据获取 46 | public static DataFetcher friendsDataFetcher = environment -> { 47 | FilmCharacter character = environment.getSource(); 48 | List friendIds = character.getFriends(); 49 | Context ctx = environment.getContext(); 50 | return ctx.getCharacterDataLoader().loadMany(friendIds.stream().map(FilmCharacter::getId).collect(Collectors.toList())); 51 | }; 52 | } 53 | -------------------------------------------------------------------------------- /graphql-complete/src/main/java/com/github/dreamylost/resolver/GraphQLResolverHelper.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.resolver; 2 | 3 | import com.github.dreamylost.domain.Episode; 4 | import com.github.dreamylost.domain.FilmCharacter; 5 | import com.github.dreamylost.domain.Human; 6 | import com.github.dreamylost.scalar.EmailScalar; 7 | import graphql.schema.GraphQLObjectType; 8 | import graphql.schema.GraphQLScalarType; 9 | import graphql.schema.TypeResolver; 10 | import graphql.schema.idl.EnumValuesProvider; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * @author liguobin@growingio.com 16 | * @version 1.0, 2020/3/31 17 | */ 18 | public class GraphQLResolverHelper { 19 | 20 | //TypeResolver帮助graphql-java决定具体值属于哪种类型。接口和联合需要此功能。 21 | /** 22 | * graphql类型系统中的角色是一个接口,需要确定要返回的具体graphql对象类型 23 | */ 24 | public static TypeResolver characterTypeResolver = environment -> { 25 | //类型解析 26 | FilmCharacter character = environment.getObject(); 27 | if (character instanceof Human) { 28 | //人类 29 | return (GraphQLObjectType) environment.getSchema().getType("Human"); 30 | } else { 31 | //机器人 32 | return (GraphQLObjectType) environment.getSchema().getType("Droid"); 33 | } 34 | }; 35 | 36 | //枚举类型解析 37 | public static EnumValuesProvider episodeResolver = Episode::valueOf; 38 | 39 | public static GraphQLScalarType Email = EmailScalar.Email; 40 | } 41 | -------------------------------------------------------------------------------- /graphql-complete/src/main/java/com/github/dreamylost/scalar/EmailScalar.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.scalar; 2 | 3 | import graphql.language.StringValue; 4 | import graphql.schema.*; 5 | 6 | import java.util.regex.Pattern; 7 | 8 | /** 9 | * 在graphql中自定义标量类型 10 | * 使用时还需要在graphqls中定义 scalar Email 11 | * 12 | * @author 梦境迷离 13 | * @time 2020年04月03日 14 | */ 15 | public class EmailScalar { 16 | 17 | public static final GraphQLScalarType Email = new GraphQLScalarType("Email", "A custom scalar that handles emails", new Coercing() { 18 | @Override 19 | public Object serialize(Object dataFetcherResult) { 20 | return serializeEmail(dataFetcherResult); 21 | } 22 | 23 | @Override 24 | public Object parseValue(Object input) { 25 | return parseEmailFromVariable(input); 26 | } 27 | 28 | @Override 29 | public Object parseLiteral(Object input) { 30 | return parseEmailFromAstLiteral(input); 31 | } 32 | }); 33 | 34 | 35 | private static boolean looksLikeAnEmailAddress(String possibleEmailValue) { 36 | return Pattern.matches("^[A-Za-z0-9\\u4e00-\\u9fa5]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$", possibleEmailValue); 37 | } 38 | 39 | private static Object serializeEmail(Object dataFetcherResult) { 40 | String possibleEmailValue = String.valueOf(dataFetcherResult); 41 | if (looksLikeAnEmailAddress(possibleEmailValue)) { 42 | return possibleEmailValue; 43 | } else { 44 | throw new CoercingSerializeException("Unable to serialize " + possibleEmailValue + " as an email address"); 45 | } 46 | } 47 | 48 | private static Object parseEmailFromVariable(Object input) { 49 | if (input instanceof String) { 50 | String possibleEmailValue = input.toString(); 51 | if (looksLikeAnEmailAddress(possibleEmailValue)) { 52 | return possibleEmailValue; 53 | } 54 | } 55 | throw new CoercingParseValueException("Unable to parse variable value " + input + " as an email address"); 56 | } 57 | 58 | private static Object parseEmailFromAstLiteral(Object input) { 59 | if (input instanceof StringValue) { 60 | String possibleEmailValue = ((StringValue) input).getValue(); 61 | if (looksLikeAnEmailAddress(possibleEmailValue)) { 62 | return possibleEmailValue; 63 | } 64 | } 65 | throw new CoercingParseLiteralException( 66 | "Value is not any email address : '" + input + "'" 67 | ); 68 | } 69 | } -------------------------------------------------------------------------------- /graphql-complete/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/graphql-complete/src/main/resources/application.properties -------------------------------------------------------------------------------- /graphql-complete/src/main/resources/starWarsSchemaAnnotated.graphqls: -------------------------------------------------------------------------------- 1 | scalar Email #一定要在最开始定义自定义标量 2 | 3 | # 背景是星球大战 4 | # 必须至少具有一个查询根类型 5 | # 6 | schema { 7 | query: Query 8 | } 9 | 10 | #定义查询 11 | type Query { 12 | #指定一个Episode类型的参数 13 | hero(episode: Episode) : Character 14 | #指定一个String类型的id 15 | human(id : String) : Human 16 | #返回所有的人类列表 17 | humans: [Human] 18 | #指定一个String类型的非空id 19 | droid(id: ID!) : Droid 20 | } 21 | #定义枚举类型 电影 指星球大战系列 22 | enum Episode { 23 | NEWHOPE 24 | EMPIRE 25 | JEDI 26 | } 27 | 28 | #定义接口 角色 29 | #文档https://graphql.org/learn/schema/ 30 | interface Character { 31 | #角色的id,非人类可读的唯一性id,这里没搞明白 32 | id: ID! 33 | #角色名字 34 | name: String! 35 | #角色的朋友,如果没有,则为空列表,[]表示数组,!表示不为空 36 | friends: [Character] 37 | #出现在哪些电影中 38 | appearsIn: [Episode]! 39 | #所有关于他们过去的秘密。 40 | secretBackstory : String @deprecated(reason : "We have decided that this is not canon") 41 | } 42 | 43 | #人 44 | type Human implements Character { 45 | id: ID! 46 | name: String! 47 | friends: [Character] 48 | appearsIn: [Episode]! 49 | homePlanet: String 50 | secretBackstory : String @deprecated(reason : "We have decided that this is not canon") 51 | # 自定义标量 52 | email: Email! 53 | } 54 | 55 | #机器人 56 | type Droid implements Character { 57 | id: ID! 58 | name: String! 59 | friends: [Character] 60 | appearsIn: [Episode]! 61 | primaryFunction: String 62 | secretBackstory : String @deprecated(reason : "We have decided that this is not canon") 63 | } 64 | -------------------------------------------------------------------------------- /graphql/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | com.github.dreamylost 8 | graphql 9 | 0.0.1-SNAPSHOT 10 | jar 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-parent 15 | 1.5.10.RELEASE 16 | 17 | 18 | 19 | 20 | UTF-8 21 | UTF-8 22 | 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-web 28 | 29 | 30 | com.graphql-java 31 | graphql-java 32 | 13.0 33 | 34 | 35 | com.google.guava 36 | guava 37 | 29.0-jre 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | org.apache.maven.plugins 46 | maven-compiler-plugin 47 | 48 | 8 49 | 8 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /graphql/src/main/java/com/github/dreamylost/Application.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | //启动并访问http://localhost:8080/ 7 | @SpringBootApplication 8 | public class Application { 9 | 10 | public static void main(String[] args) { 11 | SpringApplication.run(Application.class, args); 12 | } 13 | } -------------------------------------------------------------------------------- /graphql/src/main/java/com/github/dreamylost/GraphQLDataFetchers.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import graphql.schema.DataFetcher; 4 | import org.springframework.stereotype.Component; 5 | 6 | 7 | /** 8 | * 获取数据 9 | * 10 | * @author 梦境迷离 11 | * @time 2020年03月24日17:57:08 12 | */ 13 | @Component 14 | public class GraphQLDataFetchers { 15 | 16 | 17 | public DataFetcher getHelloWorldDataFetcher() { 18 | return environment -> "world"; 19 | } 20 | 21 | public DataFetcher getEchoDataFetcher() { 22 | return environment -> environment.getArgument("toEcho"); 23 | } 24 | 25 | 26 | } -------------------------------------------------------------------------------- /graphql/src/main/java/com/github/dreamylost/GraphQLProvider.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import com.google.common.base.Charsets; 4 | import com.google.common.io.Resources; 5 | import graphql.GraphQL; 6 | import graphql.schema.GraphQLSchema; 7 | import graphql.schema.idl.RuntimeWiring; 8 | import graphql.schema.idl.SchemaGenerator; 9 | import graphql.schema.idl.SchemaParser; 10 | import graphql.schema.idl.TypeDefinitionRegistry; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.stereotype.Component; 14 | 15 | import javax.annotation.PostConstruct; 16 | import java.io.IOException; 17 | import java.net.URL; 18 | 19 | import static graphql.schema.idl.TypeRuntimeWiring.newTypeWiring; 20 | 21 | 22 | /** 23 | * 运行时织入 24 | * 25 | * @author 梦境迷离 26 | * @time 2020年03月24日17:57:08 27 | */ 28 | @Component 29 | public class GraphQLProvider { 30 | 31 | 32 | @Autowired 33 | GraphQLDataFetchers graphQLDataFetchers; 34 | 35 | private GraphQL graphQL; 36 | 37 | //初始化 构造gql 加载schema 38 | @PostConstruct 39 | public void init() throws IOException { 40 | //加载schema 41 | URL url = Resources.getResource("schema.graphql"); 42 | String sdl = Resources.toString(url, Charsets.UTF_8); 43 | GraphQLSchema graphQLSchema = buildSchema(sdl); 44 | this.graphQL = GraphQL.newGraphQL(graphQLSchema).build(); 45 | } 46 | 47 | private GraphQLSchema buildSchema(String sdl) { 48 | TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(sdl); 49 | RuntimeWiring runtimeWiring = buildWiring(); 50 | SchemaGenerator schemaGenerator = new SchemaGenerator(); 51 | return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring); 52 | } 53 | 54 | private RuntimeWiring buildWiring() { 55 | return RuntimeWiring.newRuntimeWiring() 56 | .type(newTypeWiring("Query") 57 | //指定好数据获取方法 58 | .dataFetcher("hello", graphQLDataFetchers.getHelloWorldDataFetcher()) 59 | .dataFetcher("echo", graphQLDataFetchers.getEchoDataFetcher()) 60 | .build()) 61 | .build(); 62 | 63 | } 64 | 65 | @Bean 66 | public GraphQL graphQL() { 67 | return graphQL; 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /graphql/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/graphql/src/main/resources/application.properties -------------------------------------------------------------------------------- /graphql/src/main/resources/schema.graphql: -------------------------------------------------------------------------------- 1 | type Query { 2 | #定义无参方法 3 | hello: String 4 | #定义有参方法 5 | echo(toEcho: String): String 6 | } -------------------------------------------------------------------------------- /mongodb/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 4.0.0 6 | 7 | com.github.dreamylost 8 | mongodb 9 | 0.0.1-SNAPSHOT 10 | jar 11 | 12 | mongodb 13 | http://maven.apache.org 14 | 15 | 16 | 17 | org.springframework.boot 18 | spring-boot-starter-parent 19 | 1.5.6.RELEASE 20 | 21 | 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter 27 | 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-web 33 | 34 | 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-data-mongodb 39 | 40 | 41 | 42 | 43 | 44 | org.apache.maven.plugins 45 | maven-compiler-plugin 46 | 47 | 8 48 | 8 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /mongodb/src/main/java/com/github/dreamylost/Application.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Application.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /mongodb/src/main/java/com/github/dreamylost/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.controller; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.data.mongodb.core.MongoTemplate; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RequestParam; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import com.github.dreamylost.entity.User; 12 | import com.github.dreamylost.service.UserService; 13 | 14 | @RestController 15 | public class TestController { 16 | @Autowired 17 | private UserService userService; 18 | @Autowired 19 | private MongoTemplate mongoTemplate; 20 | 21 | /** 22 | * 新增 23 | * 24 | * @return 25 | */ 26 | @GetMapping("/save") 27 | public User save() { 28 | User user = new User((int) (Math.random() * 100), "mongodb", 21); 29 | mongoTemplate.save(user);// 简便,没有封装在服务层 30 | return user; 31 | } 32 | 33 | /** 34 | * 无参数查询 35 | * 36 | * @author 梦境迷离. 37 | * @time 2018年5月12日 38 | * @version v1.0 39 | * @return list列表 40 | */ 41 | @GetMapping("/find") 42 | public List find() { 43 | List userList = mongoTemplate.findAll(User.class); 44 | return userList; 45 | } 46 | 47 | /** 48 | * 有参数查询 49 | * 50 | * @param name 51 | * @return 52 | */ 53 | @GetMapping("/findByName") 54 | public User findByName(@RequestParam("name") String name) { 55 | User user = userService.findByName(name); 56 | return user; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /mongodb/src/main/java/com/github/dreamylost/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.entity; 2 | 3 | import org.springframework.data.annotation.Id; 4 | 5 | public class User { 6 | 7 | /** 8 | * 使用自定义id 9 | */ 10 | @Id 11 | private Integer id; 12 | private String name; 13 | private int age; 14 | 15 | public User(Integer id, String name, int age) { 16 | this.id = id; 17 | this.name = name; 18 | this.age = age; 19 | } 20 | 21 | public Integer getId() { 22 | return id; 23 | } 24 | 25 | public void setId(Integer id) { 26 | this.id = id; 27 | } 28 | 29 | public String getName() { 30 | return name; 31 | } 32 | 33 | public void setName(String name) { 34 | this.name = name; 35 | } 36 | 37 | public int getAge() { 38 | return age; 39 | } 40 | 41 | public void setAge(int age) { 42 | this.age = age; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "User{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /mongodb/src/main/java/com/github/dreamylost/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.repository; 2 | 3 | import org.springframework.data.mongodb.repository.MongoRepository; 4 | 5 | import com.github.dreamylost.entity.User; 6 | 7 | /** 8 | * 类似JPA 9 | * 10 | * 定义基础CRUD操作DAO 11 | */ 12 | public interface UserRepository extends MongoRepository { 13 | 14 | User findByName(String name); 15 | } 16 | -------------------------------------------------------------------------------- /mongodb/src/main/java/com/github/dreamylost/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.service; 2 | 3 | import org.springframework.stereotype.Repository; 4 | 5 | import com.github.dreamylost.entity.User; 6 | 7 | /** 8 | * 定义业务特有的CRUD接口 9 | */ 10 | @Repository 11 | public interface UserService { 12 | void save(User user); 13 | 14 | User findByName(String name); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /mongodb/src/main/java/com/github/dreamylost/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.service.impl; 2 | 3 | import com.github.dreamylost.repository.UserRepository; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Service; 6 | 7 | import com.github.dreamylost.entity.User; 8 | import com.github.dreamylost.service.UserService; 9 | 10 | /** 11 | * 实现业务的操作,并封装MongoTemplate 12 | * 13 | * 此处并未封装 14 | */ 15 | @Service 16 | public class UserServiceImpl implements UserService { 17 | @Autowired 18 | private UserRepository userRepository; 19 | 20 | public void save(User user) { 21 | userRepository.save(user); 22 | } 23 | 24 | public User findByName(String name) { 25 | return this.userRepository.findByName(name); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /mongodb/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | #配置mongodb参数 2 | spring: 3 | data: 4 | mongodb: 5 | host: 127.0.0.1 6 | port: 27017 7 | database: mydb 8 | #配置server参数 9 | server: 10 | port: 9000 11 | -------------------------------------------------------------------------------- /redis/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 4.0.0 6 | com.github.dreamylost 7 | redis 8 | 0.0.1-SNAPSHOT 9 | jar 10 | redis 11 | 12 | 13 | UTF-8 14 | 15 | 16 | 17 | org.springframework.boot 18 | spring-boot-starter-parent 19 | 1.5.10.RELEASE 20 | 21 | 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-web 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-data-redis 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-cache 35 | 36 | 37 | 38 | 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-maven-plugin 43 | 44 | 45 | org.apache.maven.plugins 46 | maven-compiler-plugin 47 | 48 | 8 49 | 8 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /redis/src/main/java/com/github/dreamylost/Application.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Application.class, args); 11 | } 12 | } -------------------------------------------------------------------------------- /redis/src/main/java/com/github/dreamylost/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 4 | import com.fasterxml.jackson.annotation.PropertyAccessor; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import org.springframework.cache.annotation.CachingConfigurerSupport; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.data.redis.connection.RedisConnectionFactory; 10 | import org.springframework.data.redis.core.RedisTemplate; 11 | import org.springframework.data.redis.core.ValueOperations; 12 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 13 | import org.springframework.data.redis.serializer.StringRedisSerializer; 14 | 15 | @Configuration 16 | //@EnableCaching 17 | public class RedisConfig extends CachingConfigurerSupport { 18 | 19 | // /** 20 | // * 选择redis作为默认缓存工具 21 | // */ 22 | // @Bean 23 | // public CacheManager cacheManager(RedisTemplate redisTemplate) { 24 | // RedisCacheManager rcm = new RedisCacheManager(redisTemplate); 25 | // return rcm; 26 | // } 27 | 28 | /** 29 | * retemplate相关配置 30 | */ 31 | @Bean 32 | public RedisTemplate redisTemplate(RedisConnectionFactory factory) { 33 | RedisTemplate template = new RedisTemplate<>(); 34 | // 配置连接工厂 35 | template.setConnectionFactory(factory); 36 | //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式) 37 | Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class); 38 | ObjectMapper om = new ObjectMapper(); 39 | // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public 40 | om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 41 | // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常 42 | om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 43 | jacksonSeial.setObjectMapper(om); 44 | // 值采用json序列化 45 | template.setValueSerializer(jacksonSeial); 46 | //使用StringRedisSerializer来序列化和反序列化redis的key值 47 | template.setKeySerializer(new StringRedisSerializer()); 48 | // 设置hash key 和value序列化模式 49 | template.setHashKeySerializer(new StringRedisSerializer()); 50 | template.setHashValueSerializer(jacksonSeial); 51 | template.afterPropertiesSet(); 52 | 53 | return template; 54 | } 55 | 56 | /** 57 | * 对redis字符串类型数据操作 58 | */ 59 | @Bean 60 | public ValueOperations valueOperations(RedisTemplate redisTemplate) { 61 | return redisTemplate.opsForValue(); 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /redis/src/main/java/com/github/dreamylost/TestController.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.data.redis.core.RedisTemplate; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.ResponseBody; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | public class TestController { 11 | 12 | @Autowired 13 | RedisTemplate redisTemplate; 14 | 15 | //输入测试地址 http://localhost:8081/?p=90909 16 | @RequestMapping("/") 17 | @ResponseBody 18 | public User hello(String p) { 19 | System.out.println("have a request"); 20 | //redis-cli get hello 21 | //查看value [\"com.github.dreamylost.User\",{\"uid\":123,\"userName\":\"zhangsan\",\"passWord\":\"pwd\"}] 22 | redisTemplate.opsForValue().set("hello", new User(123, "zhangsan", p)); 23 | User s = (User) redisTemplate.opsForValue().get("hello"); 24 | return s; 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /redis/src/main/java/com/github/dreamylost/User.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 用于测试的实体类 7 | */ 8 | public class User implements Serializable { 9 | 10 | private static final long serialVersionUID = 1L; 11 | private int uid; 12 | private String userName; 13 | private String passWord; 14 | 15 | public int getUid() { 16 | return uid; 17 | } 18 | 19 | public void setUid(int uid) { 20 | this.uid = uid; 21 | } 22 | 23 | public String getUserName() { 24 | return userName; 25 | } 26 | 27 | public void setUserName(String userName) { 28 | this.userName = userName; 29 | } 30 | 31 | public String getPassWord() { 32 | return passWord; 33 | } 34 | 35 | public void setPassWord(String passWord) { 36 | this.passWord = passWord; 37 | } 38 | 39 | 40 | public User(int uid, String userName, String passWord) { 41 | super(); 42 | this.uid = uid; 43 | this.userName = userName; 44 | this.passWord = passWord; 45 | } 46 | 47 | public User() { 48 | super(); 49 | } 50 | } -------------------------------------------------------------------------------- /redis/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8081 3 | #数据库连接 4 | spring: 5 | redis: 6 | ## Redis数据库索引(默认为0) 7 | database: 0 8 | ## Redis服务器地址 9 | host: 127.0.0.1 10 | ## Redis服务器连接端口 11 | port: 6379 12 | ## Redis服务器连接密码(默认为空) 13 | password: 14 | jedis: 15 | pool: 16 | ## 连接池最大连接数(使用负值表示没有限制) 17 | #spring.redis.pool.max-active=8 18 | max-active: 8 19 | ## 连接池最大阻塞等待时间(使用负值表示没有限制) 20 | # spring.redis.pool.max-wait=-1 21 | max-wait: -1 22 | ## 连接池中的最大空闲连接 23 | # spring.redis.pool.max-idle=8 24 | max-idle: 8 25 | ## 连接池中的最小空闲连接 26 | # spring.redis.pool.min-idle=0 27 | min-idle: 0 28 | ## 连接超时时间(毫秒) 29 | timeout: 1200 -------------------------------------------------------------------------------- /swagger/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.github.dreamylost 8 | swagger 9 | 0.0.1-SNAPSHOT 10 | jar 11 | 12 | swagger 13 | Demo project for Spring Boot 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-parent 18 | 1.5.9.RELEASE 19 | 20 | 21 | 22 | 23 | UTF-8 24 | UTF-8 25 | 26 | 27 | 28 | 29 | io.springfox 30 | springfox-swagger2 31 | 2.2.2 32 | 33 | 34 | io.springfox 35 | springfox-swagger-ui 36 | 2.2.2 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-web 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-test 50 | test 51 | 52 | 53 | 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-maven-plugin 59 | 60 | 61 | org.apache.maven.plugins 62 | maven-compiler-plugin 63 | 64 | 8 65 | 8 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /swagger/src/main/java/com/github/dreamylost/Application.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Configuration 8 | @SpringBootApplication 9 | public class Application { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(Application.class, args); 13 | } 14 | } -------------------------------------------------------------------------------- /swagger/src/main/java/com/github/dreamylost/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import springfox.documentation.builders.ApiInfoBuilder; 6 | import springfox.documentation.builders.ParameterBuilder; 7 | import springfox.documentation.builders.PathSelectors; 8 | import springfox.documentation.builders.RequestHandlerSelectors; 9 | import springfox.documentation.schema.ModelRef; 10 | import springfox.documentation.service.ApiInfo; 11 | import springfox.documentation.service.Parameter; 12 | import springfox.documentation.spi.DocumentationType; 13 | import springfox.documentation.spring.web.plugins.Docket; 14 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | /** 20 | * swagger配置 21 | * 22 | * @author 梦境迷离. 23 | * @version v1.0 24 | * @time 2018年5月28日 25 | */ 26 | @Configuration 27 | @EnableSwagger2 28 | public class SwaggerConfig { 29 | 30 | /** 31 | * swagger2的配置文件,这里可以配置swagger2的一些基本的内容,比如扫描的包等等 32 | * 33 | * @return 34 | * @author 梦境迷离. 35 | * @time 2018年5月28日 36 | * @version v1.0 37 | */ 38 | @Bean 39 | public Docket createRestApi() { 40 | ParameterBuilder tokenPar = new ParameterBuilder(); 41 | List pars = new ArrayList<>(); 42 | tokenPar.name("token").description("令牌").modelRef(new ModelRef("string")).parameterType("query").required(false) 43 | .build(); 44 | pars.add(tokenPar.build()); 45 | return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select() 46 | .apis(RequestHandlerSelectors.basePackage("cn.edu.jxnu.swagger")).paths(PathSelectors.any()).build() 47 | .globalOperationParameters(pars); 48 | } 49 | 50 | private ApiInfo apiInfo() { 51 | return new ApiInfoBuilder() 52 | // 页面标题 53 | .title("个人测试") 54 | // 创建人 55 | .description("个人测试用API").termsOfServiceUrl("https://blog.csdn.net/qq_34446485") 56 | // 创建人 57 | .contact("测试") 58 | // 版本号 59 | .version("1.0").build(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /swagger/src/main/java/com/github/dreamylost/TestController.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import io.swagger.annotations.Api; 4 | import io.swagger.annotations.ApiImplicitParam; 5 | import io.swagger.annotations.ApiImplicitParams; 6 | import io.swagger.annotations.ApiOperation; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | /** 11 | * 浏览器访问 http://localhost:8080/swagger-ui.html 12 | */ 13 | @RestController 14 | @RequestMapping("test") 15 | // 这个注解用于整个类上,对整个类中的接口列表进行简单说明 16 | @Api(value = "测试接口Controller") 17 | public class TestController { 18 | 19 | // value 和notes都是对接口的说明,是显示的位置不一样 20 | // httpMethod 是接口的提交方法,如果不写的话swagger会把所有的提交方式都展示一遍就像这样 21 | @ApiOperation(value = "测试用接口", notes = "测试用接口", httpMethod = "POST") 22 | @ApiImplicitParams({ 23 | @ApiImplicitParam(name = "name", value = "用户姓名", dataType = "String", required = true, paramType = "form"), 24 | @ApiImplicitParam(name = "id", value = "id", dataType = "int", required = false, paramType = "form")}) 25 | @RequestMapping("word") 26 | public String HelloWord(String name, Integer id) { 27 | return "Hello Word"; 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /swagger/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/swagger/src/main/resources/application.properties -------------------------------------------------------------------------------- /swagger/src/test/java/com/github/dreamylost/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /undertow/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | com.github.dreamylost 8 | undertow 9 | 0.0.1-SNAPSHOT 10 | undertow 11 | jar 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | org.springframework.boot 19 | spring-boot-starter-parent 20 | 1.5.10.RELEASE 21 | 22 | 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-web 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-tomcat 33 | 34 | 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-undertow 40 | 41 | 42 | 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-maven-plugin 48 | 49 | 50 | org.apache.maven.plugins 51 | maven-compiler-plugin 52 | 53 | 8 54 | 8 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /undertow/src/main/java/com/github/dreamylost/Application.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Application.class, args); 11 | } 12 | } -------------------------------------------------------------------------------- /undertow/src/main/java/com/github/dreamylost/TestController.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost; 2 | 3 | import io.undertow.UndertowOptions; 4 | import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.ResponseBody; 9 | 10 | @Controller 11 | public class TestController { 12 | 13 | 14 | @Bean 15 | UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() { 16 | UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory(); 17 | //这里也可以做其他配置 18 | factory.addBuilderCustomizers(builder -> builder.setServerOption(UndertowOptions.MAX_COOKIES, 2000)); 19 | 20 | return factory; 21 | } 22 | 23 | 24 | @RequestMapping("/") 25 | @ResponseBody 26 | public String home() { 27 | return "Hello World!"; 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /undertow/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8084 3 | http2: 4 | #是否开启HTTP2 5 | enabled: true 6 | undertow: 7 | # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程 8 | io-threads: 16 9 | # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载 10 | worker-threads: 256 11 | # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理 12 | buffer-size: 1024 13 | # 是否分配直接内存 14 | direct-buffers: true -------------------------------------------------------------------------------- /webflow-booking/src/main/java/com/github/dreamylost/booking/config/DataSourceConfig.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.booking.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.ComponentScan; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.jdbc.datasource.DriverManagerDataSource; 7 | import org.springframework.orm.jpa.JpaTransactionManager; 8 | import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; 9 | import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; 10 | import org.springframework.transaction.PlatformTransactionManager; 11 | import org.springframework.transaction.annotation.EnableTransactionManagement; 12 | 13 | import javax.persistence.EntityManagerFactory; 14 | import javax.sql.DataSource; 15 | import java.util.Collections; 16 | 17 | 18 | /** 19 | * 数据源 配置bean 20 | */ 21 | @Configuration 22 | @EnableTransactionManagement 23 | @ComponentScan(basePackages = "com.github.dreamylost.booking") 24 | public class DataSourceConfig { 25 | 26 | @Bean 27 | public PlatformTransactionManager transactionManager(EntityManagerFactory emf) { 28 | JpaTransactionManager txManager = new JpaTransactionManager(); 29 | txManager.setEntityManagerFactory(emf); 30 | return txManager; 31 | } 32 | 33 | @Bean 34 | public LocalContainerEntityManagerFactoryBean entityManagerFactory() { 35 | LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); 36 | emf.setDataSource(dataSource()); 37 | emf.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); 38 | emf.setJpaPropertyMap(Collections.singletonMap("hibernate.session_factory_name", "mySessionFactory")); 39 | return emf; 40 | } 41 | 42 | @Bean 43 | public DataSource dataSource() { 44 | DriverManagerDataSource dataSource = new DriverManagerDataSource("jdbc:hsqldb:mem:booking", "sa", ""); 45 | dataSource.setDriverClassName("org.hsqldb.jdbcDriver"); 46 | return dataSource; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /webflow-booking/src/main/java/com/github/dreamylost/booking/config/DispatcherServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.booking.config; 2 | 3 | import org.springframework.web.filter.HiddenHttpMethodFilter; 4 | import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; 5 | 6 | import javax.servlet.Filter; 7 | 8 | /** 9 | * servlet初始化加载配置 10 | */ 11 | public class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 12 | 13 | @Override 14 | protected Class[] getRootConfigClasses() { 15 | return new Class[]{ 16 | SecurityConfig.class, 17 | DataSourceConfig.class, 18 | WebMvcConfig.class, 19 | WebFlowConfig.class 20 | }; 21 | } 22 | 23 | @Override 24 | protected Class[] getServletConfigClasses() { 25 | return null; 26 | } 27 | 28 | @Override 29 | protected String[] getServletMappings() { 30 | return new String[]{"/"}; 31 | } 32 | 33 | @Override 34 | protected Filter[] getServletFilters() { 35 | return new Filter[]{new HiddenHttpMethodFilter()}; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /webflow-booking/src/main/java/com/github/dreamylost/booking/config/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.booking.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 5 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 6 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 7 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 8 | 9 | /** 10 | * 权限配置 11 | */ 12 | @Configuration 13 | @EnableWebSecurity 14 | public class SecurityConfig extends WebSecurityConfigurerAdapter { 15 | 16 | @Override 17 | protected void configure(HttpSecurity http) throws Exception { 18 | http 19 | .formLogin() 20 | .loginPage("/login") 21 | .loginProcessingUrl("/loginProcess") 22 | .defaultSuccessUrl("/hotels/search") 23 | .failureUrl("/login?login_error=1") 24 | .and() 25 | .logout() 26 | .logoutUrl("/logout") 27 | .logoutSuccessUrl("/logoutSuccess"); 28 | } 29 | 30 | @Override 31 | protected void configure(AuthenticationManagerBuilder auth) throws Exception { 32 | auth.inMemoryAuthentication() 33 | .withUser("keith").password("{MD5}417c7382b16c395bc25b5da1398cf076").roles("USER", "SUPERVISOR").and() 34 | .withUser("erwin").password("{MD5}12430911a8af075c6f41c6976af22b09").roles("USER", "SUPERVISOR").and() 35 | .withUser("jeremy").password("{MD5}57c6cbff0d421449be820763f03139eb").roles("USER").and() 36 | .withUser("scott").password("{MD5}942f2339bf50796de535a384f0d1af3e").roles("USER"); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /webflow-booking/src/main/java/com/github/dreamylost/booking/config/SecurityWebApplicationInitializer.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.booking.config; 2 | 3 | import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; 4 | 5 | public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer { 6 | } 7 | -------------------------------------------------------------------------------- /webflow-booking/src/main/java/com/github/dreamylost/booking/config/WebFlowConfig.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.booking.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; 7 | import org.springframework.webflow.config.AbstractFlowConfiguration; 8 | import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; 9 | import org.springframework.webflow.engine.builder.support.FlowBuilderServices; 10 | import org.springframework.webflow.executor.FlowExecutor; 11 | import org.springframework.webflow.mvc.builder.MvcViewFactoryCreator; 12 | import org.springframework.webflow.security.SecurityFlowExecutionListener; 13 | 14 | import java.util.Collections; 15 | 16 | /** 17 | * webflow应用配置 18 | */ 19 | @Configuration 20 | public class WebFlowConfig extends AbstractFlowConfiguration { 21 | 22 | @Autowired 23 | private WebMvcConfig webMvcConfig; 24 | 25 | //1.流程执行器 26 | @Bean 27 | public FlowExecutor flowExecutor() { 28 | return getFlowExecutorBuilder(flowRegistry()) 29 | .addFlowExecutionListener(new SecurityFlowExecutionListener(), "*") 30 | .build(); 31 | } 32 | 33 | //2.流程注册表 34 | @Bean 35 | public FlowDefinitionRegistry flowRegistry() { 36 | return getFlowDefinitionRegistryBuilder(flowBuilderServices()) 37 | .setBasePath("/WEB-INF") 38 | //booking/booking-flow.xml 39 | .addFlowLocationPattern("/**/*-flow.xml").build(); 40 | } 41 | 42 | //视图工厂 43 | @Bean 44 | public FlowBuilderServices flowBuilderServices() { 45 | return getFlowBuilderServicesBuilder() 46 | .setViewFactoryCreator(mvcViewFactoryCreator()) 47 | .setValidator(validator()) 48 | .setDevelopmentMode(true) 49 | .build(); 50 | } 51 | 52 | @Bean 53 | public MvcViewFactoryCreator mvcViewFactoryCreator() { 54 | MvcViewFactoryCreator factoryCreator = new MvcViewFactoryCreator(); 55 | factoryCreator.setViewResolvers(Collections.singletonList(this.webMvcConfig.viewResolver())); 56 | factoryCreator.setUseSpringBeanBinding(true); 57 | return factoryCreator; 58 | } 59 | 60 | @Bean 61 | public LocalValidatorFactoryBean validator() { 62 | return new LocalValidatorFactoryBean(); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /webflow-booking/src/main/java/com/github/dreamylost/booking/controller/HotelsController.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.booking.controller; 2 | 3 | import com.github.dreamylost.booking.mode.Booking; 4 | import com.github.dreamylost.booking.mode.Hotel; 5 | import com.github.dreamylost.booking.mode.SearchCriteria; 6 | import com.github.dreamylost.booking.service.BookingService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.ui.Model; 10 | import org.springframework.web.bind.annotation.DeleteMapping; 11 | import org.springframework.web.bind.annotation.GetMapping; 12 | import org.springframework.web.bind.annotation.PathVariable; 13 | 14 | import java.security.Principal; 15 | import java.util.List; 16 | 17 | /** 18 | * 前端接口 19 | */ 20 | @Controller 21 | public class HotelsController { 22 | 23 | private BookingService bookingService; 24 | 25 | @Autowired 26 | public HotelsController(BookingService bookingService) { 27 | this.bookingService = bookingService; 28 | } 29 | 30 | @GetMapping("/hotels/search") 31 | public void search(SearchCriteria searchCriteria, Principal currentUser, Model model) { 32 | if (currentUser != null) { 33 | List booking = bookingService.findBookings(currentUser.getName()); 34 | model.addAttribute(booking); 35 | } 36 | } 37 | 38 | @GetMapping("/hotels") 39 | public String list(SearchCriteria criteria, Model model) { 40 | List hotels = bookingService.findHotels(criteria); 41 | model.addAttribute(hotels); 42 | return "hotels/list"; 43 | } 44 | 45 | @GetMapping("/hotels/{id}") 46 | public String show(@PathVariable Long id, Model model) { 47 | model.addAttribute(bookingService.findHotelById(id)); 48 | return "hotels/show"; 49 | } 50 | 51 | @DeleteMapping("/bookings/{id}") 52 | public String deleteBooking(@PathVariable Long id) { 53 | bookingService.cancelBooking(id); 54 | return "redirect:../hotels/search"; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /webflow-booking/src/main/java/com/github/dreamylost/booking/mode/Hotel.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.booking.mode; 2 | 3 | 4 | import javax.persistence.Column; 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.Id; 8 | import java.io.Serializable; 9 | import java.math.BigDecimal; 10 | 11 | /** 12 | * 用户可以预订住宿的酒店(旅馆)。 13 | */ 14 | @Entity 15 | public class Hotel implements Serializable { 16 | private Long id; 17 | 18 | private String name; 19 | 20 | private String address; 21 | 22 | private String city; 23 | 24 | private String state; 25 | 26 | private String zip; 27 | 28 | private String country; 29 | 30 | private BigDecimal price; 31 | 32 | @Id 33 | @GeneratedValue 34 | public Long getId() { 35 | return id; 36 | } 37 | 38 | public void setId(Long id) { 39 | this.id = id; 40 | } 41 | 42 | public String getName() { 43 | return name; 44 | } 45 | 46 | public void setName(String name) { 47 | this.name = name; 48 | } 49 | 50 | public String getAddress() { 51 | return address; 52 | } 53 | 54 | public void setAddress(String address) { 55 | this.address = address; 56 | } 57 | 58 | public String getCity() { 59 | return city; 60 | } 61 | 62 | public void setCity(String city) { 63 | this.city = city; 64 | } 65 | 66 | public String getZip() { 67 | return zip; 68 | } 69 | 70 | public void setZip(String zip) { 71 | this.zip = zip; 72 | } 73 | 74 | public String getState() { 75 | return state; 76 | } 77 | 78 | public void setState(String state) { 79 | this.state = state; 80 | } 81 | 82 | public String getCountry() { 83 | return country; 84 | } 85 | 86 | public void setCountry(String country) { 87 | this.country = country; 88 | } 89 | 90 | @Column(precision = 6, scale = 2) 91 | public BigDecimal getPrice() { 92 | return price; 93 | } 94 | 95 | public void setPrice(BigDecimal price) { 96 | this.price = price; 97 | } 98 | 99 | public Booking createBooking(User user) { 100 | return new Booking(this, user); 101 | } 102 | 103 | @Override 104 | public String toString() { 105 | return "Hotel(" + name + "," + address + "," + city + "," + zip + ")"; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /webflow-booking/src/main/java/com/github/dreamylost/booking/mode/SearchCriteria.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.booking.mode; 2 | 3 | import java.io.Serializable; 4 | 5 | 6 | /** 7 | * 封装搜索条件 8 | */ 9 | public class SearchCriteria implements Serializable { 10 | 11 | private static final long serialVersionUID = 1L; 12 | 13 | /** 14 | * The user-provided search criteria for finding Hotels. 15 | */ 16 | private String searchString; 17 | 18 | /** 19 | * The maximum page size of the Hotel result list 20 | */ 21 | private int pageSize; 22 | 23 | /** 24 | * The current page of the Hotel result list. 25 | */ 26 | private int page; 27 | 28 | public String getSearchString() { 29 | return searchString; 30 | } 31 | 32 | public void setSearchString(String searchString) { 33 | this.searchString = searchString; 34 | } 35 | 36 | public int getPageSize() { 37 | return pageSize; 38 | } 39 | 40 | public void setPageSize(int pageSize) { 41 | this.pageSize = pageSize; 42 | } 43 | 44 | public int getPage() { 45 | return page; 46 | } 47 | 48 | public void setPage(int page) { 49 | this.page = page; 50 | } 51 | } -------------------------------------------------------------------------------- /webflow-booking/src/main/java/com/github/dreamylost/booking/mode/User.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.booking.mode; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.Id; 5 | import javax.persistence.Table; 6 | import java.io.Serializable; 7 | 8 | /** 9 | * 允许订购旅馆的用户 10 | */ 11 | @Entity 12 | @Table(name = "Customer") 13 | public class User implements Serializable { 14 | private String username; 15 | 16 | private String password; 17 | 18 | private String name; 19 | 20 | public User() { 21 | } 22 | 23 | public User(String username, String password, String name) { 24 | this.username = username; 25 | this.password = password; 26 | this.name = name; 27 | } 28 | 29 | @Id 30 | public String getUsername() { 31 | return username; 32 | } 33 | 34 | public void setUsername(String username) { 35 | this.username = username; 36 | } 37 | 38 | public String getPassword() { 39 | return password; 40 | } 41 | 42 | public void setPassword(String password) { 43 | this.password = password; 44 | } 45 | 46 | public String getName() { 47 | return name; 48 | } 49 | 50 | public void setName(String name) { 51 | this.name = name; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return "User(" + username + ")"; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /webflow-booking/src/main/java/com/github/dreamylost/booking/service/BookingService.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.booking.service; 2 | 3 | import com.github.dreamylost.booking.mode.Booking; 4 | import com.github.dreamylost.booking.mode.Hotel; 5 | import com.github.dreamylost.booking.mode.SearchCriteria; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * 服务层接口 11 | */ 12 | public interface BookingService { 13 | 14 | List findBookings(String username); 15 | 16 | List findHotels(SearchCriteria criteria); 17 | 18 | Hotel findHotelById(Long id); 19 | 20 | Booking createBooking(Long hotelId, String userName); 21 | 22 | void persistBooking(Booking booking); 23 | 24 | void cancelBooking(Long id); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /webflow-booking/src/main/java/com/github/dreamylost/booking/util/Amenity.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.booking.util; 2 | 3 | //旅馆设施类型 4 | public enum Amenity { 5 | OCEAN_VIEW, LATE_CHECKOUT, MINIBAR; 6 | } 7 | -------------------------------------------------------------------------------- /webflow-booking/src/main/java/com/github/dreamylost/booking/util/BookingDateRange.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.booking.util; 2 | 3 | import javax.validation.Constraint; 4 | import javax.validation.Payload; 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | /** 11 | * 注解 12 | */ 13 | @Constraint(validatedBy = BookingDateRangeValidator.class) 14 | @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | public @interface BookingDateRange { 17 | 18 | String message() default "Invalid check-in and check-out date range"; 19 | 20 | Class[] groups() default {}; 21 | 22 | Class[] payload() default {}; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /webflow-booking/src/main/java/com/github/dreamylost/booking/util/BookingDateRangeValidator.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.booking.util; 2 | 3 | import com.github.dreamylost.booking.mode.Booking; 4 | 5 | import javax.validation.ConstraintValidator; 6 | import javax.validation.ConstraintValidatorContext; 7 | 8 | /** 9 | * 注解实现 10 | */ 11 | public class BookingDateRangeValidator implements ConstraintValidator { 12 | 13 | public void initialize(BookingDateRange bookingDateRange) { 14 | } 15 | 16 | public boolean isValid(Booking booking, ConstraintValidatorContext context) { 17 | if ((booking.getCheckinDate() != null) && (booking.getCheckoutDate() != null) 18 | && booking.getCheckoutDate().before(booking.getCheckinDate())) { 19 | return false; 20 | } 21 | return true; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /webflow-booking/src/main/java/com/github/dreamylost/booking/util/BookingFlowHandler.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.booking.util; 2 | 3 | import org.springframework.webflow.core.FlowException; 4 | import org.springframework.webflow.execution.FlowExecutionOutcome; 5 | import org.springframework.webflow.execution.repository.NoSuchFlowExecutionException; 6 | import org.springframework.webflow.mvc.servlet.AbstractFlowHandler; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | 11 | /** 12 | * 实现自己的流程处理,异常时匹配/hotels/search 13 | */ 14 | public class BookingFlowHandler extends AbstractFlowHandler { 15 | 16 | private static final String DEFAULT_URL = "/hotels/search"; 17 | 18 | @Override 19 | public String handleExecutionOutcome(FlowExecutionOutcome outcome, HttpServletRequest req, HttpServletResponse res) { 20 | return DEFAULT_URL; 21 | } 22 | 23 | @Override 24 | public String handleException(FlowException e, HttpServletRequest request, HttpServletResponse response) { 25 | if (e instanceof NoSuchFlowExecutionException) { 26 | return DEFAULT_URL; 27 | } else { 28 | throw e; 29 | } 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /webflow-booking/src/main/resources/META-INF/persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | org.hibernate.ejb.HibernatePersistence 8 | com.github.dreamylost.booking.mode.User 9 | com.github.dreamylost.booking.mode.Booking 10 | com.github.dreamylost.booking.mode.Hotel 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /webflow-booking/src/main/resources/import.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/resources/import.sql -------------------------------------------------------------------------------- /webflow-booking/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | 3 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/WEB-INF/hotels/booking/booking-flow.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/WEB-INF/hotels/booking/messages.jsp: -------------------------------------------------------------------------------- 1 | <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 2 | 3 |
4 | 5 |
-------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/WEB-INF/hotels/booking/messages.properties: -------------------------------------------------------------------------------- 1 | booking.checkinDate.NotNull=The check in date is required 2 | booking.checkinDate.Future=The check in date must be in the future 3 | booking.checkinDate.beforeToday=The check in date must be a future date 4 | booking.checkinDate.typeMismatch=The check in date must be in the format mm-dd-yyyy 5 | 6 | booking.checkoutDate.Future=The check out date must be in the future 7 | booking.checkoutDate.NotNull=The check out date is required 8 | booking.checkoutDate.typeMismatch=The check out date must be in the format mm-dd-yyyy 9 | booking.BookingDateRange=The check out date must be later than the check in date 10 | 11 | booking.creditCard.NotEmpty=The credit card must be a valid 16 digit number 12 | booking.creditCardName.NotEmpty=The name on the credit card is required 13 | 14 | NotEmpty=The {0} field is required 15 | NotNull=The {0} field is required 16 | Future=The {0} date must be in the future -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/WEB-INF/hotels/booking/reviewBooking.jsp: -------------------------------------------------------------------------------- 1 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 | <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> 3 | <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 4 | 5 |
6 |
7 |

${booking.hotel.name}

8 | 9 |
10 | ${booking.hotel.address} 11 |
12 | ${booking.hotel.city}, ${booking.hotel.state}, ${booking.hotel.zip} 13 |
14 | ${booking.hotel.country} 15 |
16 |
17 |
18 | 19 |
20 | Confirm Booking Details 21 |
22 |
Check In:
23 |
24 |

${status.value}

25 |
26 |
27 |
28 |
Checkout:
29 |
30 |

${status.value}

31 |
32 |
33 |
34 |
Number of Nights:
35 |
36 |

${status.value}

37 |
38 |
39 |
40 |
Total Payment:
41 |
42 |

${status.value}

43 |
44 |
45 |
46 |
Credit Card #:
47 |
48 |

${booking.creditCard}

49 |
50 |
51 |
52 | 53 | 54 | 55 | 58 |
59 |
60 |
61 |
62 | 63 |
64 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/WEB-INF/hotels/booking/views.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/WEB-INF/hotels/bookingsTable.jsp: -------------------------------------------------------------------------------- 1 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 | <%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %> 3 | <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> 4 | <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 5 | 6 |
7 | 8 |

Current Hotel Bookings

9 | 10 | 11 | 12 | No bookings found 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 46 | 47 | 48 | 49 |
NameAddressCity, StateCheck in DateCheck out DateConfirmation NumberAction
${booking.hotel.name}${booking.hotel.address}${booking.hotel.city}, ${booking.hotel.state}${booking.checkinDate}${booking.checkoutDate}${booking.id} 39 | 40 | 41 | 42 | 43 | 44 | 45 |
50 |
51 |
52 | 53 |
-------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/WEB-INF/hotels/list.jsp: -------------------------------------------------------------------------------- 1 | <%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %> 2 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 3 | <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%> 4 | 5 |

Hotel Results

6 |

7 | Change Search 8 | 16 |

17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
NameAddressCity, StateZipAction
${hotel.name}${hotel.address}${hotel.city}, ${hotel.state}, ${hotel.country}${hotel.zip}View Hotel
No hotels found
46 |
47 |
48 | 49 | << Prev 50 | 57 | 58 |
59 |
60 | 61 | Next >> 62 | 69 | 70 |
71 |
72 |
73 |
74 | 75 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/WEB-INF/hotels/search.jsp: -------------------------------------------------------------------------------- 1 | <%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %> 2 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 3 | 4 | 5 | 6 | 7 |
${confirmed}
8 |
9 | 10 | 11 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/WEB-INF/hotels/searchForm.jsp: -------------------------------------------------------------------------------- 1 | <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 2 | <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> 3 | 4 |

Search Hotels

5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 | 14 | 20 |
21 |
22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 |
31 |
32 | 33 |
34 |
35 |
-------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/WEB-INF/hotels/show.jsp: -------------------------------------------------------------------------------- 1 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 | <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> 3 | <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 4 | 5 |

${hotel.name}

6 |
7 | ${hotel.address} 8 |
9 | ${hotel.city}, ${hotel.state}, ${hotel.zip} 10 |
11 | ${hotel.country} 12 |
13 |
14 |

15 | Nightly Rate: 16 | ${status.value} 17 |

18 | 19 |
20 | 21 |
22 |
23 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/WEB-INF/hotels/views.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/WEB-INF/intro.jsp: -------------------------------------------------------------------------------- 1 |
2 |

Welcome to Spring Travel

3 |

4 | This sample demonstrates how to use Spring MVC and Spring Web Flow together with JavaServerPages (JSP) and Tiles. 5 |

6 |
7 |

8 | The key features illustrated in this sample include: 9 |

10 |
    11 |
  • A declarative navigation model enabling full browser button support and dynamic navigation rules
  • 12 |
  • A fine-grained state management model, including support for ConversationScope and ViewScope
  • 13 |
  • Modularization of web application functionality by domain use case, illustrating project structure best-practices
  • 14 |
  • Spring Expression Language (SpEL) integration
  • 15 |
  • Spring 3 formatting annotations @DateTimeFormat, @NumberFormat
  • 16 |
  • Spring MVC custom namespace
  • 17 |
  • Spring Security integration
  • 18 |
  • Annotated POJO @Controllers for implementing RESTful user interactions.
  • 19 |
  • Declarative page authoring with JSP, JSTL, and Spring MVC's form tag library
  • 20 |
  • Page layout and composition with Apache Tiles
  • 21 |
  • A JavaScript API for decorating HTML elements with behaviors such as Ajax, validation, and effects.
  • 22 |
  • A grid layout with Blueprint CSS
  • 23 |
  • Exception handling support across all layers of the application
  • 24 |
  • SpringSource Tool Suite integration, with support for graphical flow modeling and visualization
  • 25 |
26 |

27 | Start your Spring Travel experience 28 |

29 |
30 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/WEB-INF/layouts/views.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/WEB-INF/login.jsp: -------------------------------------------------------------------------------- 1 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 | <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 3 | 4 |
5 |

Valid username/passwords are:

6 |
    7 |
  • keith/melbourne
  • 8 |
  • erwin/leuven
  • 9 |
  • jeremy/atlanta
  • 10 |
  • scott/rochester
  • 11 |
12 |
13 | 14 |
15 | 16 |
17 | Your login attempt was not successful, try again. 18 |
19 |
20 |
" method="post"> 21 |
22 | Login Information 23 |

24 | 25 |
26 | 27 |

28 | 34 |

35 | 36 |
37 | 38 |

39 | 45 |

46 | 47 | 48 |

49 | 54 |
55 | 56 |
57 |

58 | 59 | 62 |

63 |
64 |
65 |
66 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/WEB-INF/logoutSuccess.jsp: -------------------------------------------------------------------------------- 1 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 | 3 |
4 |

Logout

5 |

You have successfully logged out.

6 |
7 |

">Continue

8 |
9 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/WEB-INF/views.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/images/bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/images/bg.gif -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/images/btn.bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/images/btn.bg.gif -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/images/diplomat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/images/diplomat.jpg -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/images/header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/images/header.jpg -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/images/input.bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/images/input.bg.gif -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/images/powered-by-spring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/images/powered-by-spring.png -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/images/spring-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/images/spring-logo.jpg -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/images/springone2gx.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/images/springone2gx.jpeg -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/images/th.bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/images/th.bg.gif -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/images/tse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/images/tse.gif -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/images/webflow-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/images/webflow-logo.jpg -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/icons/cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/styles/blueprint/icons/cross.png -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/icons/key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/styles/blueprint/icons/key.png -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/icons/tick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/styles/blueprint/icons/tick.png -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/ie.css: -------------------------------------------------------------------------------- 1 | /* ----------------------------------------------------------------------- 2 | 3 | 4 | Blueprint CSS Framework 0.9 5 | http://blueprintcss.org 6 | 7 | * Copyright (c) 2007-Present. See LICENSE for more info. 8 | * See README for instructions on how to use Blueprint. 9 | * For credits and origins, see AUTHORS. 10 | * This is a compressed file. See the sources in the 'src' directory. 11 | 12 | ----------------------------------------------------------------------- */ 13 | 14 | /* ie.css */ 15 | body {text-align:center;} 16 | .container {text-align:left;} 17 | * html .column, * html div.span-1, * html div.span-2, * html div.span-3, * html div.span-4, * html div.span-5, * html div.span-6, * html div.span-7, * html div.span-8, * html div.span-9, * html div.span-10, * html div.span-11, * html div.span-12, * html div.span-13, * html div.span-14, * html div.span-15, * html div.span-16, * html div.span-17, * html div.span-18, * html div.span-19, * html div.span-20, * html div.span-21, * html div.span-22, * html div.span-23, * html div.span-24 {display:inline;overflow-x:hidden;} 18 | * html legend {margin:0px -8px 16px 0;padding:0;} 19 | ol {margin-left:2em;} 20 | sup {vertical-align:text-top;} 21 | sub {vertical-align:text-bottom;} 22 | html>body p code {*white-space:normal;} 23 | hr {margin:-8px auto 11px;} 24 | img {-ms-interpolation-mode:bicubic;} 25 | .clearfix, .container {display:inline-block;} 26 | * html .clearfix, * html .container {height:1%;} 27 | fieldset {padding-top:0;} 28 | textarea {overflow:auto;} 29 | input.text, input.title, textarea {background-color:#fff;border:1px solid #bbb;} 30 | input.text:focus, input.title:focus {border-color:#666;} 31 | input.text, input.title, textarea, select {margin:0.5em 0;} 32 | input.checkbox, input.radio {position:relative;top:.25em;} 33 | form.inline div, form.inline p {vertical-align:middle;} 34 | form.inline label {position:relative;top:-0.25em;} 35 | form.inline input.checkbox, form.inline input.radio, form.inline input.button, form.inline button {margin:0.5em 0;} 36 | button, input.button {position:relative;top:0.25em;} -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/buttons/icons/cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/styles/blueprint/plugins/buttons/icons/cross.png -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/buttons/icons/key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/styles/blueprint/plugins/buttons/icons/key.png -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/buttons/icons/tick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/styles/blueprint/plugins/buttons/icons/tick.png -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/buttons/readme.txt: -------------------------------------------------------------------------------- 1 | Buttons 2 | 3 | * Gives you great looking CSS buttons, for both and 25 | 26 | 27 | Change Password 28 | 29 | 30 | 31 | Cancel 32 | 33 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/buttons/screen.css: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------- 2 | 3 | buttons.css 4 | * Gives you some great CSS-only buttons. 5 | 6 | Created by Kevin Hale [particletree.com] 7 | * particletree.com/features/rediscovering-the-button-element 8 | 9 | See Readme.txt in this folder for instructions. 10 | 11 | -------------------------------------------------------------- */ 12 | 13 | a.button, button { 14 | display:block; 15 | float:left; 16 | margin: 0.7em 0.5em 0.7em 0; 17 | padding:5px 10px 5px 7px; /* Links */ 18 | 19 | border:1px solid #dedede; 20 | border-top:1px solid #eee; 21 | border-left:1px solid #eee; 22 | 23 | background-color:#f5f5f5; 24 | font-family:"Lucida Grande", Tahoma, Arial, Verdana, sans-serif; 25 | font-size:100%; 26 | line-height:130%; 27 | text-decoration:none; 28 | font-weight:bold; 29 | color:#565656; 30 | cursor:pointer; 31 | } 32 | button { 33 | width:auto; 34 | overflow:visible; 35 | padding:4px 10px 3px 7px; /* IE6 */ 36 | } 37 | button[type] { 38 | padding:4px 10px 4px 7px; /* Firefox */ 39 | line-height:17px; /* Safari */ 40 | } 41 | *:first-child+html button[type] { 42 | padding:4px 10px 3px 7px; /* IE7 */ 43 | } 44 | button img, a.button img{ 45 | margin:0 3px -3px 0 !important; 46 | padding:0; 47 | border:none; 48 | width:16px; 49 | height:16px; 50 | float:none; 51 | } 52 | 53 | 54 | /* Button colors 55 | -------------------------------------------------------------- */ 56 | 57 | /* Standard */ 58 | button:hover, a.button:hover{ 59 | background-color:#dff4ff; 60 | border:1px solid #c2e1ef; 61 | color:#336699; 62 | } 63 | a.button:active{ 64 | background-color:#6299c5; 65 | border:1px solid #6299c5; 66 | color:#fff; 67 | } 68 | 69 | /* Positive */ 70 | body .positive { 71 | color:#529214; 72 | } 73 | a.positive:hover, button.positive:hover { 74 | background-color:#E6EFC2; 75 | border:1px solid #C6D880; 76 | color:#529214; 77 | } 78 | a.positive:active { 79 | background-color:#529214; 80 | border:1px solid #529214; 81 | color:#fff; 82 | } 83 | 84 | /* Negative */ 85 | body .negative { 86 | color:#d12f19; 87 | } 88 | a.negative:hover, button.negative:hover { 89 | background-color:#fbe3e4; 90 | border:1px solid #fbc2c4; 91 | color:#d12f19; 92 | } 93 | a.negative:active { 94 | background-color:#d12f19; 95 | border:1px solid #d12f19; 96 | color:#fff; 97 | } 98 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/fancy-type/readme.txt: -------------------------------------------------------------------------------- 1 | Fancy Type 2 | 3 | * Gives you classes to use if you'd like some 4 | extra fancy typography. 5 | 6 | Credits and instructions are specified above each class 7 | in the fancy-type.css file in this directory. 8 | 9 | 10 | Usage 11 | ---------------------------------------------------------------- 12 | 13 | 1) Add this plugin to lib/settings.yml. 14 | See compress.rb for instructions. 15 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/fancy-type/screen.css: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------- 2 | 3 | fancy-type.css 4 | * Lots of pretty advanced classes for manipulating text. 5 | 6 | See the Readme file in this folder for additional instructions. 7 | 8 | -------------------------------------------------------------- */ 9 | 10 | /* Indentation instead of line shifts for sibling paragraphs. */ 11 | p + p { text-indent:2em; margin-top:-1.5em; } 12 | form p + p { text-indent: 0; } /* Don't want this in forms. */ 13 | 14 | 15 | /* For great looking type, use this code instead of asdf: 16 | asdf 17 | Best used on prepositions and ampersands. */ 18 | 19 | .alt { 20 | color: #666; 21 | font-family: "Warnock Pro", "Goudy Old Style","Palatino","Book Antiqua", Georgia, serif; 22 | font-style: italic; 23 | font-weight: normal; 24 | } 25 | 26 | 27 | /* For great looking quote marks in titles, replace "asdf" with: 28 | asdf” 29 | (That is, when the title starts with a quote mark). 30 | (You may have to change this value depending on your font size). */ 31 | 32 | .dquo { margin-left: -.5em; } 33 | 34 | 35 | /* Reduced size type with incremental leading 36 | (https://www.markboulton.co.uk/journal/comments/incremental_leading/) 37 | 38 | This could be used for side notes. For smaller type, you don't necessarily want to 39 | follow the 1.5x vertical rhythm -- the line-height is too much. 40 | 41 | Using this class, it reduces your font size and line-height so that for 42 | every four lines of normal sized type, there is five lines of the sidenote. eg: 43 | 44 | New type size in em's: 45 | 10px (wanted side note size) / 12px (existing base size) = 0.8333 (new type size in ems) 46 | 47 | New line-height value: 48 | 12px x 1.5 = 18px (old line-height) 49 | 18px x 4 = 72px 50 | 72px / 5 = 14.4px (new line height) 51 | 14.4px / 10px = 1.44 (new line height in em's) */ 52 | 53 | p.incr, .incr p { 54 | font-size: 10px; 55 | line-height: 1.44em; 56 | margin-bottom: 1.5em; 57 | } 58 | 59 | 60 | /* Surround uppercase words and abbreviations with this class. 61 | Based on work by Jørgen Arnor Gårdsø Lom [https://twistedintellect.com/] */ 62 | 63 | .caps { 64 | font-variant: small-caps; 65 | letter-spacing: 1px; 66 | text-transform: lowercase; 67 | font-size:1.2em; 68 | line-height:1%; 69 | font-weight:bold; 70 | padding:0 2px; 71 | } 72 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/icons/doc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/icons/doc.png -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/icons/email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/icons/email.png -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/icons/external.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/icons/external.png -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/icons/feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/icons/feed.png -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/icons/im.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/icons/im.png -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/icons/pdf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/icons/pdf.png -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/icons/visited.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/icons/visited.png -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/icons/xls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/icons/xls.png -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/readme.txt: -------------------------------------------------------------------------------- 1 | Link Icons 2 | * Icons for links based on protocol or file type. 3 | 4 | This is not supported in IE versions < 7. 5 | 6 | 7 | Credits 8 | ---------------------------------------------------------------- 9 | 10 | * Marc Morgan 11 | * Olav Bjorkoy [bjorkoy.com] 12 | 13 | 14 | Usage 15 | ---------------------------------------------------------------- 16 | 17 | 1) Add this line to your HTML: 18 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/link-icons/screen.css: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------- 2 | 3 | link-icons.css 4 | * Icons for links based on protocol or file type. 5 | 6 | See the Readme file in this folder for additional instructions. 7 | 8 | -------------------------------------------------------------- */ 9 | 10 | /* Use this class if a link gets an icon when it shouldn't. */ 11 | body a.noicon { 12 | background:transparent none !important; 13 | padding:0 !important; 14 | margin:0 !important; 15 | } 16 | 17 | /* Make sure the icons are not cut */ 18 | a[href^="http:"], a[href^="mailto:"], a[href^="http:"]:visited, 19 | a[href$=".pdf"], a[href$=".doc"], a[href$=".xls"], a[href$=".rss"], 20 | a[href$=".rdf"], a[href^="aim:"] { 21 | padding:2px 22px 2px 0; 22 | margin:-2px 0; 23 | background-repeat: no-repeat; 24 | background-position: right center; 25 | } 26 | 27 | /* External links */ 28 | a[href^="http:"] { background-image: url(icons/external.png); } 29 | a[href^="mailto:"] { background-image: url(icons/email.png); } 30 | a[href^="http:"]:visited { background-image: url(icons/visited.png); } 31 | 32 | /* Files */ 33 | a[href$=".pdf"] { background-image: url(icons/pdf.png); } 34 | a[href$=".doc"] { background-image: url(icons/doc.png); } 35 | a[href$=".xls"] { background-image: url(icons/xls.png); } 36 | 37 | /* Misc */ 38 | a[href$=".rss"], 39 | a[href$=".rdf"] { background-image: url(icons/feed.png); } 40 | a[href^="aim:"] { background-image: url(icons/im.png); } -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/plugins/rtl/readme.txt: -------------------------------------------------------------------------------- 1 | RTL 2 | * Mirrors Blueprint, so it can be used with Right-to-Left languages. 3 | 4 | By Ran Yaniv Hartstein, ranh.co.il 5 | 6 | Usage 7 | ---------------------------------------------------------------- 8 | 9 | 1) Add this line to your HTML: 10 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/print.css: -------------------------------------------------------------------------------- 1 | /* ----------------------------------------------------------------------- 2 | 3 | 4 | Blueprint CSS Framework 0.9 5 | http://blueprintcss.org 6 | 7 | * Copyright (c) 2007-Present. See LICENSE for more info. 8 | * See README for instructions on how to use Blueprint. 9 | * For credits and origins, see AUTHORS. 10 | * This is a compressed file. See the sources in the 'src' directory. 11 | 12 | ----------------------------------------------------------------------- */ 13 | 14 | /* print.css */ 15 | body {line-height:1.5;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;color:#000;background:none;font-size:10pt;} 16 | .container {background:none;} 17 | hr {background:#ccc;color:#ccc;width:100%;height:2px;margin:2em 0;padding:0;border:none;} 18 | hr.space {background:#fff;color:#fff;visibility:hidden;} 19 | h1, h2, h3, h4, h5, h6 {font-family:"Helvetica Neue", Arial, "Lucida Grande", sans-serif;} 20 | code {font:.9em "Courier New", Monaco, Courier, monospace;} 21 | a img {border:none;} 22 | p img.top {margin-top:0;} 23 | blockquote {margin:1.5em;padding:1em;font-style:italic;font-size:.9em;} 24 | .small {font-size:.9em;} 25 | .large {font-size:1.1em;} 26 | .quiet {color:#999;} 27 | .hide {display:none;} 28 | a:link, a:visited {background:transparent;font-weight:700;text-decoration:underline;} 29 | a:link:after, a:visited:after {content:" (" attr(href) ")";font-size:90%;} -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/src/forms.css: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------- 2 | 3 | forms.css 4 | * Sets up some default styling for forms 5 | * Gives you classes to enhance your forms 6 | 7 | Usage: 8 | * For text fields, use class .title or .text 9 | * For inline forms, use .inline (even when using columns) 10 | 11 | -------------------------------------------------------------- */ 12 | 13 | label { font-weight: bold; } 14 | fieldset { padding:1.4em; margin: 0 0 1.5em 0; border: 1px solid #ccc; } 15 | legend { font-weight: bold; font-size:1.2em; } 16 | 17 | 18 | /* Form fields 19 | -------------------------------------------------------------- */ 20 | 21 | input[type=text], input[type=password], 22 | input.text, input.title, 23 | textarea, select { 24 | background-color:#fff; 25 | border:1px solid #bbb; 26 | } 27 | input[type=text]:focus, input[type=password]:focus, 28 | input.text:focus, input.title:focus, 29 | textarea:focus, select:focus { 30 | border-color:#666; 31 | } 32 | 33 | input[type=text], input[type=password], 34 | input.text, input.title, 35 | textarea, select { 36 | margin:0.5em 0; 37 | } 38 | 39 | input.text, 40 | input.title { width: 300px; padding:5px; } 41 | input.title { font-size:1.5em; } 42 | textarea { width: 390px; height: 250px; padding:5px; } 43 | 44 | input[type=checkbox], input[type=radio], 45 | input.checkbox, input.radio { 46 | position:relative; top:.25em; 47 | } 48 | 49 | form.inline { line-height:3; } 50 | form.inline p { margin-bottom:0; } 51 | 52 | 53 | /* Success, notice and error boxes 54 | -------------------------------------------------------------- */ 55 | 56 | .error, 57 | .notice, 58 | .success { padding: .8em; margin-bottom: 1em; border: 2px solid #ddd; } 59 | 60 | .error { background: #FBE3E4; color: #8a1f11; border-color: #FBC2C4; } 61 | .notice { background: #FFF6BF; color: #514721; border-color: #FFD324; } 62 | .success { background: #E6EFC2; color: #264409; border-color: #C6D880; } 63 | .error a { color: #8a1f11; } 64 | .notice a { color: #514721; } 65 | .success a { color: #264409; } 66 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/src/grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflow-booking/src/main/webapp/styles/blueprint/src/grid.png -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/src/ie.css: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------- 2 | 3 | ie.css 4 | 5 | Contains every hack for Internet Explorer, 6 | so that our core files stay sweet and nimble. 7 | 8 | -------------------------------------------------------------- */ 9 | 10 | /* Make sure the layout is centered in IE5 */ 11 | body { text-align: center; } 12 | .container { text-align: left; } 13 | 14 | /* Fixes IE margin bugs */ 15 | * html .column, * html div.span-1, * html div.span-2, 16 | * html div.span-3, * html div.span-4, * html div.span-5, 17 | * html div.span-6, * html div.span-7, * html div.span-8, 18 | * html div.span-9, * html div.span-10, * html div.span-11, 19 | * html div.span-12, * html div.span-13, * html div.span-14, 20 | * html div.span-15, * html div.span-16, * html div.span-17, 21 | * html div.span-18, * html div.span-19, * html div.span-20, 22 | * html div.span-21, * html div.span-22, * html div.span-23, 23 | * html div.span-24 { display:inline; overflow-x: hidden; } 24 | 25 | 26 | /* Elements 27 | -------------------------------------------------------------- */ 28 | 29 | /* Fixes incorrect styling of legend in IE6. */ 30 | * html legend { margin:0px -8px 16px 0; padding:0; } 31 | 32 | /* Fixes wrong line-height on sup/sub in IE. */ 33 | sup { vertical-align:text-top; } 34 | sub { vertical-align:text-bottom; } 35 | 36 | /* Fixes IE7 missing wrapping of code elements. */ 37 | html>body p code { *white-space: normal; } 38 | 39 | /* IE 6&7 has problems with setting proper
margins. */ 40 | hr { margin:-8px auto 11px; } 41 | 42 | /* Explicitly set interpolation, allowing dynamically resized images to not look horrible */ 43 | img { -ms-interpolation-mode:bicubic; } 44 | 45 | /* Clearing 46 | -------------------------------------------------------------- */ 47 | 48 | /* Makes clearfix actually work in IE */ 49 | .clearfix, .container { display:inline-block; } 50 | * html .clearfix, 51 | * html .container { height:1%; } 52 | 53 | 54 | /* Forms 55 | -------------------------------------------------------------- */ 56 | 57 | /* Fixes padding on fieldset */ 58 | fieldset { padding-top:0; } 59 | 60 | /* Makes classic textareas in IE 6 resemble other browsers */ 61 | textarea { overflow:auto; } 62 | 63 | /* Fixes rule that IE 6 ignores */ 64 | input.text, input.title, textarea { background-color:#fff; border:1px solid #bbb; } 65 | input.text:focus, input.title:focus { border-color:#666; } 66 | input.text, input.title, textarea, select { margin:0.5em 0; } 67 | input.checkbox, input.radio { position:relative; top:.25em; } 68 | 69 | /* Fixes alignment of inline form elements */ 70 | form.inline div, form.inline p { vertical-align:middle; } 71 | form.inline label { position:relative;top:-0.25em; } 72 | form.inline input.checkbox, form.inline input.radio, 73 | form.inline input.button, form.inline button { 74 | margin:0.5em 0; 75 | } 76 | button, input.button { position:relative;top:0.25em; } -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/src/print.css: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------- 2 | 3 | print.css 4 | * Gives you some sensible styles for printing pages. 5 | * See Readme file in this directory for further instructions. 6 | 7 | Some additions you'll want to make, customized to your markup: 8 | #header, #footer, #navigation { display:none; } 9 | 10 | -------------------------------------------------------------- */ 11 | 12 | body { 13 | line-height: 1.5; 14 | font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; 15 | color:#000; 16 | background: none; 17 | font-size: 10pt; 18 | } 19 | 20 | 21 | /* Layout 22 | -------------------------------------------------------------- */ 23 | 24 | .container { 25 | background: none; 26 | } 27 | 28 | hr { 29 | background:#ccc; 30 | color:#ccc; 31 | width:100%; 32 | height:2px; 33 | margin:2em 0; 34 | padding:0; 35 | border:none; 36 | } 37 | hr.space { 38 | background: #fff; 39 | color: #fff; 40 | visibility: hidden; 41 | } 42 | 43 | 44 | /* Text 45 | -------------------------------------------------------------- */ 46 | 47 | h1,h2,h3,h4,h5,h6 { font-family: "Helvetica Neue", Arial, "Lucida Grande", sans-serif; } 48 | code { font:.9em "Courier New", Monaco, Courier, monospace; } 49 | 50 | a img { border:none; } 51 | p img.top { margin-top: 0; } 52 | 53 | blockquote { 54 | margin:1.5em; 55 | padding:1em; 56 | font-style:italic; 57 | font-size:.9em; 58 | } 59 | 60 | .small { font-size: .9em; } 61 | .large { font-size: 1.1em; } 62 | .quiet { color: #999; } 63 | .hide { display:none; } 64 | 65 | 66 | /* Links 67 | -------------------------------------------------------------- */ 68 | 69 | a:link, a:visited { 70 | background: transparent; 71 | font-weight:700; 72 | text-decoration: underline; 73 | } 74 | 75 | a:link:after, a:visited:after { 76 | content: " (" attr(href) ")"; 77 | font-size: 90%; 78 | } 79 | 80 | /* If you're having trouble printing relative links, uncomment and customize this: 81 | (note: This is valid CSS3, but it still won't go through the W3C CSS Validator) */ 82 | 83 | /* a[href^="/"]:after { 84 | content: " (https://www.yoursite.com" attr(href) ") "; 85 | } */ 86 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/blueprint/src/reset.css: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------- 2 | 3 | reset.css 4 | * Resets default browser CSS. 5 | 6 | -------------------------------------------------------------- */ 7 | 8 | html, body, div, span, object, iframe, 9 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 10 | a, abbr, acronym, address, code, 11 | del, dfn, em, img, q, dl, dt, dd, ol, ul, li, 12 | fieldset, form, label, legend, 13 | table, caption, tbody, tfoot, thead, tr, th, td { 14 | margin: 0; 15 | padding: 0; 16 | border: 0; 17 | font-weight: inherit; 18 | font-style: inherit; 19 | font-size: 100%; 20 | font-family: inherit; 21 | vertical-align: baseline; 22 | } 23 | 24 | body { 25 | line-height: 1.5; 26 | } 27 | 28 | /* Tables still need 'cellspacing="0"' in the markup. */ 29 | table { border-collapse: separate; border-spacing: 0; } 30 | caption, th, td { text-align: left; font-weight: normal; } 31 | table, td, th { vertical-align: middle; } 32 | 33 | /* Remove possible quote marks (") from ,
. */ 34 | blockquote:before, blockquote:after, q:before, q:after { content: ""; } 35 | blockquote, q { quotes: "" ""; } 36 | 37 | /* Remove annoying border on linked images. */ 38 | a img { border: none; } 39 | -------------------------------------------------------------------------------- /webflow-booking/src/main/webapp/styles/booking.css: -------------------------------------------------------------------------------- 1 | 2 | a,a:visited,a:link,a:active { 3 | color: #59924B; 4 | background-color: transparent; 5 | text-decoration: none; 6 | font-weight: bold; 7 | } 8 | 9 | a:hover { 10 | color: white; 11 | background-color: #65a242; 12 | text-decoration: none; 13 | font-weight: bold; 14 | } 15 | 16 | button { 17 | color: #fff; 18 | background: #fff url(../images/btn.bg.gif) 0 0 repeat-x; 19 | border-style: none; 20 | } 21 | 22 | button:hover { 23 | color: yellow; 24 | background: #fff url(../images/btn.bg.gif) 0 0 repeat-x; 25 | border-style: none; 26 | } 27 | 28 | .summary { 29 | width: 100%; 30 | border: 1px solid #414f23; 31 | border-collapse: collapse; 32 | } 33 | 34 | .summary thead th { 35 | border-left: 1px solid #414f23; 36 | background: #fff url(../images/th.bg.gif) 0 100% repeat-x; 37 | border-bottom: 1px solid #414f23; 38 | padding: 6px; 39 | text-align: left; 40 | font-size: small; 41 | } 42 | 43 | .summary tbody td { 44 | border-left: 1px solid #9cac7c; 45 | padding: 4px; 46 | border-bottom: 1px solid #9cac7c; 47 | font-size: 8pt; 48 | } 49 | 50 | .label { 51 | font-weight: bold; 52 | } 53 | 54 | div.confirmed { 55 | border: solid 1px #CCCCCC; 56 | background: #E4F7CD; 57 | padding: 4px; 58 | font-weight: bold; 59 | margin-bottom: 4px; 60 | } 61 | -------------------------------------------------------------------------------- /webflux-functional/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | webflux-functional 7 | jar 8 | 9 | 10 | org.springframework.boot 11 | spring-boot-starter-parent 12 | 2.0.3.RELEASE 13 | 14 | 15 | 16 | 17 | UTF-8 18 | UTF-8 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-webflux 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-test 30 | test 31 | 32 | 33 | io.projectreactor 34 | reactor-test 35 | test 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-maven-plugin 45 | 46 | 47 | org.apache.maven.plugins 48 | maven-compiler-plugin 49 | 50 | 8 51 | 8 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /webflux-functional/src/main/java/com/github/dreamylost/webflux/SpringbootWebfluxApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.webflux; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.web.reactive.config.EnableWebFlux; 6 | 7 | @SpringBootApplication 8 | @EnableWebFlux 9 | public class SpringbootWebfluxApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(SpringbootWebfluxApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /webflux-functional/src/main/java/com/github/dreamylost/webflux/funtctional/handler/UserHandler.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.webflux.funtctional.handler; 2 | 3 | import com.github.dreamylost.webflux.model.User; 4 | import com.github.dreamylost.webflux.service.IUserService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.http.MediaType; 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.web.reactive.function.server.ServerRequest; 9 | import org.springframework.web.reactive.function.server.ServerResponse; 10 | import reactor.core.publisher.Flux; 11 | import reactor.core.publisher.Mono; 12 | 13 | @Component 14 | public class UserHandler { 15 | 16 | private IUserService userService; 17 | 18 | @Autowired 19 | public UserHandler(IUserService userService) { 20 | this.userService = userService; 21 | } 22 | 23 | public Mono getAllUser(ServerRequest serverRequest) { 24 | Flux allUser = userService.getAllUser(); 25 | return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(allUser, User.class); 26 | } 27 | 28 | public Mono getUserById(ServerRequest serverRequest) { 29 | //获取url上的id 30 | Long uid = Long.valueOf(serverRequest.pathVariable("id")); 31 | Mono user = userService.getUserById(uid); 32 | return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(user, User.class); 33 | } 34 | 35 | public Mono saveUser(ServerRequest serverRequest) { 36 | Mono user = serverRequest.bodyToMono(User.class); 37 | return ServerResponse.ok().build(userService.saveUser(user)); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /webflux-functional/src/main/java/com/github/dreamylost/webflux/funtctional/router/RoutingConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.webflux.funtctional.router; 2 | 3 | import com.github.dreamylost.webflux.funtctional.handler.UserHandler; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.http.MediaType; 7 | import org.springframework.web.reactive.function.server.RouterFunction; 8 | import org.springframework.web.reactive.function.server.ServerResponse; 9 | 10 | import static org.springframework.web.reactive.function.server.RequestPredicates.*; 11 | import static org.springframework.web.reactive.function.server.RouterFunctions.route; 12 | 13 | @Configuration 14 | public class RoutingConfiguration { 15 | 16 | @Bean 17 | public RouterFunction monoRouterFunction(UserHandler userHandler) { 18 | return route(GET("/api/user").and(accept(MediaType.APPLICATION_JSON)), userHandler::getAllUser) 19 | .andRoute(GET("/api/user/{id}").and(accept(MediaType.APPLICATION_JSON)), userHandler::getUserById) 20 | .andRoute(POST("/api/save").and(accept(MediaType.APPLICATION_JSON)), userHandler::saveUser); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /webflux-functional/src/main/java/com/github/dreamylost/webflux/model/User.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.webflux.model; 2 | 3 | public class User { 4 | private Long uid; 5 | private String name; 6 | private String psw; 7 | 8 | public Long getUid() { 9 | return uid; 10 | } 11 | 12 | public User() { 13 | } 14 | 15 | public User(Long uid, String name, String psw) { 16 | this.uid = uid; 17 | this.name = name; 18 | this.psw = psw; 19 | } 20 | 21 | public void setUid(Long uid) { 22 | this.uid = uid; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | 33 | public String getPsw() { 34 | return psw; 35 | } 36 | 37 | public void setPsw(String psw) { 38 | this.psw = psw; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return "User{" + 44 | "uid=" + uid + 45 | ", name='" + name + '\'' + 46 | ", psw='" + psw + '\'' + 47 | '}'; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /webflux-functional/src/main/java/com/github/dreamylost/webflux/service/IUserService.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.webflux.service; 2 | 3 | import com.github.dreamylost.webflux.model.User; 4 | import reactor.core.publisher.Flux; 5 | import reactor.core.publisher.Mono; 6 | 7 | public interface IUserService { 8 | 9 | Flux getAllUser(); 10 | 11 | Mono getUserById(Long id); 12 | 13 | Mono saveUser(Mono userMono); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /webflux-functional/src/main/java/com/github/dreamylost/webflux/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.webflux.service.impl; 2 | 3 | import com.github.dreamylost.webflux.model.User; 4 | import com.github.dreamylost.webflux.service.IUserService; 5 | import org.springframework.stereotype.Service; 6 | import reactor.core.publisher.Flux; 7 | import reactor.core.publisher.Mono; 8 | 9 | import javax.annotation.PostConstruct; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | @Service 14 | public class UserServiceImpl implements IUserService { 15 | 16 | private Map map = new HashMap<>(10); 17 | 18 | @PostConstruct 19 | public void init() { 20 | map.put(1L, new User(1L, "admin", "admin")); 21 | map.put(2L, new User(2L, "admin2", "admin2")); 22 | map.put(3L, new User(3L, "admin3", "admin3")); 23 | } 24 | 25 | @Override 26 | public Flux getAllUser() { 27 | return Flux.fromIterable(map.values()); 28 | } 29 | 30 | @Override 31 | public Mono getUserById(Long id) { 32 | return Mono.just(map.get(id)); 33 | } 34 | 35 | @Override 36 | public Mono saveUser(Mono userMono) { 37 | Mono mono = userMono.doOnNext(user -> 38 | map.put(user.getUid(), user) 39 | ); 40 | return mono.then(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /webflux-functional/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 9999 -------------------------------------------------------------------------------- /webflux-functional/src/test/java/com/github/dreamylost/webflux/SpringbootWebfluxApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.webflux; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class SpringbootWebfluxApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /webflux/README.md: -------------------------------------------------------------------------------- 1 | SpringBoot Webflux 示例 2 | --- 3 | 4 | Spring WebFlux是Spring Framework 5.0中引入的新的反应式Web框架。 5 | 与Spring MVC不同,它不需要Servlet API,完全异步和非阻塞,并通过Reactor项目实现Reactive Streams规范。并且可以在诸如Netty,Undertow和Servlet 3.1+容器的服务器上运行。 6 | 7 | ## Reactor 中的 Mono 和 Flux 8 | 9 | Flux 和 Mono 是 Reactor 中的两个基本概念。Flux 表示的是包含 0 到 N 个元素的异步序列。 10 | 在该序列中可以包含三种不同类型的消息通知:正常的包含元素的消息、序列结束的消息和序列出错的消息。 11 | 当消息通知产生时,订阅者中对应的方法 onNext(), onComplete()和 onError()会被调用。Mono 表示的是包含 0 或者 1 个元素的异步序列。 12 | 该序列中同样可以包含与 Flux 相同的三种类型的消息通知。Flux 和 Mono 之间可以进行转换。 13 | 对一个 Flux 序列进行计数操作,得到的结果是一个 Mono对象。把两个 Mono 序列合并在一起,得到的是一个 Flux 对象。 [了解更多](https://www.ibm.com/developerworks/cn/java/j-cn-with-reactor-response-encode/index.html) 14 | 15 | ## 示例 16 | 17 | 1. webflow 18 | - 基于SpringMvc注解@Controller 19 | 2. webflow-functional 20 | - 基于Java8 lambda样式路由和处理 -------------------------------------------------------------------------------- /webflux/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | webflux 7 | jar 8 | springboot-webflux 9 | Demo project for Spring Boot 10 | 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-parent 15 | 2.0.3.RELEASE 16 | 17 | 18 | 19 | 20 | UTF-8 21 | UTF-8 22 | 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-web 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-webflux 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-test 36 | test 37 | 38 | 39 | io.projectreactor 40 | reactor-test 41 | test 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-maven-plugin 50 | 51 | 52 | org.apache.maven.plugins 53 | maven-compiler-plugin 54 | 55 | 8 56 | 8 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /webflux/src/main/java/com/github/dreamylost/webflux/SpringbootWebfluxApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.webflux; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.web.reactive.config.EnableWebFlux; 6 | 7 | @SpringBootApplication 8 | @EnableWebFlux 9 | public class SpringbootWebfluxApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(SpringbootWebfluxApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /webflux/src/main/java/com/github/dreamylost/webflux/User.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.webflux; 2 | 3 | public class User { 4 | private Long uid; 5 | private String name; 6 | private String psw; 7 | 8 | public Long getUid() { 9 | return uid; 10 | } 11 | 12 | public User() { 13 | } 14 | 15 | public User(Long uid, String name, String psw) { 16 | this.uid = uid; 17 | this.name = name; 18 | this.psw = psw; 19 | } 20 | 21 | public void setUid(Long uid) { 22 | this.uid = uid; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | 33 | public String getPsw() { 34 | return psw; 35 | } 36 | 37 | public void setPsw(String psw) { 38 | this.psw = psw; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return "User{" + 44 | "uid=" + uid + 45 | ", name='" + name + '\'' + 46 | ", psw='" + psw + '\'' + 47 | '}'; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /webflux/src/main/java/com/github/dreamylost/webflux/WebFluxController.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.webflux; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.web.bind.annotation.*; 6 | import reactor.core.publisher.Flux; 7 | import reactor.core.publisher.Mono; 8 | 9 | import javax.annotation.PostConstruct; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.stream.Collectors; 13 | 14 | @RestController 15 | @RequestMapping("/api/user") 16 | public class WebFluxController { 17 | 18 | private Map map = new HashMap(10); 19 | 20 | @PostConstruct 21 | public void init() { 22 | map.put(1L, new User(1L, "admin", "admin")); 23 | map.put(2L, new User(2L, "admin2", "admin2")); 24 | map.put(3L, new User(3L, "admin3", "admin3")); 25 | } 26 | 27 | @GetMapping("/getAll") 28 | @CrossOrigin 29 | public Flux getAllUser() { 30 | return Flux.fromIterable(map.entrySet().stream().map(Map.Entry::getValue) 31 | .collect(Collectors.toList())); 32 | } 33 | 34 | @GetMapping("/{id}") 35 | public Mono getUserById(@PathVariable("id") Long id) { 36 | return Mono.just(map.get(id)); 37 | } 38 | 39 | @PostMapping("/save") 40 | public Mono> save(@RequestBody User user) { 41 | map.put(user.getUid(), user); 42 | return Mono.just(new ResponseEntity<>("添加成功", HttpStatus.CREATED)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /webflux/src/main/resources/application.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxnu-liguobin/springboot-examples/ae7150ec95a2d16829e80b200eb90c26a1572f57/webflux/src/main/resources/application.yml -------------------------------------------------------------------------------- /webflux/src/test/java/com/github/dreamylost/webflux/SpringbootWebfluxApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.github.dreamylost.webflux; 2 | 3 | import org.junit.BeforeClass; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | import org.springframework.test.web.reactive.server.WebTestClient; 11 | import org.springframework.web.reactive.function.BodyInserters; 12 | 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | 16 | @RunWith(SpringRunner.class) 17 | @WebFluxTest 18 | public class SpringbootWebfluxApplicationTests { 19 | 20 | @Autowired 21 | private WebTestClient webClient; 22 | 23 | private static Map map = new HashMap(10); 24 | 25 | @BeforeClass 26 | public static void init() { 27 | map.put(1L, new User(1L, "admin", "admin")); 28 | map.put(2L, new User(2L, "admin2", "admin2")); 29 | map.put(3L, new User(3L, "admin3", "admin3")); 30 | } 31 | 32 | @Test 33 | public void contextLoads() { 34 | User user = new User(4L, "admin4", "admin4"); 35 | webClient.post().uri("/api/user/save") 36 | .contentType(MediaType.APPLICATION_JSON) 37 | .body(BodyInserters.fromObject(user)) 38 | .exchange() 39 | .expectStatus().isCreated() 40 | .expectBody(String.class) 41 | .isEqualTo("添加成功"); 42 | } 43 | 44 | } 45 | --------------------------------------------------------------------------------