├── .gitignore ├── Cache-SpringBoot ├── README.MD ├── build.gradle ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ ├── main │ └── java │ │ └── com │ │ └── skypyb │ │ ├── CacheDemoApplication.java │ │ ├── entity │ │ └── User.java │ │ └── service │ │ └── UserService.java │ └── test │ └── java │ └── CacheTest.java ├── Event-Springboot ├── README.md ├── build.gradle ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ ├── main │ └── java │ │ └── com │ │ └── skypyb │ │ ├── EventApplication.java │ │ ├── config │ │ └── MyAsyncConfigurer.java │ │ ├── entity │ │ └── User.java │ │ ├── event │ │ └── UserRegisterEvent.java │ │ ├── listener │ │ └── InitializationListener.java │ │ └── service │ │ ├── MailService.java │ │ └── UserService.java │ └── test │ └── java │ └── com │ └── skypyb │ └── EventTest.java ├── LICENSE ├── README.md ├── RabbitMQ-SpringBoot ├── README.md ├── RabbitMQ-Consumer │ ├── build.gradle │ ├── gradlew │ ├── gradlew.bat │ ├── out │ │ └── production │ │ │ └── resources │ │ │ └── application.yml │ ├── settings.gradle │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── skypyb │ │ │ │ └── rabbitmq │ │ │ │ ├── Application.java │ │ │ │ ├── config │ │ │ │ ├── RabbitBindConfig.java │ │ │ │ └── RabbitMQCoreConfig.java │ │ │ │ ├── controller │ │ │ │ ├── DeadReceiver.java │ │ │ │ ├── DelayReceiver.java │ │ │ │ └── User1Receiver.java │ │ │ │ └── entity │ │ │ │ └── User1.java │ │ └── resources │ │ │ └── application.yml │ │ └── test │ │ └── java │ │ └── com │ │ └── skypyb │ │ └── test │ │ └── RabbitmqTest.java └── RabbitMQ-Producer │ ├── build.gradle │ ├── gradlew │ ├── gradlew.bat │ ├── out │ └── production │ │ └── resources │ │ └── application.yml │ ├── settings.gradle │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── skypyb │ │ │ └── rabbitmq │ │ │ ├── Application.java │ │ │ ├── entity │ │ │ └── User1.java │ │ │ └── producer │ │ │ └── User1Sender.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── skypyb │ └── test │ └── RabbitmqTest.java ├── WebSocket ├── README.md └── websocket │ ├── build.gradle │ ├── gradlew │ ├── gradlew.bat │ ├── out │ └── production │ │ └── resources │ │ ├── application.yml │ │ └── view │ │ └── index.html │ ├── settings.gradle │ └── src │ └── main │ ├── java │ └── com │ │ └── skypyb │ │ ├── WebSocketApplication.java │ │ ├── scheduled │ │ ├── SchedulerConfig.java │ │ └── WebSocketSendMessageScheduled.java │ │ ├── springboot_websocket │ │ ├── MyWebSocketHandler.java │ │ └── WebSocketConfigTwo.java │ │ └── websocket │ │ ├── WebSocketConfigOne.java │ │ └── WebSocketServerOne.java │ └── resources │ ├── application.yml │ └── view │ └── index.html ├── distributed-lock ├── build.gradle ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── skypyb │ │ │ ├── DemoApplication.java │ │ │ ├── config │ │ │ └── RedisConfig.java │ │ │ ├── lock │ │ │ ├── DistributedLock.java │ │ │ └── RedisLock.java │ │ │ └── semaphore │ │ │ ├── DistributedSemaphore.java │ │ │ ├── RedisSemaphore.java │ │ │ └── SemaphoreInfo.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── skypyb │ ├── DistributedLockTest.java │ └── DistributedSemaphoreTest.java ├── dubbo-springboot ├── README.md ├── docker-compose.zookeeper.yml ├── dubbo-user-service-api │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── skypyb │ │ └── dubbo │ │ └── service │ │ └── user │ │ └── api │ │ └── UserService.java ├── dubbo-user-service-consumer │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── skypyb │ │ │ │ └── dubbo │ │ │ │ └── user │ │ │ │ └── service │ │ │ │ └── consumer │ │ │ │ ├── DubboUserServiceConsumerApplication.java │ │ │ │ ├── config │ │ │ │ └── HystrixConfig.java │ │ │ │ └── controller │ │ │ │ └── UserController.java │ │ └── resources │ │ │ └── application.yml │ │ └── test │ │ └── java │ │ └── com │ │ └── skypyb │ │ └── dubbo │ │ └── user │ │ └── service │ │ └── consumer │ │ └── DubboUserServiceConsumerApplicationTests.java └── dubbo-user-service-provider │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── skypyb │ │ │ └── dubbo │ │ │ └── user │ │ │ └── service │ │ │ └── provider │ │ │ ├── DubboUserServiceProviderApplication.java │ │ │ └── api │ │ │ └── impl │ │ │ └── UserServiceImpl.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── skypyb │ └── dubbo │ └── user │ └── service │ └── provider │ └── DubboUserServiceProviderApplicationTests.java ├── sc-demo-alibaba ├── README.md ├── sc-demo-alibaba-consumer │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── skypyb │ │ │ └── provider │ │ │ ├── NacosConsumerApplication.java │ │ │ ├── config │ │ │ └── RestConfiguration.java │ │ │ ├── controller │ │ │ └── NacosConsumerController.java │ │ │ ├── fallback │ │ │ └── HelloServiceFallback.java │ │ │ └── feign │ │ │ └── NacosHelloFeign.java │ │ └── resources │ │ └── application.yml ├── sc-demo-alibaba-dependencies │ └── pom.xml ├── sc-demo-alibaba-gateway │ ├── pom.xml │ └── src │ │ ├── java │ │ └── com │ │ │ └── skypyb │ │ │ └── gateway │ │ │ ├── GatewayApplication.java │ │ │ ├── config │ │ │ ├── GatewayRateLimiterConfig.java │ │ │ └── RedisConfig.java │ │ │ └── filter │ │ │ └── all │ │ │ └── AuthFilter.java │ │ └── resources │ │ └── application.yml └── sc-demo-alibaba-provider │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── com │ │ └── skypyb │ │ └── provider │ │ ├── NacosProviderApplication.java │ │ └── controller │ │ └── NacosProviderController.java │ └── resources │ └── application.yml ├── sc-demo-microservice ├── build.gradle ├── gradlew ├── gradlew.bat ├── sc-demo-microservice-eureka │ ├── build.gradle │ ├── out │ │ └── production │ │ │ └── resources │ │ │ └── application.yml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── skypyb │ │ │ └── sc │ │ │ ├── EurekaServerApplication.java │ │ │ └── config │ │ │ └── WebSecurityConfig.java │ │ └── resources │ │ └── application.yml ├── sc-demo-microservice-movie │ ├── build.gradle │ ├── out │ │ └── production │ │ │ └── resources │ │ │ └── application.yml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── skypyb │ │ │ └── sc │ │ │ ├── MovieApplication.java │ │ │ ├── config │ │ │ ├── FeignConfiguration.java │ │ │ └── RestConfig.java │ │ │ ├── controller │ │ │ └── MovieController.java │ │ │ ├── entity │ │ │ └── User.java │ │ │ ├── feign │ │ │ └── UserFeignClient.java │ │ │ └── hystrix │ │ │ └── UserFeignFallback.java │ │ └── resources │ │ └── application.yml ├── sc-demo-microservice-user │ ├── build.gradle │ ├── out │ │ └── production │ │ │ └── resources │ │ │ ├── application.yml │ │ │ └── schema.sql │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── skypyb │ │ │ └── sc │ │ │ ├── UserApplication.java │ │ │ ├── controller │ │ │ └── UserController.java │ │ │ ├── dao │ │ │ └── UserDao.java │ │ │ ├── entity │ │ │ └── User.java │ │ │ └── service │ │ │ └── UserService.java │ │ └── resources │ │ ├── application.yml │ │ └── schema.sql ├── sc-demo-microservice-zuul │ ├── build.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── skypyb │ │ │ └── sc │ │ │ ├── ZuulApplication.java │ │ │ ├── config │ │ │ ├── RestConfig.java │ │ │ └── ZuulFilterConfig.java │ │ │ ├── controller │ │ │ ├── AggregationController.java │ │ │ └── LocalController.java │ │ │ ├── entity │ │ │ └── User.java │ │ │ └── hystrix │ │ │ └── UserMicroserviceFallBack.java │ │ └── resources │ │ └── application.yml └── settings.gradle ├── shardingsphere-springboot └── sharding-jdbc │ ├── build.gradle │ ├── settings.gradle │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── skypyb │ │ │ └── demo │ │ │ └── sharding │ │ │ ├── ShardingJDBCApplication.java │ │ │ └── order │ │ │ ├── dao │ │ │ └── OrderMapper.java │ │ │ ├── entity │ │ │ └── OrderDO.java │ │ │ └── service │ │ │ ├── OrderService.java │ │ │ └── impl │ │ │ └── OrderServiceImpl.java │ └── resources │ │ ├── application.yml │ │ ├── init │ │ └── schema.sql │ │ └── mybatis │ │ └── mapper │ │ └── OrderMapper.xml │ └── test │ └── java │ └── com │ └── skypyb │ └── test │ └── shardingjdbc │ └── ShardingSphereTest.java ├── spring-security-demo ├── README.md ├── pom.xml ├── spring-security-demo-dependencies │ └── pom.xml └── spring-security-demo-server │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── com │ │ └── skypyb │ │ ├── SecurityServerApplication.java │ │ ├── security │ │ ├── config │ │ │ ├── SecurityConfiguration.java │ │ │ └── SecurityProperties.java │ │ ├── controller │ │ │ └── advice │ │ │ │ └── AuthenticationExceptionAdvice.java │ │ ├── exception │ │ │ ├── RequestValidationException.java │ │ │ └── SecurityAuthException.java │ │ ├── filter │ │ │ ├── AuthenticationFailEntryPoint.java │ │ │ ├── access │ │ │ │ ├── JwtAccessDecisionManager.java │ │ │ │ ├── JwtAuthenticationTokenFilter.java │ │ │ │ ├── JwtFilterSecurityInterceptor.java │ │ │ │ └── JwtInvocationSecurityMetadataSourceService.java │ │ │ └── authentication │ │ │ │ ├── CreateAuthenticationTokenFilter.java │ │ │ │ └── OptionsRequestFilter.java │ │ ├── model │ │ │ ├── dto │ │ │ │ └── AuthenticationUser.java │ │ │ ├── request │ │ │ │ └── AuthenticationRequest.java │ │ │ └── response │ │ │ │ ├── AuthenticationFailResponse.java │ │ │ │ ├── AuthenticationResponse.java │ │ │ │ ├── BasicResponse.java │ │ │ │ └── ValidationFailResponse.java │ │ ├── service │ │ │ └── AuthenticationUserService.java │ │ └── util │ │ │ └── JwtTokenUtil.java │ │ ├── test │ │ └── controller │ │ │ └── MethodProtectedRestController.java │ │ └── user │ │ ├── config │ │ └── UserConfiguration.java │ │ ├── dao │ │ └── UserDao.java │ │ ├── model │ │ ├── dto │ │ │ ├── MinimumPermissionDTO.java │ │ │ ├── MinimumRoleDTO.java │ │ │ ├── MinimumUserDTO.java │ │ │ └── RolePermissionPO.java │ │ └── po │ │ │ ├── PermissionPO.java │ │ │ ├── RolePO.java │ │ │ └── UserPO.java │ │ └── service │ │ └── UserService.java │ └── resources │ ├── application.yml │ ├── init_sql │ └── tables │ └── mybatis │ └── mapper │ └── UserMapper.xml └── ssm-backstage ├── README.MD ├── pom.xml └── src └── main ├── java └── com │ └── skypyb │ ├── config │ └── SecurityInterceptor.java │ ├── controller │ ├── AuthorityController.java │ ├── FeatureController.java │ ├── UserController.java │ └── ViewController.java │ ├── dao │ ├── AuthorityDao.java │ ├── FeatureDao.java │ └── UserDao.java │ ├── entity │ ├── Authority.java │ ├── AuthorityToFeature.java │ ├── Feature.java │ └── User.java │ ├── model │ └── LaydataResponse.java │ └── service │ ├── AuthorityService.java │ ├── FeatureService.java │ └── UserService.java ├── resources ├── applicationContext.xml ├── log4j.properties ├── mybatis.xml ├── mysql.properties ├── springmvc.xml └── sql │ └── schema.sql └── webapp ├── WEB-INF ├── templates │ ├── authorityManager.html │ ├── index.html │ ├── layout.html │ ├── login.html │ └── userManager.html └── web.xml ├── css ├── authorityManager.css └── login.css ├── js ├── authorityManager.js ├── layout.js └── userManager.js └── layui ├── css ├── layui.css ├── layui.mobile.css └── modules │ ├── code.css │ ├── laydate │ └── default │ │ └── laydate.css │ └── layer │ └── default │ ├── icon-ext.png │ ├── icon.png │ ├── layer.css │ ├── loading-0.gif │ ├── loading-1.gif │ └── loading-2.gif ├── font ├── iconfont.eot ├── iconfont.svg ├── iconfont.ttf └── iconfont.woff ├── images └── face │ ├── 0.gif │ ├── 1.gif │ ├── 10.gif │ ├── 11.gif │ ├── 12.gif │ ├── 13.gif │ ├── 14.gif │ ├── 15.gif │ ├── 16.gif │ ├── 17.gif │ ├── 18.gif │ ├── 19.gif │ ├── 2.gif │ ├── 20.gif │ ├── 21.gif │ ├── 22.gif │ ├── 23.gif │ ├── 24.gif │ ├── 25.gif │ ├── 26.gif │ ├── 27.gif │ ├── 28.gif │ ├── 29.gif │ ├── 3.gif │ ├── 30.gif │ ├── 31.gif │ ├── 32.gif │ ├── 33.gif │ ├── 34.gif │ ├── 35.gif │ ├── 36.gif │ ├── 37.gif │ ├── 38.gif │ ├── 39.gif │ ├── 4.gif │ ├── 40.gif │ ├── 41.gif │ ├── 42.gif │ ├── 43.gif │ ├── 44.gif │ ├── 45.gif │ ├── 46.gif │ ├── 47.gif │ ├── 48.gif │ ├── 49.gif │ ├── 5.gif │ ├── 50.gif │ ├── 51.gif │ ├── 52.gif │ ├── 53.gif │ ├── 54.gif │ ├── 55.gif │ ├── 56.gif │ ├── 57.gif │ ├── 58.gif │ ├── 59.gif │ ├── 6.gif │ ├── 60.gif │ ├── 61.gif │ ├── 62.gif │ ├── 63.gif │ ├── 64.gif │ ├── 65.gif │ ├── 66.gif │ ├── 67.gif │ ├── 68.gif │ ├── 69.gif │ ├── 7.gif │ ├── 70.gif │ ├── 71.gif │ ├── 8.gif │ └── 9.gif ├── lay └── modules │ ├── carousel.js │ ├── code.js │ ├── colorpicker.js │ ├── element.js │ ├── flow.js │ ├── form.js │ ├── jquery.js │ ├── laydate.js │ ├── layedit.js │ ├── layer.js │ ├── laypage.js │ ├── laytpl.js │ ├── mobile.js │ ├── rate.js │ ├── slider.js │ ├── table.js │ ├── tree.js │ ├── upload.js │ └── util.js ├── layui.all.js └── layui.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | *.iml 22 | *.lst 23 | 24 | #java files 25 | 26 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 27 | hs_err_pid* 28 | 29 | #dirs 30 | .idea/ 31 | .mvn/ 32 | out/ 33 | build/ 34 | gradle/ 35 | .gradle/ 36 | target/out/ 37 | target/ 38 | 39 | #files 40 | HELP.md 41 | mvnw 42 | mvnw.cmd 43 | gradlew 44 | gradlew.bat -------------------------------------------------------------------------------- /Cache-SpringBoot/README.MD: -------------------------------------------------------------------------------- 1 | SpringBoot的缓存操作 2 | --- 3 | 4 | * IDEA中选择[Project Structure]的Project子菜单, 进行如下操作导入: 5 | `绿色加号 -> Import Module -> 选择build.gradle -> OK -> ... ` 6 | 7 |
8 |
9 | 关于缓存,这里只涉及到SpringBoot自带的缓存实现,即默认的 SimpleCacheConfiguration 创建的 ConcurrentMapCacheManager ,不涉及Redis缓存。 10 | @CacheConfig 11 | @CacheEvict 12 | @CachePut 13 | @Cacheable 14 | 以上注解都有用到,test 文件夹下有测试类举例说明,除注解配置之外,测试类中也有个简易的代码操作缓存演示。 15 | -------------------------------------------------------------------------------- /Cache-SpringBoot/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | springBootVersion = '2.0.4.RELEASE' 4 | } 5 | repositories { 6 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 7 | mavenCentral() 8 | } 9 | dependencies { 10 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 11 | } 12 | } 13 | 14 | apply plugin: 'java' 15 | apply plugin: 'idea' 16 | apply plugin: 'org.springframework.boot' 17 | 18 | jar { 19 | baseName = 'Cache-SpringBoot' 20 | version = '0.0.1-SNAPSHOT' 21 | } 22 | 23 | sourceCompatibility = 1.8 24 | targetCompatibility = 1.8 25 | 26 | allprojects { 27 | repositories { 28 | mavenLocal() 29 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 30 | mavenCentral() 31 | } 32 | } 33 | 34 | dependencies { 35 | compile fileTree(dir: 'libs', include: ['*.jar']) 36 | compile group: 'org.springframework.boot', name: 'spring-boot-starter', version: '2.0.4.RELEASE' 37 | testCompile('org.springframework.boot:spring-boot-starter-test:2.0.4.RELEASE') 38 | } 39 | 40 | tasks.withType(JavaCompile) { 41 | options.encoding = "UTF-8" 42 | } 43 | -------------------------------------------------------------------------------- /Cache-SpringBoot/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'Cache-SpringBoot' 2 | 3 | -------------------------------------------------------------------------------- /Cache-SpringBoot/src/main/java/com/skypyb/CacheDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.skypyb; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cache.annotation.EnableCaching; 6 | 7 | @EnableCaching//开启基于注解的缓存 8 | @SpringBootApplication 9 | public class CacheDemoApplication { 10 | public static void main(String[] args) { 11 | SpringApplication.run(CacheDemoApplication.class, args); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Cache-SpringBoot/src/main/java/com/skypyb/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | public class User implements Serializable { 6 | 7 | private Integer id; 8 | private String name; 9 | private String gender; 10 | 11 | public User() { 12 | } 13 | 14 | public User(Integer id, String name, String gender) { 15 | this.id = id; 16 | this.name = name; 17 | this.gender = gender; 18 | } 19 | 20 | public Integer getId() { 21 | return id; 22 | } 23 | 24 | public void setId(Integer id) { 25 | this.id = id; 26 | } 27 | 28 | public String getName() { 29 | return name; 30 | } 31 | 32 | public void setName(String name) { 33 | this.name = name; 34 | } 35 | 36 | public String getGender() { 37 | return gender; 38 | } 39 | 40 | public void setGender(String gender) { 41 | this.gender = gender; 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | final StringBuffer sb = new StringBuffer("User{"); 47 | sb.append("id=").append(id); 48 | sb.append(", name='").append(name).append('\''); 49 | sb.append(", gender='").append(gender).append('\''); 50 | sb.append('}'); 51 | return sb.toString(); 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /Cache-SpringBoot/src/main/java/com/skypyb/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.service; 2 | 3 | import com.skypyb.entity.User; 4 | import org.springframework.cache.annotation.CacheConfig; 5 | import org.springframework.cache.annotation.CacheEvict; 6 | import org.springframework.cache.annotation.CachePut; 7 | import org.springframework.cache.annotation.Cacheable; 8 | import org.springframework.stereotype.Service; 9 | 10 | 11 | /** 12 | * CRUD 都是直接返回的假数据,不连数据库查了 13 | */ 14 | @Service 15 | @CacheConfig(cacheNames = "user") 16 | public class UserService { 17 | private User user = new User(1, "tom", "man"); 18 | 19 | /** 20 | * @Cacheable 表示需要缓存 21 | * key 属性是指定如何生成key(可用SpEL表达式)。也可以手动实现 keyGenerator 22 | * 在查询时,若是在Cache中(我这里是指定的名为"user的"Cache)有对应的key的话则不会执行方法 23 | * - 24 | * cacheManager 属性可以指定使用的CacheManager,CacheManager可以自己实现 25 | * 若是什么都没有导入则默认使用 SimpleCacheConfiguration 创建的 ConcurrentMapCacheManager 26 | * 要是导入了拥有自己实现的CacheManager的第三方依赖,比如 spring-boot-starter-data-redis,就会覆盖掉默认的实现 27 | * - 28 | * condition 属性,满足条件就缓存(可用SpEL表达式写条件),默认始终缓存 29 | * unless 属性,满足条件就不缓存,默认始终缓存 30 | */ 31 | @Cacheable(key = "#root.targetClass.name+#id") 32 | public User getUserById(Integer id) { 33 | 34 | System.out.println("执行了 getUserById 该方法.."); 35 | return user; 36 | } 37 | 38 | 39 | @Cacheable(key = "#root.targetClass.name + #name") 40 | public User getUserByName(String name) { 41 | 42 | System.out.println("执行了 getUserByName 该方法.."); 43 | return user; 44 | } 45 | 46 | /** 47 | * @CachePut 表示随你怎么搞,反正方法是要执行的。如果对应的Key有缓存,就给你更新了 48 | */ 49 | @CachePut(key = "#root.targetClass.name+#result.id") 50 | public User updateUser(User user) { 51 | System.out.println("执行了 updateUser 该方法.."); 52 | this.user = user; 53 | 54 | return user; 55 | } 56 | 57 | /** 58 | * @CacheEvict 表示会清除key对应的缓存, 方法也是无论如何都会执行的 59 | */ 60 | @CacheEvict(key = "#root.targetClass.name+#id") 61 | public void deleteUserById(Integer id) { 62 | System.out.println("执行了 deleteUserById 该方法.."); 63 | } 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /Cache-SpringBoot/src/test/java/CacheTest.java: -------------------------------------------------------------------------------- 1 | import com.skypyb.CacheDemoApplication; 2 | import com.skypyb.entity.User; 3 | import com.skypyb.service.UserService; 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.context.SpringBootTest; 8 | import org.springframework.cache.concurrent.ConcurrentMapCacheManager; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | 11 | import javax.annotation.Resource; 12 | 13 | @SpringBootTest(classes = CacheDemoApplication.class) 14 | @RunWith(SpringRunner.class) 15 | public class CacheTest { 16 | 17 | @Autowired 18 | private UserService userService; 19 | 20 | @Resource 21 | private ConcurrentMapCacheManager cacheManager; 22 | 23 | 24 | @Test 25 | public void test1() { 26 | 27 | //第一次查 28 | User user = userService.getUserById(1); 29 | userService.getUserByName("tom"); 30 | System.out.println("------"); 31 | 32 | //第二次查 33 | userService.getUserById(1); 34 | userService.getUserByName("tom"); 35 | System.out.println("------"); 36 | 37 | userService.updateUser(user); 38 | System.out.println("------"); 39 | 40 | userService.deleteUserById(1); 41 | System.out.println("------"); 42 | 43 | //第三次查 44 | userService.getUserById(1); 45 | userService.getUserByName("tom"); 46 | System.out.println("------"); 47 | 48 | test2(); 49 | } 50 | 51 | /** 52 | * 代码方式操作缓存 53 | */ 54 | public void test2() { 55 | Object user = cacheManager.getCache("user").get("com.skypyb.service.UserService1").get(); 56 | System.out.println(user); 57 | } 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /Event-Springboot/README.md: -------------------------------------------------------------------------------- 1 | SpringBoot实现异步事件驱动(发布、监听)编程 2 | --- 3 | 4 | * IDEA中选择[Project Structure]的Project子菜单, 进行如下操作导入: 5 | `绿色加号 -> Import Module -> 选择build.gradle -> OK -> ... ` 6 | * test 文件夹下有测试类,直接启动即可 7 | * 有序监听没写,没什么用,严格要求有序处理业务为啥不一个个调用方法。 8 | `有序监听实现 SmartApplicationListener 就行了。` 9 | -------------------------------------------------------------------------------- /Event-Springboot/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | springBootVersion = '2.0.4.RELEASE' 4 | } 5 | repositories { 6 | mavenLocal() 7 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 8 | mavenCentral() 9 | } 10 | dependencies { 11 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 12 | } 13 | } 14 | 15 | apply plugin: 'java' 16 | apply plugin: 'idea' 17 | apply plugin: 'org.springframework.boot' 18 | 19 | jar { 20 | baseName = 'Event' 21 | version = '0.0.1-SNAPSHOT' 22 | } 23 | 24 | sourceCompatibility = 1.8 25 | targetCompatibility = 1.8 26 | 27 | allprojects { 28 | repositories { 29 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 30 | mavenCentral() 31 | } 32 | } 33 | 34 | dependencies { 35 | compile fileTree(dir: 'libs', include: ['*.jar']) 36 | // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter 37 | compile group: 'org.springframework.boot', name: 'spring-boot-starter', version: '2.0.4.RELEASE' 38 | testCompile('org.springframework.boot:spring-boot-starter-test:2.0.4.RELEASE') 39 | } 40 | 41 | tasks.withType(JavaCompile) { 42 | options.encoding = "UTF-8" 43 | } 44 | -------------------------------------------------------------------------------- /Event-Springboot/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'Event-Springboot' 2 | 3 | -------------------------------------------------------------------------------- /Event-Springboot/src/main/java/com/skypyb/EventApplication.java: -------------------------------------------------------------------------------- 1 | package com.skypyb; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class EventApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(EventApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Event-Springboot/src/main/java/com/skypyb/config/MyAsyncConfigurer.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.config; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.scheduling.annotation.AsyncConfigurer; 8 | import org.springframework.scheduling.annotation.EnableAsync; 9 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 10 | 11 | import java.lang.reflect.Method; 12 | import java.util.concurrent.Executor; 13 | 14 | @Configuration 15 | @EnableAsync 16 | public class MyAsyncConfigurer implements AsyncConfigurer { 17 | private static Logger logger = LoggerFactory.getLogger(MyAsyncConfigurer.class); 18 | 19 | /** 20 | * 自定义异步线程池,若不重写会使用默认的线程池。 21 | * @return 22 | */ 23 | @Override 24 | public Executor getAsyncExecutor() { 25 | //使用Spring内置线程池任务对象 26 | ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); 27 | taskExecutor.setCorePoolSize(10); 28 | taskExecutor.setMaxPoolSize(20); 29 | taskExecutor.setQueueCapacity(25); 30 | taskExecutor.initialize(); 31 | return taskExecutor; 32 | } 33 | 34 | @Override 35 | public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { 36 | return new MyAsyncExceptionHandler(); 37 | } 38 | 39 | 40 | class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler { 41 | 42 | @Override 43 | public void handleUncaughtException(Throwable throwable, Method method, Object... objects) { 44 | logger.info("Exception message - " + throwable.getMessage()); 45 | logger.info("Method name - " + method.getName()); 46 | for (Object param : objects) { 47 | logger.info("Parameter value - " + param); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Event-Springboot/src/main/java/com/skypyb/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | public class User implements Serializable { 6 | 7 | private Long id; 8 | 9 | private String userName; 10 | 11 | private String password; 12 | 13 | public User() { 14 | } 15 | 16 | public User(Long id, String userName, String password) { 17 | this.id = id; 18 | this.userName = userName; 19 | this.password = password; 20 | } 21 | 22 | public Long getId() { 23 | return id; 24 | } 25 | 26 | public void setId(Long id) { 27 | this.id = id; 28 | } 29 | 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 | @Override 47 | public String toString() { 48 | final StringBuffer sb = new StringBuffer("User{"); 49 | sb.append("id=").append(id); 50 | sb.append(", userName='").append(userName).append('\''); 51 | sb.append('}'); 52 | return sb.toString(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Event-Springboot/src/main/java/com/skypyb/event/UserRegisterEvent.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.event; 2 | 3 | import com.skypyb.entity.User; 4 | import org.springframework.context.ApplicationEvent; 5 | 6 | /** 7 | * 用户注册事件 8 | */ 9 | public class UserRegisterEvent extends ApplicationEvent { 10 | 11 | private User user; 12 | 13 | /** 14 | * 重写构造函数 15 | * @param source 16 | * @param user 17 | */ 18 | public UserRegisterEvent(Object source, User user) { 19 | super(source); 20 | this.user = user; 21 | } 22 | 23 | 24 | public User getUser() { 25 | return user; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Event-Springboot/src/main/java/com/skypyb/listener/InitializationListener.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.listener; 2 | 3 | import com.skypyb.entity.User; 4 | import com.skypyb.event.UserRegisterEvent; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.context.ApplicationListener; 8 | import org.springframework.scheduling.annotation.Async; 9 | import org.springframework.stereotype.Component; 10 | 11 | /** 12 | * 用户注册完了,要初始化一些数据嘛 13 | * 这是监听用户注册的初始化方法 14 | */ 15 | @Component 16 | public class InitializationListener implements ApplicationListener { 17 | 18 | private static Logger logger = LoggerFactory.getLogger(InitializationListener.class); 19 | 20 | @Override 21 | @Async 22 | public void onApplicationEvent(UserRegisterEvent event) { 23 | User user = event.getUser(); 24 | //init(user) 25 | logger.info("User initialization completed."); 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Event-Springboot/src/main/java/com/skypyb/service/MailService.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.service; 2 | 3 | import com.skypyb.event.UserRegisterEvent; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.context.event.EventListener; 7 | import org.springframework.scheduling.annotation.Async; 8 | import org.springframework.stereotype.Service; 9 | 10 | /** 11 | * 假设这是个发邮件的服务 12 | */ 13 | @Service 14 | public class MailService { 15 | private static Logger logger = LoggerFactory.getLogger(MailService.class); 16 | 17 | /* 18 | public void send(Mail mail) { 19 | ... 20 | }*/ 21 | 22 | 23 | /** 24 | * 监听用户注册,发送注册成功邮件。 25 | * 26 | * @param event 27 | */ 28 | @EventListener 29 | @Async 30 | public void userRegister(UserRegisterEvent event) { 31 | //send(xxx); 32 | 33 | logger.info("Send a registration success email to the user! user name : {}", 34 | event.getUser().getUserName()); 35 | } 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /Event-Springboot/src/main/java/com/skypyb/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.service; 2 | 3 | 4 | import com.skypyb.entity.User; 5 | import com.skypyb.event.UserRegisterEvent; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.context.ApplicationContext; 10 | import org.springframework.stereotype.Service; 11 | 12 | @Service 13 | public class UserService { 14 | private static Logger logger = LoggerFactory.getLogger(UserService.class); 15 | 16 | @Autowired 17 | private ApplicationContext context; 18 | 19 | 20 | public void register(User user) { 21 | //repository.save(user) 22 | logger.info("User register success! user :{}",user); 23 | 24 | context.publishEvent(new UserRegisterEvent(this, user)); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Event-Springboot/src/test/java/com/skypyb/EventTest.java: -------------------------------------------------------------------------------- 1 | package com.skypyb; 2 | 3 | import com.skypyb.entity.User; 4 | import com.skypyb.service.UserService; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | 11 | import java.util.UUID; 12 | 13 | @SpringBootTest 14 | @RunWith(SpringRunner.class) 15 | public class EventTest { 16 | 17 | @Autowired 18 | private UserService userService; 19 | 20 | @Test 21 | public void test1() { 22 | User u = new User() {{ 23 | setId(1L); 24 | setUserName("skypyb"); 25 | setPassword(UUID.randomUUID().toString()); 26 | }}; 27 | 28 | userService.register(u); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 skypyb 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 使用各类主流框架、以及中间件整合之类的代码演示,注释详细 2 | --- 3 | [![License](https://img.shields.io/badge/License-MIT-red.svg)](https://mit-license.org/) 4 | 5 |
6 |
7 | 8 | ### Demo 演示列表 9 | - [sc-demo-alibaba](https://github.com/skypyb/code_demo/tree/master/sc-demo-alibaba):Spring Cloud Alibaba全家桶的示例,服务治理、熔断、通信、网关、限流、鉴权等 10 | - [spring-security-demo](https://github.com/skypyb/code_demo/tree/master/spring-security-demo):(内附sql脚本) 标准的RBAC权限设计,基于动态查询数据库的权限判定 ( *以接口为粒度,即 Request URL+Request Method* )基于JWT的认证授权流程,使用SpringBoot+SpringSecurity+MyBatis+jjwt 11 | - [dubbo-springboot](https://github.com/skypyb/code_demo/tree/master/dubbo-springboot):SpringBoot整合Dubbo的演示,服务治理使用Zookeeper 12 | - [sc-demo-microservice](https://github.com/skypyb/code_demo/tree/master/sc-demo-microservice):SpringCloudNetfilx全家桶,包含Zuul,Eureka,Ribbon,Hystrix,Feign等组件的使用 13 | - [ssm-backstage](https://github.com/skypyb/code_demo/tree/master/ssm-backstage):Spring+SpringMVC+Mybatis注解式开发的简易后台项目,Mybatis实现一对一/一对多映射,前台使用Thymeleaf+Layui 14 | - [WebSocket](https://github.com/skypyb/code_demo/tree/master/WebSocket):SpringBoot开发的WebSocket应用,包含传统tomcat开发方式和使用`spring-boot-starter-websocket`的开发方式 15 | - [Cache-SpringBoot](https://github.com/skypyb/code_demo/tree/master/Cache-SpringBoot):SpringBoot自带的缓存实现,@CacheConfig @CacheEvict @CachePut @Cacheable 等注解使用 16 | - [RabbitMQ-SpringBoot](https://github.com/skypyb/code_demo/tree/master/RabbitMQ-SpringBoot):SpringBoot 集成 RabbitMQ; 消息发送/接收、死信队列 17 | - [Event-Springboot](https://github.com/skypyb/code_demo/tree/master/Event-Springboot):SpringBoot实现异步事件驱动(发布、监听)编程,AsyncConfigurer异步配置演示,ApplicationEvent、ApplicationListener、@EventListener等相关接口/注解使用示例 18 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/README.md: -------------------------------------------------------------------------------- 1 | SpringBoot 集成 RabbitMQ; 消息发送/接收、死信队列 2 | --- 3 | 4 | * IDEA中选择[Project Structure]的Project子菜单, 进行如下操作导入: 5 | `绿色加号 -> Import Module -> 选择build.gradle -> OK -> ... ` 6 | 7 | * 两个项目的 test 文件夹下均有演示测试类 8 | * 测试前先启动Consumer服务器,两个服务的yml配置文件都要改为可以连上的RabbitMQ 9 | 10 |
11 |
12 | 13 | ### 完成的功能 14 | * 生产者消费者基础功能,消息收发 15 | * 注解形式/配置类形式 创建Queue、ExChange、Binding 16 | * 配置监听器工厂,指定消息限流次数、并发线程数 17 | * 死信队列相关配置,使用死信队列实现延时消息的收/发 18 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Consumer/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | springBootVersion = '2.0.4.RELEASE' 4 | } 5 | repositories { 6 | mavenLocal() 7 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 8 | mavenCentral() 9 | } 10 | dependencies { 11 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 12 | } 13 | } 14 | 15 | apply plugin: 'java' 16 | apply plugin: 'idea' 17 | apply plugin: 'org.springframework.boot' 18 | 19 | jar { 20 | baseName = 'RabbitMQ-Consumer' 21 | version = '0.0.1-SNAPSHOT' 22 | } 23 | 24 | sourceCompatibility = 1.8 25 | targetCompatibility = 1.8 26 | 27 | allprojects { 28 | repositories { 29 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 30 | mavenCentral() 31 | } 32 | } 33 | 34 | dependencies { 35 | compile fileTree(dir: 'libs', include: ['*.jar']) 36 | // compile('org.springframework.boot:spring-boot-starter-data-redis:2.0.4.RELEASE') 37 | compile('org.springframework.boot:spring-boot-starter-amqp:2.0.4.RELEASE') 38 | // compile("com.google.code.gson:gson:2.8.0") 39 | compile('org.springframework.boot:spring-boot-starter-web:2.0.4.RELEASE') 40 | // compile('org.springframework.boot:spring-boot-starter-thymeleaf') 41 | // compile group: 'org.freemarker', name: 'freemarker', version: '2.3.23' 42 | // compile('org.springframework.boot:spring-boot-starter-data-jpa') 43 | // compile group: 'org.mybatis', name: 'mybatis', version: '3.4.6' 44 | compile group: 'mysql', name: 'mysql-connector-java', version: '6.0.6' 45 | // compile "org.springframework.boot:spring-boot-devtools:2.0.4.RELEASE" 46 | testCompile('org.springframework.boot:spring-boot-starter-test:2.0.4.RELEASE') 47 | } 48 | 49 | tasks.withType(JavaCompile) { 50 | options.encoding = "UTF-8" 51 | } 52 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Consumer/out/production/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8081 3 | servlet: 4 | context-path: / 5 | spring: 6 | http: 7 | encoding: 8 | charset: UTF-8 9 | jackson: 10 | #前端页面传Date值时格式化 11 | date-format: yyyy-MM-dd HH:mm:ss 12 | time-zone: GMT+8 13 | #rabbitmq基本配置 14 | rabbitmq: 15 | addresses: 192.168.194.132:5672 16 | username: admin 17 | password: 614 18 | virtual-host: / 19 | connection-timeout: 15s 20 | #rabbitmq消费端配置 21 | listener: 22 | simple: 23 | #并发数 24 | concurrency: 5 25 | #最大并发数 26 | max-concurrency: 10 27 | #签收模式:手工签收、自动签收 28 | acknowledge-mode: manual 29 | #限流,在此消费端同一时间只有一条消息消费 30 | prefetch: 1 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Consumer/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'RabbitMQ-Consumer' 2 | 3 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Consumer/src/main/java/com/skypyb/rabbitmq/Application.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.rabbitmq; 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 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Consumer/src/main/java/com/skypyb/rabbitmq/config/RabbitMQCoreConfig.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.rabbitmq.config; 2 | 3 | import org.springframework.amqp.core.AcknowledgeMode; 4 | import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; 5 | import org.springframework.amqp.rabbit.connection.ConnectionFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | @Configuration 11 | public class RabbitMQCoreConfig { 12 | 13 | @Autowired 14 | private ConnectionFactory connectionFactory; 15 | 16 | 17 | @Bean(name = "prefetchCount5Container") 18 | public SimpleRabbitListenerContainerFactory prefetchCount5Container() { 19 | SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); 20 | //并发数设置: 初始化线程3,最大并发5 21 | factory.setConcurrentConsumers(3); 22 | factory.setMaxConcurrentConsumers(3); 23 | 24 | ////限流,同一单位时间内只有5条消息消费 25 | factory.setConnectionFactory(connectionFactory); 26 | factory.setPrefetchCount(5); 27 | factory.setAcknowledgeMode(AcknowledgeMode.MANUAL); 28 | 29 | return factory; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Consumer/src/main/java/com/skypyb/rabbitmq/controller/DeadReceiver.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.rabbitmq.controller; 2 | 3 | import com.rabbitmq.client.Channel; 4 | import com.skypyb.rabbitmq.config.RabbitBindConfig; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 8 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 9 | import org.springframework.amqp.support.AmqpHeaders; 10 | import org.springframework.messaging.handler.annotation.Headers; 11 | import org.springframework.messaging.handler.annotation.Payload; 12 | import org.springframework.stereotype.Component; 13 | 14 | import java.io.IOException; 15 | import java.util.Map; 16 | 17 | // 18 | //containerFactory 监听器工厂设置,指定一个被Spring管理的监听器工厂 19 | @RabbitListener(queues = {RabbitBindConfig.SKYPYB_DEAD_QUEUE}, containerFactory = "prefetchCount5Container") 20 | @Component 21 | public class DeadReceiver { 22 | 23 | private Logger logger = LoggerFactory.getLogger(DeadReceiver.class); 24 | 25 | @RabbitHandler 26 | public void onDeadMessage(@Payload String message, 27 | @Headers Map headers, 28 | Channel channel) throws IOException { 29 | 30 | logger.info("死信队列接收消息: {}", message); 31 | 32 | //delivery tag可以从headers中get出来 33 | Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG); 34 | 35 | try { 36 | channel.basicAck(deliveryTag, false); 37 | } catch (Exception e) { 38 | System.err.println(e.getMessage()); 39 | boolean redelivered = (boolean) headers.get(AmqpHeaders.REDELIVERED); 40 | channel.basicNack(deliveryTag, false, !redelivered); 41 | } 42 | 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Consumer/src/main/java/com/skypyb/rabbitmq/controller/DelayReceiver.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.rabbitmq.controller; 2 | 3 | import com.rabbitmq.client.Channel; 4 | import com.skypyb.rabbitmq.config.RabbitBindConfig; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 8 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 9 | import org.springframework.amqp.support.AmqpHeaders; 10 | import org.springframework.messaging.handler.annotation.Headers; 11 | import org.springframework.messaging.handler.annotation.Payload; 12 | import org.springframework.stereotype.Component; 13 | 14 | import java.io.IOException; 15 | import java.util.Map; 16 | 17 | @RabbitListener(queues = {RabbitBindConfig.SKYPYB_DELAY_QUEUE}) 18 | @Component 19 | public class DelayReceiver { 20 | 21 | private Logger logger = LoggerFactory.getLogger(DelayReceiver.class); 22 | 23 | @RabbitHandler 24 | public void onDelayMessage(@Payload String message, 25 | @Headers Map headers, 26 | Channel channel) throws IOException { 27 | 28 | logger.info("监听延时交换机, 收到消息: {}", message); 29 | 30 | //delivery tag可以从headers中get出来 31 | Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG); 32 | 33 | try { 34 | channel.basicAck(deliveryTag, false); 35 | } catch (Exception e) { 36 | boolean redelivered = (boolean) headers.get(AmqpHeaders.REDELIVERED); 37 | channel.basicNack(deliveryTag, false, !redelivered); 38 | } 39 | 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Consumer/src/main/java/com/skypyb/rabbitmq/controller/User1Receiver.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.rabbitmq.controller; 2 | 3 | import com.rabbitmq.client.Channel; 4 | import com.skypyb.rabbitmq.entity.User1; 5 | import org.springframework.amqp.rabbit.annotation.*; 6 | import org.springframework.amqp.support.AmqpHeaders; 7 | import org.springframework.messaging.handler.annotation.Headers; 8 | import org.springframework.messaging.handler.annotation.Payload; 9 | import org.springframework.stereotype.Component; 10 | 11 | import java.io.IOException; 12 | import java.util.Map; 13 | 14 | @Component 15 | public class User1Receiver { 16 | 17 | /** 18 | * @param user1 消息体,使用 @Payload 注解 19 | * @param headers 消息头,使用 @Headers 注解 20 | * @param channel 21 | */ 22 | /*@RabbitListener表示监听的具体队列. 23 | bindings属性代表绑定。里边有几个值填写,填写好绑定的队列名字和交换机名字 24 | 指定好routingKey。若指定的这些参数不存在的话。则会自行给你创建好 25 | durable代表是否持久化 26 | */ 27 | @RabbitListener(bindings = @QueueBinding( 28 | value = @Queue(value = "user1-queue", durable = "true"), 29 | exchange = @Exchange(name = "user1-exchange", durable = "true", type = "topic"), 30 | key = "user1.#" 31 | ) 32 | ) 33 | @RabbitHandler//标识这个方法用于消费消息 34 | public void onUser1Message(@Payload User1 user1, 35 | @Headers Map headers, 36 | Channel channel) throws IOException { 37 | //消费者操作 38 | System.out.println("-------收到消息辣!-----"); 39 | System.out.println("发过来的用户名为:" + user1.getName()); 40 | 41 | //delivery tag可以从消息头里边get出来 42 | Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG); 43 | 44 | try{ 45 | 46 | //basicAck()表示确认已经消费消息。通知一下mq,需要先得到 delivery tag 47 | channel.basicAck(deliveryTag, false); 48 | }catch (Exception e){ 49 | 50 | boolean redelivered = (boolean) headers.get(AmqpHeaders.REDELIVERED); 51 | //requeue参数:如果被拒绝的消息应该被重新排队而不是丢弃/死信,则为true,这个参数代表是否重新分发 52 | channel.basicNack(deliveryTag,false,!redelivered); 53 | } 54 | 55 | 56 | 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Consumer/src/main/java/com/skypyb/rabbitmq/entity/User1.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.rabbitmq.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | public class User1 implements Serializable{ 6 | 7 | private Long id; 8 | private String name; 9 | private String messageId;//储存消息发送的唯一标识 10 | 11 | 12 | public User1() { 13 | } 14 | 15 | public User1(Long id, String name, String messageId) { 16 | this.id = id; 17 | this.name = name; 18 | this.messageId = messageId; 19 | } 20 | 21 | public Long getId() { 22 | return id; 23 | } 24 | 25 | public void setId(Long 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 String getMessageId() { 38 | return messageId; 39 | } 40 | 41 | public void setMessageId(String messageId) { 42 | this.messageId = messageId; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Consumer/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8081 3 | servlet: 4 | context-path: / 5 | spring: 6 | http: 7 | encoding: 8 | charset: UTF-8 9 | jackson: 10 | #前端页面传Date值时格式化 11 | date-format: yyyy-MM-dd HH:mm:ss 12 | time-zone: GMT+8 13 | #rabbitmq基本配置 14 | rabbitmq: 15 | addresses: 192.168.194.132:5672 16 | username: admin 17 | password: 614 18 | virtual-host: / 19 | connection-timeout: 15s 20 | #rabbitmq消费端配置 21 | listener: 22 | simple: 23 | #并发数 24 | concurrency: 5 25 | #最大并发数 26 | max-concurrency: 10 27 | #签收模式:手工签收、自动签收 28 | acknowledge-mode: manual 29 | #限流,在此消费端同一时间只有一条消息消费 30 | prefetch: 1 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Producer/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | springBootVersion = '2.0.4.RELEASE' 4 | } 5 | repositories { 6 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 7 | mavenCentral() 8 | } 9 | dependencies { 10 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 11 | } 12 | } 13 | 14 | apply plugin: 'java' 15 | apply plugin: 'idea' 16 | apply plugin: 'org.springframework.boot' 17 | 18 | jar { 19 | baseName = 'RabbitMQ-Producer' 20 | version = '0.0.1-SNAPSHOT' 21 | } 22 | 23 | sourceCompatibility = 1.8 24 | targetCompatibility = 1.8 25 | 26 | allprojects { 27 | repositories { 28 | mavenLocal() 29 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 30 | mavenCentral() 31 | } 32 | } 33 | 34 | dependencies { 35 | compile fileTree(dir: 'libs', include: ['*.jar']) 36 | // compile('org.springframework.boot:spring-boot-starter-data-redis:2.0.4.RELEASE') 37 | compile('org.springframework.boot:spring-boot-starter-amqp:2.0.4.RELEASE') 38 | // compile("com.google.code.gson:gson:2.8.0") 39 | compile('org.springframework.boot:spring-boot-starter-web:2.0.4.RELEASE') 40 | // compile('org.springframework.boot:spring-boot-starter-thymeleaf') 41 | // compile group: 'org.freemarker', name: 'freemarker', version: '2.3.23' 42 | // compile('org.springframework.boot:spring-boot-starter-data-jpa') 43 | // compile group: 'org.mybatis', name: 'mybatis', version: '3.4.6' 44 | compile group: 'mysql', name: 'mysql-connector-java', version: '6.0.6' 45 | // compile "org.springframework.boot:spring-boot-devtools:2.0.4.RELEASE" 46 | testCompile('org.springframework.boot:spring-boot-starter-test:2.0.4.RELEASE') 47 | } 48 | 49 | tasks.withType(JavaCompile) { 50 | options.encoding = "UTF-8" 51 | } 52 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Producer/out/production/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | servlet: 4 | context-path: / 5 | spring: 6 | http: 7 | encoding: 8 | charset: UTF-8 9 | jackson: 10 | #前端页面传Date值时格式化 11 | date-format: yyyy-MM-dd HH:mm:ss 12 | time-zone: GMT+8 13 | rabbitmq: 14 | port: 5672 15 | host: 192.168.194.132 16 | username: admin 17 | password: 614 18 | virtual-host: / 19 | connection-timeout: 15s 20 | #启用消息确认机制。能收到MQ Broker的异步响应 21 | publisher-confirms: true 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Producer/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'RabbitMQ-Producer' 2 | 3 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Producer/src/main/java/com/skypyb/rabbitmq/Application.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.rabbitmq; 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 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Producer/src/main/java/com/skypyb/rabbitmq/entity/User1.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.rabbitmq.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | public class User1 implements Serializable{ 6 | 7 | private Long id; 8 | private String name; 9 | private String messageId;//储存消息发送的唯一标识 10 | 11 | 12 | public User1() { 13 | } 14 | 15 | public User1(Long id, String name, String messageId) { 16 | this.id = id; 17 | this.name = name; 18 | this.messageId = messageId; 19 | } 20 | 21 | public Long getId() { 22 | return id; 23 | } 24 | 25 | public void setId(Long 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 String getMessageId() { 38 | return messageId; 39 | } 40 | 41 | public void setMessageId(String messageId) { 42 | this.messageId = messageId; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Producer/src/main/java/com/skypyb/rabbitmq/producer/User1Sender.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.rabbitmq.producer; 2 | 3 | import com.skypyb.rabbitmq.entity.User1; 4 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 5 | import org.springframework.amqp.rabbit.support.CorrelationData; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Component; 8 | 9 | 10 | @Component 11 | public class User1Sender { 12 | 13 | @Autowired 14 | private RabbitTemplate rabbitTemplate;//操作rabbitmq的模板 15 | 16 | 17 | /** 18 | * 回调函数,confirm 确认 19 | */ 20 | final RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() { 21 | 22 | /** 23 | * 24 | * @param correlationData 消息唯一ID 25 | * @param ack 确认消息是否被MQBroker接收,true是已被接收,false为没被接收/投递失败/异常/... 26 | * @param cause 27 | */ 28 | @Override 29 | public void confirm(CorrelationData correlationData, boolean ack, String cause) { 30 | System.out.println("CorrelationData:" + correlationData); 31 | 32 | if (ack) { 33 | System.out.println("消息已被消费~~~"); 34 | } else { 35 | System.err.println("消息未被消费!!!"); 36 | } 37 | } 38 | }; 39 | 40 | public void send(User1 user1) { 41 | 42 | //这里是设置回调 43 | rabbitTemplate.setConfirmCallback(confirmCallback); 44 | 45 | //下面是发消息 46 | CorrelationData correlationData = new CorrelationData(); 47 | correlationData.setId(user1.getMessageId()); 48 | rabbitTemplate.convertAndSend( 49 | "user1-exchange",//exchange 50 | "user1.key1",//routingKey 51 | user1,//消息体内容 52 | correlationData//消息唯一ID 53 | ); 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Producer/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | servlet: 4 | context-path: / 5 | spring: 6 | http: 7 | encoding: 8 | charset: UTF-8 9 | jackson: 10 | #前端页面传Date值时格式化 11 | date-format: yyyy-MM-dd HH:mm:ss 12 | time-zone: GMT+8 13 | rabbitmq: 14 | port: 5672 15 | host: 192.168.194.132 16 | username: admin 17 | password: 614 18 | virtual-host: / 19 | connection-timeout: 15s 20 | #启用消息确认机制。能收到MQ Broker的异步响应 21 | publisher-confirms: true 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /RabbitMQ-SpringBoot/RabbitMQ-Producer/src/test/java/com/skypyb/test/RabbitmqTest.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.test; 2 | 3 | import com.skypyb.rabbitmq.Application; 4 | import com.skypyb.rabbitmq.entity.User1; 5 | import com.skypyb.rabbitmq.producer.User1Sender; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.amqp.core.Message; 11 | import org.springframework.amqp.core.MessageBuilder; 12 | import org.springframework.amqp.core.MessagePostProcessor; 13 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.boot.test.context.SpringBootTest; 16 | import org.springframework.test.context.junit4.SpringRunner; 17 | 18 | import java.util.UUID; 19 | 20 | @RunWith(SpringRunner.class) 21 | @SpringBootTest(classes = Application.class) 22 | public class RabbitmqTest { 23 | 24 | @Autowired 25 | private User1Sender userSender; 26 | 27 | @Autowired 28 | private RabbitTemplate rabbitTemplate; 29 | 30 | Logger logger = LoggerFactory.getLogger(RabbitmqTest.class); 31 | 32 | @Test 33 | public void testSend1() { 34 | 35 | for (long i = 0; i < 10; i++) { 36 | User1 user1 = new User1(); 37 | 38 | user1.setId(i); 39 | user1.setName("测试用户" + i); 40 | user1.setMessageId("user1$" + System.currentTimeMillis() + "$" + UUID.randomUUID().toString()); 41 | 42 | userSender.send(user1); 43 | } 44 | } 45 | 46 | 47 | @Test 48 | public void testDead() { 49 | 50 | //单位毫秒 51 | String ttl = "3000"; 52 | 53 | MessagePostProcessor msgProcessor = (Message msg) -> { 54 | msg.getMessageProperties().setExpiration(ttl); 55 | return msg; 56 | }; 57 | 58 | 59 | rabbitTemplate.convertAndSend("skypyb-ordinary-exchange", 60 | "skypyb.key.ordinary.one", "死信 -- 指定时间:" + ttl, msgProcessor); 61 | 62 | rabbitTemplate.convertAndSend("skypyb-ordinary-exchange", 63 | "skypyb.key.ordinary.one", "死信 -- 默认值"); 64 | 65 | 66 | logger.info("-----消息发送完毕-----"); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /WebSocket/README.md: -------------------------------------------------------------------------------- 1 | SpringBoot开发WebSocket应用 2 | --- 3 | 4 | * IDEA中选择[Project Structure]的Project子菜单, 进行如下操作导入: 5 | `绿色加号 -> Import Module -> 选择build.gradle -> OK -> ... ` 6 | * 启动服务器后直接本地打开resources下的HTML文件即可 7 | 8 | 9 | com.skypyb.websocket 包下为传统 @ServerEndpoint 注解方式的 WebSocket 开发演示 10 | com.skypyb.springboot_websocket 包下为集成 spring-boot-starter-websocket 的 WebSocket 开发演示 -------------------------------------------------------------------------------- /WebSocket/websocket/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | springBootVersion = '2.0.4.RELEASE' 4 | } 5 | repositories { 6 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 7 | mavenCentral() 8 | } 9 | dependencies { 10 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 11 | } 12 | } 13 | 14 | apply plugin: 'java' 15 | apply plugin: 'idea' 16 | apply plugin: 'org.springframework.boot' 17 | 18 | jar { 19 | baseName = 'websocket' 20 | version = '0.0.1-SNAPSHOT' 21 | } 22 | 23 | sourceCompatibility = 1.8 24 | targetCompatibility = 1.8 25 | 26 | allprojects { 27 | repositories { 28 | mavenLocal() 29 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 30 | mavenCentral() 31 | } 32 | } 33 | 34 | dependencies { 35 | compile fileTree(dir: 'libs', include: ['*.jar']) 36 | compile('org.springframework.boot:spring-boot-starter-websocket:2.0.4.RELEASE') 37 | testCompile('org.springframework.boot:spring-boot-starter-test:2.0.4.RELEASE') 38 | } 39 | 40 | tasks.withType(JavaCompile) { 41 | options.encoding = "UTF-8" 42 | } 43 | -------------------------------------------------------------------------------- /WebSocket/websocket/out/production/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | spring: 4 | http: 5 | encoding: 6 | charset: UTF-8 7 | jackson: 8 | #前端页面传Date值时格式化 9 | date-format: yyyy-MM-dd HH:mm:ss 10 | time-zone: GMT+8 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /WebSocket/websocket/out/production/resources/view/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | webSocket 6 | 9 | 10 | 11 |

WebSocket Demo.

12 |

WebSocket Demo..

13 |

WebSocket Demo...

14 | 15 | 16 | 60 | -------------------------------------------------------------------------------- /WebSocket/websocket/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'websocket' 2 | 3 | -------------------------------------------------------------------------------- /WebSocket/websocket/src/main/java/com/skypyb/WebSocketApplication.java: -------------------------------------------------------------------------------- 1 | package com.skypyb; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.scheduling.annotation.EnableScheduling; 6 | 7 | @SpringBootApplication 8 | @EnableScheduling 9 | public class WebSocketApplication { 10 | public static void main(String[] args) { 11 | SpringApplication.run(WebSocketApplication.class, args); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /WebSocket/websocket/src/main/java/com/skypyb/scheduled/SchedulerConfig.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.scheduled; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; 6 | 7 | @Configuration 8 | public class SchedulerConfig { 9 | 10 | @Bean 11 | public ThreadPoolTaskScheduler taskScheduler() { 12 | ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); 13 | return taskScheduler; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /WebSocket/websocket/src/main/java/com/skypyb/scheduled/WebSocketSendMessageScheduled.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.scheduled; 2 | 3 | import com.skypyb.springboot_websocket.MyWebSocketHandler; 4 | import com.skypyb.websocket.WebSocketServerOne; 5 | import org.springframework.scheduling.annotation.Scheduled; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.time.LocalDateTime; 9 | import java.util.concurrent.TimeUnit; 10 | 11 | @Component 12 | public class WebSocketSendMessageScheduled { 13 | 14 | @Scheduled(fixedRate = 3 * 1000) 15 | public void publish() { 16 | String msg = LocalDateTime.now().toString(); 17 | WebSocketServerOne.fanoutMessage(msg); 18 | MyWebSocketHandler.fanoutMessage(msg); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /WebSocket/websocket/src/main/java/com/skypyb/websocket/WebSocketConfigOne.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.websocket; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.socket.server.standard.ServerEndpointExporter; 6 | 7 | @Configuration 8 | public class WebSocketConfigOne { 9 | 10 | /** 11 | * 这个bean会自动注册使用了@ServerEndpoint注解声明的对象 12 | * 没有的话会报404 13 | * 14 | * @return 15 | */ 16 | @Bean 17 | public ServerEndpointExporter serverEndpointExporter() { 18 | 19 | return new ServerEndpointExporter(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /WebSocket/websocket/src/main/java/com/skypyb/websocket/WebSocketServerOne.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.websocket; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import javax.websocket.*; 6 | import javax.websocket.server.ServerEndpoint; 7 | import java.io.IOException; 8 | import java.util.concurrent.CopyOnWriteArraySet; 9 | 10 | /** 11 | * @ServerEndpoint 该注解可以将类定义成一个WebSocket服务器端, 12 | * @OnOpen 表示有浏览器链接过来的时候被调用 13 | * @OnClose 表示浏览器发出关闭请求的时候被调用 14 | * @OnMessage 表示浏览器发消息的时候被调用 15 | * @OnError 表示报错了 16 | */ 17 | @ServerEndpoint("/ws/serverOne") 18 | @Component 19 | public class WebSocketServerOne { 20 | 21 | //concurrent包下线程安全的Set 22 | private static final CopyOnWriteArraySet SESSIONS = new CopyOnWriteArraySet<>(); 23 | 24 | private Session session; 25 | 26 | @OnOpen 27 | public void onOpen(Session session) { 28 | this.session = session; 29 | SESSIONS.add(this); 30 | System.out.println(String.format("成功建立连接~ 当前总连接数为:%s", SESSIONS.size())); 31 | } 32 | 33 | @OnClose 34 | public void onClose() { 35 | SESSIONS.remove(this); 36 | System.out.println(String.format("成功关闭连接~ 当前总连接数为:%s", SESSIONS.size())); 37 | } 38 | 39 | @OnMessage 40 | public void onMessage(String message, Session session) { 41 | System.out.println(message); 42 | } 43 | 44 | @OnError 45 | public void onError(Session session, Throwable error) { 46 | System.out.println("发生错误"); 47 | error.printStackTrace(); 48 | } 49 | 50 | /** 51 | * 指定发消息 52 | * 53 | * @param message 54 | */ 55 | public void sendMessage(String message) { 56 | try { 57 | this.session.getBasicRemote().sendText(message); 58 | } catch (IOException e) { 59 | e.printStackTrace(); 60 | } 61 | } 62 | 63 | /** 64 | * 群发消息 65 | * 66 | * @param message 67 | */ 68 | public static void fanoutMessage(String message) { 69 | SESSIONS.forEach(ws -> ws.sendMessage(message)); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /WebSocket/websocket/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | spring: 4 | http: 5 | encoding: 6 | charset: UTF-8 7 | jackson: 8 | #前端页面传Date值时格式化 9 | date-format: yyyy-MM-dd HH:mm:ss 10 | time-zone: GMT+8 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /WebSocket/websocket/src/main/resources/view/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | webSocket 6 | 9 | 10 | 11 |

WebSocket Demo.

12 |

WebSocket Demo..

13 |

WebSocket Demo...

14 | 15 | 16 | 60 | -------------------------------------------------------------------------------- /distributed-lock/build.gradle: -------------------------------------------------------------------------------- 1 | //def springBootVersion = rootProject.ext.springBootVersion 2 | 3 | 4 | 5 | buildscript { 6 | ext { 7 | bootGroupName = 'org.springframework.boot' 8 | bootVersion = '2.0.4.RELEASE' 9 | } 10 | repositories { 11 | mavenLocal() 12 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 13 | mavenCentral() 14 | } 15 | dependencies { 16 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${bootVersion}") 17 | } 18 | } 19 | 20 | 21 | apply plugin: 'java' 22 | apply plugin: 'idea' 23 | apply plugin: 'org.springframework.boot' 24 | 25 | jar { 26 | baseName = 'distributed-lock' 27 | version = '0.0.1-SNAPSHOT' 28 | } 29 | 30 | sourceCompatibility = 1.8 31 | targetCompatibility = 1.8 32 | 33 | allprojects { 34 | repositories { 35 | mavenLocal() 36 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 37 | mavenCentral() 38 | } 39 | } 40 | 41 | dependencies { 42 | compile fileTree(dir: 'libs', include: ['*.jar']) 43 | testCompile( 44 | group: bootGroupName, 45 | name: 'spring-boot-starter-test', 46 | version: bootVersion 47 | ) 48 | compile( 49 | [group: bootGroupName, name: 'spring-boot-starter-data-redis', version: bootVersion], 50 | [group: bootGroupName, name: 'spring-boot-starter-web', version: bootVersion], 51 | [group: 'com.101tec', name: 'zkclient', version: '0.11'], 52 | [group: 'redis.clients', name: 'jedis',version: '2.9.0'], 53 | ) 54 | } 55 | 56 | 57 | tasks.withType(JavaCompile) { 58 | options.encoding = "UTF-8" 59 | } 60 | -------------------------------------------------------------------------------- /distributed-lock/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'distributed-lock' 2 | 3 | -------------------------------------------------------------------------------- /distributed-lock/src/main/java/com/skypyb/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.skypyb; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DemoApplication { 8 | public static void main(String[] args) { 9 | SpringApplication.run(DemoApplication.class, args); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /distributed-lock/src/main/java/com/skypyb/config/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.data.redis.connection.RedisConnectionFactory; 6 | import org.springframework.data.redis.core.RedisTemplate; 7 | import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; 8 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 9 | import org.springframework.data.redis.serializer.StringRedisSerializer; 10 | 11 | @Configuration 12 | public class RedisConfig { 13 | @Bean 14 | public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { 15 | RedisTemplate redisTemplate = new RedisTemplate<>(); 16 | StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); 17 | redisTemplate.setKeySerializer(stringRedisSerializer); 18 | redisTemplate.setHashKeySerializer(stringRedisSerializer); 19 | redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(Object.class)); 20 | redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); 21 | redisTemplate.setConnectionFactory(connectionFactory); 22 | return redisTemplate; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /distributed-lock/src/main/java/com/skypyb/lock/DistributedLock.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.lock; 2 | 3 | 4 | import java.util.concurrent.TimeUnit; 5 | 6 | /** 7 | * 分布式锁的接口 8 | * 9 | * @author skypyb 10 | * @date 2019-10-27 11 | */ 12 | public interface DistributedLock { 13 | 14 | 15 | /** 16 | * 加锁的方法,直到获取锁为止 17 | * 18 | * @throws InterruptedException 19 | */ 20 | void lock() throws InterruptedException; 21 | 22 | /** 23 | * 尝试获取锁的方法,获取不到锁则直接返回false 24 | * 25 | * @return true代表加锁成功,false反之 26 | */ 27 | boolean tryLock(); 28 | 29 | /** 30 | * 尝试获取锁的方法,与{@link this#tryLock()}不同的是,他最长会等待到超时时间过后才结束 31 | * 32 | * @param time 时间参数 33 | * @param unit 时间单位 34 | * @return true表示成功获取到锁,false反之,在返回false时 这通常代表已经等待完设置的时间后仍然未获得锁 35 | * @throws InterruptedException 36 | */ 37 | boolean tryLock(long time, TimeUnit unit) throws InterruptedException; 38 | 39 | /** 40 | * 与 tryLock 相对应,用作释放锁 41 | * 42 | * @return true表示成功 false反之 43 | */ 44 | boolean unlock(); 45 | } 46 | -------------------------------------------------------------------------------- /distributed-lock/src/main/java/com/skypyb/semaphore/DistributedSemaphore.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.semaphore; 2 | 3 | /** 4 | * 分布式信号量接口 5 | * Create by skypyb on 2020-06-07 6 | */ 7 | public interface DistributedSemaphore { 8 | 9 | 10 | /** 11 | * 尝试获取一个信号量 12 | * 13 | * @return true 获取成功, false 获取失败 14 | */ 15 | boolean tryAcquire(); 16 | 17 | /** 18 | * 释放自己持有的信号量 19 | */ 20 | void release(); 21 | } -------------------------------------------------------------------------------- /distributed-lock/src/main/java/com/skypyb/semaphore/SemaphoreInfo.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.semaphore; 2 | 3 | /** 4 | * 一个信号量的信息 5 | */ 6 | public final class SemaphoreInfo { 7 | 8 | //信号量的名称 9 | private final String semaphoreName; 10 | 11 | //许可证的数量 12 | private final int permits; 13 | 14 | //信号量最大持有时间 (过期时间) 单位s 15 | private final long expire; 16 | 17 | //公平 or 非公平 18 | private final boolean fair; 19 | 20 | public SemaphoreInfo(String semaphoreName, int permits, long expire) { 21 | this(semaphoreName, permits, expire, false); 22 | } 23 | 24 | public SemaphoreInfo(String semaphoreName, int permits, long expire, boolean fair) { 25 | this.semaphoreName = semaphoreName; 26 | this.permits = permits; 27 | this.expire = expire; 28 | this.fair = fair; 29 | } 30 | 31 | public String getSemaphoreName() { 32 | return semaphoreName; 33 | } 34 | 35 | public int getPermits() { 36 | return permits; 37 | } 38 | 39 | public long getExpire() { 40 | return expire; 41 | } 42 | 43 | public boolean isFair() { 44 | return fair; 45 | } 46 | } -------------------------------------------------------------------------------- /distributed-lock/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | servlet: 4 | context-path: / 5 | spring: 6 | http: 7 | encoding: 8 | charset: UTF-8 9 | #Redis配置 10 | redis: 11 | host: 192.168.194.132 12 | port: 6379 13 | #Redis连接池配置 14 | jedis: 15 | pool: 16 | min-idle: 0 17 | max-idle: 8 18 | max-active: 8 19 | max-wait: -1ms 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /distributed-lock/src/test/java/com/skypyb/DistributedLockTest.java: -------------------------------------------------------------------------------- 1 | package com.skypyb; 2 | 3 | import com.skypyb.lock.DistributedLock; 4 | import com.skypyb.lock.RedisLock; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.data.redis.core.RedisTemplate; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | 12 | import java.lang.reflect.Constructor; 13 | 14 | @RunWith(SpringRunner.class) 15 | @SpringBootTest(classes = DemoApplication.class) 16 | public class DistributedLockTest { 17 | 18 | @Autowired 19 | private RedisTemplate redisTemplate; 20 | 21 | @Test 22 | public void testOne() throws ReflectiveOperationException, InterruptedException { 23 | 24 | Constructor constructor = RedisLock.class.getDeclaredConstructor(RedisTemplate.class); 25 | constructor.setAccessible(true); 26 | DistributedLock lock = constructor.newInstance(redisTemplate); 27 | 28 | Runnable runnable = () -> { 29 | try { 30 | lock.lock(); 31 | } catch (InterruptedException e) { 32 | e.printStackTrace(); 33 | } 34 | System.out.println(Thread.currentThread().getName() + "获取到lock"); 35 | 36 | boolean unlock = lock.unlock(); 37 | System.out.println(Thread.currentThread().getName() + "释放锁结果:" + unlock); 38 | }; 39 | 40 | Thread[] threads = new Thread[10]; 41 | 42 | for (int i = 0; i < 10; i++) { 43 | threads[i] = new Thread(runnable); 44 | System.out.println(threads[i].getName()); 45 | threads[i].start(); 46 | } 47 | System.out.println("---------------"); 48 | 49 | 50 | for (Thread thread : threads) { 51 | thread.join(); 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /dubbo-springboot/README.md: -------------------------------------------------------------------------------- 1 | SpringBoot结合Apache dubbo+zookeeper实现远程服务调用 2 | --- 3 |
4 | 5 | #### 导入: 6 | * IDEA中选择[Project Structure]的Project子菜单, 进行如下操作导入: 7 | `绿色加号 -> Import Module -> 选择pom.xml -> OK -> ... ` 8 |
9 | 10 | #### 实现功能: 11 | 12 | * dubbo+zookeeper 完成服务提供与消费 13 | * 引入kryo高速序列化机制 14 | 15 | #### zookeeper单机伪集群: 16 | 使用docker-compose 运行项目中的docker-compose.zookeeper.yml 17 | ``` 18 | docker pull zookeeper:3.4.14 19 | docker network create zookeeper-service 20 | docker-compose up -d 21 | ``` 22 | -------------------------------------------------------------------------------- /dubbo-springboot/docker-compose.zookeeper.yml: -------------------------------------------------------------------------------- 1 | version: '3.1' 2 | 3 | services: 4 | zoo1: 5 | image: zookeeper:3.4.14 6 | restart: always 7 | network_mode: zookeeper-service 8 | container_name: zoo1 9 | hostname: zoo1 10 | ports: 11 | - 2181:2181 12 | environment: 13 | ZOO_MY_ID: 1 14 | ZOO_SERVERS: server.1=0.0.0.0:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888 15 | 16 | zoo2: 17 | image: zookeeper:3.4.14 18 | restart: always 19 | network_mode: zookeeper-service 20 | container_name: zoo2 21 | hostname: zoo2 22 | ports: 23 | - 2182:2181 24 | environment: 25 | ZOO_MY_ID: 2 26 | ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=0.0.0.0:2888:3888 server.3=zoo3:2888:3888 27 | 28 | zoo3: 29 | image: zookeeper:3.4.14 30 | restart: always 31 | network_mode: zookeeper-service 32 | container_name: zoo3 33 | hostname: zoo3 34 | ports: 35 | - 2183:2181 36 | environment: 37 | ZOO_MY_ID: 3 38 | ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=0.0.0.0:2888:3888 -------------------------------------------------------------------------------- /dubbo-springboot/dubbo-user-service-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.skypyb.dubbo 8 | springboot-dubbo-service-user-api 9 | 1.0.0-SNAPSHOT 10 | 11 | jar 12 | 13 | 14 | UTF-8 15 | UTF-8 16 | 1.8 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /dubbo-springboot/dubbo-user-service-api/src/main/java/com/skypyb/dubbo/service/user/api/UserService.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.dubbo.service.user.api; 2 | 3 | public interface UserService { 4 | 5 | String hello(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /dubbo-springboot/dubbo-user-service-consumer/src/main/java/com/skypyb/dubbo/user/service/consumer/DubboUserServiceConsumerApplication.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.dubbo.user.service.consumer; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.hystrix.EnableHystrix; 6 | 7 | @SpringBootApplication 8 | public class DubboUserServiceConsumerApplication { 9 | 10 | public static void main(String[] args) { 11 | SpringApplication.run(DubboUserServiceConsumerApplication.class, args); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /dubbo-springboot/dubbo-user-service-consumer/src/main/java/com/skypyb/dubbo/user/service/consumer/config/HystrixConfig.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.dubbo.user.service.consumer.config; 2 | 3 | import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet; 4 | import org.springframework.boot.web.servlet.ServletRegistrationBean; 5 | import org.springframework.cloud.netflix.hystrix.EnableHystrix; 6 | import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | @EnableHystrix 11 | @EnableHystrixDashboard 12 | @Configuration 13 | public class HystrixConfig { 14 | 15 | 16 | /** 17 | * 仪表盘 18 | * 19 | * @return 20 | */ 21 | @Bean 22 | public ServletRegistrationBean getServlet() { 23 | HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet(); 24 | ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet); 25 | registrationBean.setLoadOnStartup(1); 26 | registrationBean.addUrlMappings("/hystrix.stream"); 27 | registrationBean.setName("HystrixMetricsStreamServlet"); 28 | return registrationBean; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /dubbo-springboot/dubbo-user-service-consumer/src/main/java/com/skypyb/dubbo/user/service/consumer/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.dubbo.user.service.consumer.controller; 2 | 3 | import com.alibaba.dubbo.config.annotation.Reference; 4 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 5 | import com.skypyb.dubbo.service.user.api.UserService; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | public class UserController { 11 | 12 | @Reference(version = "${user.service.version}") 13 | private UserService userService; 14 | 15 | @HystrixCommand(fallbackMethod = "helloError") 16 | @GetMapping(value = "hello") 17 | public String hello() { 18 | return userService.hello(); 19 | } 20 | 21 | public String helloError() { 22 | return "hello hystrix"; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /dubbo-springboot/dubbo-user-service-consumer/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 80 3 | # Spring boot application 4 | spring: 5 | application: 6 | name: dubbo-user-service-consumer 7 | 8 | # UserService service version 9 | user: 10 | service: 11 | version: 1.0.0 12 | 13 | # Dubbo Config properties 14 | dubbo: 15 | ## Base packages to scan Dubbo Component:@com.alibaba.dubbo.config.annotation.Service 16 | scan: 17 | basePackages: com.skypyb.dubbo.user.service.consumer.controller 18 | ## ApplicationConfig Bean 19 | application: 20 | id: dubbo-user-service-consumer 21 | name: dubbo-user-service-consumer 22 | ## ProtocolConfig Bean 23 | protocol: 24 | id: dubbo 25 | name: dubbo 26 | port: 12345 27 | serialization: kryo #序列化机制 28 | # status: server 29 | ## RegistryConfig Bean 30 | registry: 31 | id: zookeeper 32 | address: zookeeper://192.168.8.113:2181?backup=192.168.8.113:2182,192.168.8.113:2183 33 | 34 | # Enables Dubbo All Endpoints 35 | management: 36 | endpoint: 37 | dubbo: 38 | enabled: true 39 | dubbo-shutdown: 40 | enabled: true 41 | dubbo-configs: 42 | enabled: true 43 | dubbo-services: 44 | enabled: true 45 | dubbo-references: 46 | enabled: true 47 | dubbo-properties: 48 | enabled: true 49 | # Dubbo Health 50 | health: 51 | dubbo: 52 | status: 53 | ## StatusChecker Name defaults (default : "memory", "load" ) 54 | defaults: memory 55 | ## StatusChecker Name extras (default : empty ) 56 | extras: load,threadpool -------------------------------------------------------------------------------- /dubbo-springboot/dubbo-user-service-consumer/src/test/java/com/skypyb/dubbo/user/service/consumer/DubboUserServiceConsumerApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.dubbo.user.service.consumer; 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 DubboUserServiceConsumerApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /dubbo-springboot/dubbo-user-service-provider/src/main/java/com/skypyb/dubbo/user/service/provider/DubboUserServiceProviderApplication.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.dubbo.user.service.provider; 2 | 3 | import com.alibaba.dubbo.container.Main; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.netflix.hystrix.EnableHystrix; 7 | 8 | @EnableHystrix 9 | @SpringBootApplication 10 | public class DubboUserServiceProviderApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(DubboUserServiceProviderApplication.class, args); 14 | Main.main(args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /dubbo-springboot/dubbo-user-service-provider/src/main/java/com/skypyb/dubbo/user/service/provider/api/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.dubbo.user.service.provider.api.impl; 2 | 3 | import com.alibaba.dubbo.config.annotation.Service; 4 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 5 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; 6 | import com.skypyb.dubbo.service.user.api.UserService; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.factory.annotation.Value; 10 | 11 | @Service(version = "${user.service.version}") 12 | public class UserServiceImpl implements UserService { 13 | 14 | private Logger logger = LoggerFactory.getLogger(UserService.class); 15 | 16 | @Value("${dubbo.protocol.port}") 17 | private String port; 18 | 19 | /** 20 | * Hystrix 两秒五次即熔断 21 | * 22 | * @return 23 | */ 24 | @HystrixCommand(commandProperties = { 25 | @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "5"), 26 | @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000") 27 | }) 28 | @Override 29 | public String hello() { 30 | logger.info("access hello, service port:{}", this.port); 31 | return "hello dubbo"; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /dubbo-springboot/dubbo-user-service-provider/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # Spring boot application 2 | spring: 3 | application: 4 | name: dubbo-user-service-provider 5 | 6 | # UserService service version 7 | user: 8 | service: 9 | version: 1.0.0 10 | 11 | # Dubbo Config properties 12 | dubbo: 13 | ## Base packages to scan Dubbo Component:@com.alibaba.dubbo.config.annotation.Service 14 | scan: 15 | basePackages: com.skypyb.dubbo.user.service.provider.api 16 | ## ApplicationConfig Bean 17 | application: 18 | id: dubbo-user-service-provider 19 | name: dubbo-user-service-provider 20 | qos-port: 22222 21 | qos-enable: true 22 | ## ProtocolConfig Bean 23 | protocol: 24 | id: dubbo 25 | name: dubbo 26 | port: 12345 27 | status: server 28 | serialization: kryo #序列化机制 29 | ## RegistryConfig Bean 30 | registry: 31 | id: zookeeper 32 | address: zookeeper://192.168.8.113:2181?backup=192.168.8.113:2182,192.168.8.113:2183 33 | provider: 34 | loadbalance: roundrobin #负载均衡策略 35 | 36 | # Enables Dubbo All Endpoints 37 | management: 38 | endpoint: 39 | dubbo: 40 | enabled: true 41 | dubbo-shutdown: 42 | enabled: true 43 | dubbo-configs: 44 | enabled: true 45 | dubbo-services: 46 | enabled: true 47 | dubbo-references: 48 | enabled: true 49 | dubbo-properties: 50 | enabled: true 51 | # Dubbo Health 52 | health: 53 | dubbo: 54 | status: 55 | ## StatusChecker Name defaults (default : "memory", "load" ) 56 | defaults: memory 57 | ## StatusChecker Name extras (default : empty ) 58 | extras: load,threadpool -------------------------------------------------------------------------------- /dubbo-springboot/dubbo-user-service-provider/src/test/java/com/skypyb/dubbo/user/service/provider/DubboUserServiceProviderApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.dubbo.user.service.provider; 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 DubboUserServiceProviderApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /sc-demo-alibaba/README.md: -------------------------------------------------------------------------------- 1 | SpringCloudAlibaba 的几大核心组件示例 2 | --- 3 | 4 | * IDEA中选择[Project Structure]的Project子菜单, 进行如下操作导入: 5 | `绿色加号 -> Import Module -> 选择pom.xml -> OK -> ... ` 6 | 7 | ### 说明 8 | * 集成的组件有 Nacos、Sentinel、Gateway、Feign 9 | * 至于微服务链路跟踪由于已经写过一套成熟的方案zipkin+sleuth, 所以就没写SkyWalking这东西 10 | * 服务之间的通信是用的默认的(HttpClient),没上Dubbo,也是因为写过一套Dubbo+Zookeeper的演示了 11 | 12 | ### 完成了哪些功能? 13 | * 服务治理、服务熔断、服务通信、服务网关 14 | * 网关限流、鉴权(假的鉴权,只是个demo) 15 | 16 | 17 | *关于Spring Cloud Alibaba的几个需要单独部署的组件的docker镜像:* 18 | ```shell 19 | # 默认账号密码是nacos/nacos 20 | docker pull nacos/nacos-server 21 | docker run --env MODE=standalone --name nacos -d -p 8848:8848 nacos/nacos-server 22 | ``` 23 | 24 | ```shell 25 | # 默认账号密码都是sentinel 26 | docker pull bladex/sentinel-dashboard 27 | docker run --name sentinel -d -p 8858:8858 -d bladex/sentinel-dashboard 28 | ``` -------------------------------------------------------------------------------- /sc-demo-alibaba/sc-demo-alibaba-consumer/src/main/java/com/skypyb/provider/NacosConsumerApplication.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.provider; 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.openfeign.EnableFeignClients; 7 | 8 | @SpringBootApplication 9 | @EnableDiscoveryClient//nacos使用spring cloud 原生注解 10 | @EnableFeignClients //Feign注解 11 | public class NacosConsumerApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(NacosConsumerApplication.class, args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sc-demo-alibaba/sc-demo-alibaba-consumer/src/main/java/com/skypyb/provider/config/RestConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.provider.config; 2 | 3 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.web.client.RestTemplate; 7 | 8 | @Configuration 9 | public class RestConfiguration { 10 | 11 | 12 | @Bean 13 | // @LoadBalanced 14 | public RestTemplate restTemplate() { 15 | return new RestTemplate(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /sc-demo-alibaba/sc-demo-alibaba-consumer/src/main/java/com/skypyb/provider/controller/NacosConsumerController.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.provider.controller; 2 | 3 | import com.skypyb.provider.feign.NacosHelloFeign; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.cloud.client.ServiceInstance; 6 | import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RestController; 11 | import org.springframework.web.client.RestTemplate; 12 | 13 | import javax.annotation.Resource; 14 | 15 | @RequestMapping("/consumer") 16 | @RestController 17 | public class NacosConsumerController { 18 | 19 | @Autowired 20 | private LoadBalancerClient loadBalancerClient; 21 | 22 | @Autowired 23 | private RestTemplate restTemplate; 24 | 25 | 26 | @Resource 27 | private NacosHelloFeign nacosHelloFeign; 28 | 29 | @GetMapping(value = "/hello/{msg}") 30 | public String hello(@PathVariable("msg") String msg) { 31 | //使用 LoadBalanceClient 和 RestTemplate 结合的方式来访问 32 | ServiceInstance serviceInstance = loadBalancerClient.choose("sc-demo-alibaba-provider"); 33 | String url = String.format("http://%s:%s/provider/hello/%s", 34 | serviceInstance.getHost(), serviceInstance.getPort(), msg); 35 | return restTemplate.getForObject(url, String.class); 36 | } 37 | 38 | 39 | @GetMapping(value = "/hello/feign/{msg}") 40 | public String helloFeign(@PathVariable("msg") String msg) { 41 | return nacosHelloFeign.hello(msg); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /sc-demo-alibaba/sc-demo-alibaba-consumer/src/main/java/com/skypyb/provider/fallback/HelloServiceFallback.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.provider.fallback; 2 | 3 | import com.skypyb.provider.feign.NacosHelloFeign; 4 | import org.springframework.stereotype.Component; 5 | 6 | /** 7 | * 熔断类 8 | * 要是 Feign 的接口调用失败(或者被快速失败)就会走这个类的方法进行处理 9 | */ 10 | @Component 11 | public class HelloServiceFallback implements NacosHelloFeign { 12 | 13 | @Override 14 | public String hello(String msg) { 15 | return "触发熔断机制~"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /sc-demo-alibaba/sc-demo-alibaba-consumer/src/main/java/com/skypyb/provider/feign/NacosHelloFeign.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.provider.feign; 2 | 3 | import com.skypyb.provider.fallback.HelloServiceFallback; 4 | import org.springframework.cloud.openfeign.FeignClient; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | 8 | /** 9 | * Feign客户端 10 | * 指定调用 sc-demo-alibaba-provider 的服务 11 | */ 12 | @FeignClient(value = "sc-demo-alibaba-provider",fallback = HelloServiceFallback.class) 13 | public interface NacosHelloFeign { 14 | 15 | @RequestMapping(value = "/provider/hello/{msg}") 16 | String hello(@PathVariable("msg") String msg); 17 | } 18 | -------------------------------------------------------------------------------- /sc-demo-alibaba/sc-demo-alibaba-consumer/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: sc-demo-alibaba-consumer 4 | cloud: 5 | nacos: 6 | discovery: 7 | server-addr: 192.168.3.105:8848 #注册进 nacos 8 | sentinel: 9 | transport: 10 | port: 18081 #这个端口的意思是自己这个服务开个端口和 sentinel 控制台交互 11 | dashboard: 192.168.3.105:8858 # sentinel 控制台的端口 12 | 13 | server: 14 | port: 8081 15 | 16 | feign: 17 | sentinel: 18 | enabled: true 19 | 20 | management: 21 | endpoints: 22 | web: 23 | exposure: 24 | include: "*" -------------------------------------------------------------------------------- /sc-demo-alibaba/sc-demo-alibaba-gateway/src/java/com/skypyb/gateway/GatewayApplication.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.gateway; 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.openfeign.EnableFeignClients; 7 | 8 | @SpringBootApplication 9 | @EnableDiscoveryClient//nacos使用spring cloud 原生注解 10 | @EnableFeignClients //Feign注解 11 | public class GatewayApplication { 12 | public static void main(String[] args) { 13 | SpringApplication.run(GatewayApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /sc-demo-alibaba/sc-demo-alibaba-gateway/src/java/com/skypyb/gateway/config/GatewayRateLimiterConfig.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.gateway.config; 2 | 3 | import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import reactor.core.publisher.Mono; 7 | 8 | @Configuration 9 | public class GatewayRateLimiterConfig { 10 | 11 | /** 12 | * Gateway通过内置的RequestRateLimiter过滤器实现限流,用的是令牌桶算法,借助Redis保存中间数据 13 | * 这里自定义一个KeyResolver 14 | * 作用是对来源ip进行限流 15 | */ 16 | @Bean(value = "ipKeyResolver") 17 | public KeyResolver ipKeyResolver() { 18 | return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /sc-demo-alibaba/sc-demo-alibaba-gateway/src/java/com/skypyb/gateway/config/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.gateway.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.data.redis.connection.RedisConnectionFactory; 6 | import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 7 | import org.springframework.data.redis.core.RedisTemplate; 8 | import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; 9 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 10 | import org.springframework.data.redis.serializer.StringRedisSerializer; 11 | 12 | @Configuration 13 | public class RedisConfig { 14 | 15 | @Bean 16 | public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { 17 | RedisTemplate redisTemplate = new RedisTemplate<>(); 18 | StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); 19 | redisTemplate.setKeySerializer(stringRedisSerializer); 20 | redisTemplate.setHashKeySerializer(stringRedisSerializer); 21 | redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(Object.class)); 22 | redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); 23 | redisTemplate.setConnectionFactory(connectionFactory); 24 | return redisTemplate; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /sc-demo-alibaba/sc-demo-alibaba-gateway/src/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | # 应用名称 4 | name: sc-demo-alibaba-gateway 5 | cloud: 6 | nacos: 7 | discovery: 8 | server-addr: 192.168.3.105:8848 #注册进nacos 9 | # 使用 Sentinel 作为熔断器 10 | sentinel: 11 | transport: 12 | port: 18102 13 | dashboard: 192.168.3.105:8858 14 | # 路由网关配置 15 | gateway: 16 | # 这里是设置与服务注册发现组件结合,这样可以采用服务名的路由策略 17 | discovery: 18 | locator: 19 | enabled: true 20 | # 配置路由规则 21 | routes: 22 | - id: ROUTER#sc-demo-alibaba-consumer #这个是路由ID,需要保证在所有路由定义中唯一,值随便写就是了 23 | # 采用 LoadBalanceClient 方式请求,以 lb:// 开头,后面的是注册在 Nacos 上的服务名 24 | uri: lb://sc-demo-alibaba-consumer 25 | predicates: 26 | # Method ,这里是匹配 GET 和 POST 请求 27 | - Method=GET,POST 28 | filters: 29 | - name: RequestRateLimiter 30 | args: 31 | redis-rate-limiter.burstCapacity: 20 32 | redis-rate-limiter.replenishRate: 5 33 | key-resolver: '#{@ipKeyResolver}' 34 | - id: ROUTER#sc-demo-alibaba-provider 35 | uri: lb://sc-demo-alibaba-provider 36 | predicates: 37 | - Method=GET,POST 38 | #Redis配置 39 | redis: 40 | host: 192.168.3.105 41 | port: 6379 42 | #Redis连接池配置 43 | jedis: 44 | pool: 45 | min-idle: 0 46 | max-idle: 8 47 | max-active: 8 48 | max-wait: -1ms 49 | server: 50 | port: 8888 51 | 52 | feign: 53 | sentinel: 54 | enabled: true 55 | 56 | management: 57 | endpoints: 58 | web: 59 | exposure: 60 | include: "*" 61 | 62 | # 配置日志级别,方别调试 63 | logging: 64 | level: 65 | org.springframework.cloud.gateway: debug -------------------------------------------------------------------------------- /sc-demo-alibaba/sc-demo-alibaba-provider/src/main/java/com/skypyb/provider/NacosProviderApplication.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.provider; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | 7 | @SpringBootApplication 8 | @EnableDiscoveryClient//nacos使用spring cloud 原生注解 9 | public class NacosProviderApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(NacosProviderApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /sc-demo-alibaba/sc-demo-alibaba-provider/src/main/java/com/skypyb/provider/controller/NacosProviderController.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.provider.controller; 2 | 3 | import org.springframework.web.bind.annotation.PathVariable; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RequestMapping("/provider") 8 | @RestController 9 | public class NacosProviderController { 10 | 11 | 12 | @RequestMapping(value = "/hello/{msg}") 13 | public String hello(@PathVariable("msg") String msg) { 14 | return "Hello " + msg; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sc-demo-alibaba/sc-demo-alibaba-provider/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: sc-demo-alibaba-provider 4 | cloud: 5 | nacos: 6 | discovery: 7 | server-addr: 192.168.3.105:8848 #注册进 nacos 8 | 9 | server: 10 | port: 8080 11 | 12 | management: 13 | endpoints: 14 | web: 15 | exposure: 16 | include: "*" -------------------------------------------------------------------------------- /sc-demo-microservice/build.gradle: -------------------------------------------------------------------------------- 1 | group 'com.skypyb.sc' 2 | version = '0.0.1-SNAPSHOT' 3 | apply plugin: 'java' 4 | sourceCompatibility = 1.8 5 | targetCompatibility = 1.8 6 | 7 | buildscript { 8 | ext { 9 | springBootVersion = '2.0.5.RELEASE' 10 | springCloudVersion = 'Finchley.SR3' 11 | } 12 | repositories { 13 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 14 | jcenter() 15 | mavenCentral() 16 | } 17 | 18 | dependencies {//用来打包 19 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 20 | } 21 | } 22 | 23 | allprojects { 24 | repositories { 25 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 26 | jcenter() 27 | mavenCentral() 28 | } 29 | //指定编码格式 30 | tasks.withType(JavaCompile) { 31 | options.encoding = "UTF-8" 32 | } 33 | } 34 | 35 | //设定子模块的通用配置 36 | subprojects { 37 | 38 | apply plugin: 'java' 39 | apply plugin: 'idea' 40 | //spring boot 插件 41 | apply plugin: 'org.springframework.boot' 42 | //Gradle插件,提供类似Maven的依赖关系管理功能 43 | apply plugin: 'io.spring.dependency-management' 44 | 45 | dependencies { 46 | //Actuator提供服务监控与管理的功能,路径: /actuator/{端点} 47 | compile('org.springframework.boot:spring-boot-starter-actuator') 48 | testCompile('org.springframework.boot:spring-boot-starter-test') 49 | } 50 | 51 | dependencyManagement { 52 | imports { 53 | //spring bom帮助我们在不指定版本号的情况下声明依赖项。 54 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" 55 | } 56 | } 57 | 58 | jar { 59 | manifest.attributes provider: 'gradle' 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-eureka/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | dependencies { 3 | compile("org.springframework.cloud:spring-cloud-starter-netflix-eureka-server") 4 | compile("org.springframework.boot:spring-boot-starter-security") 5 | } 6 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-eureka/out/production/resources/application.yml: -------------------------------------------------------------------------------- 1 | 2 | spring: 3 | profiles: 4 | active: eureka1 #启动时加上这个命令使用不同的配置 --spring.profiles.active=xxx 5 | security: 6 | #验证的用户名和密码 7 | user: 8 | name: user 9 | password: 614 10 | 11 | #Eureka Server 端配置 12 | eureka: 13 | client: 14 | healthcheck: 15 | enabled: true 16 | service-url: 17 | defaultZone: http://user:614@localhost:8080/eureka/,http://user:614@localhost:8081/eureka/ 18 | 19 | 20 | 21 | 22 | --- 23 | spring: 24 | profiles: eureka1 25 | application: 26 | name: sc-demo-microservice-eureka_1 27 | server: 28 | port: 8080 29 | eureka: 30 | instance: 31 | hostname: eureka1 32 | 33 | --- 34 | spring: 35 | profiles: eureka2 36 | application: 37 | name: sc-demo-microservice-eureka_2 38 | server: 39 | port: 8081 40 | eureka: 41 | instance: 42 | hostname: eureka2 43 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-eureka/src/main/java/com/skypyb/sc/EurekaServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc; 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 | @SpringBootApplication 8 | @EnableEurekaServer //表示这个服务是一个 Eureka 服务注册中心 9 | public class EurekaServerApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication application = new SpringApplication(EurekaServerApplication.class); 13 | application.run(args); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-eureka/src/main/java/com/skypyb/sc/config/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc.config; 2 | 3 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 4 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 5 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 6 | 7 | @EnableWebSecurity 8 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 9 | 10 | 11 | @Override 12 | protected void configure(HttpSecurity http) throws Exception { 13 | http.csrf().ignoringAntMatchers("/eureka/**");//这个链接不使用csrf 14 | super.configure(http); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-eureka/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | 2 | spring: 3 | profiles: 4 | active: eureka1 #启动时加上这个命令使用不同的配置 --spring.profiles.active=xxx 5 | security: 6 | #验证的用户名和密码 7 | user: 8 | name: user 9 | password: 614 10 | 11 | #Eureka Server 端配置 12 | eureka: 13 | client: 14 | healthcheck: 15 | enabled: true 16 | service-url: 17 | defaultZone: http://user:614@localhost:8080/eureka/,http://user:614@localhost:8081/eureka/ 18 | 19 | 20 | 21 | 22 | --- 23 | spring: 24 | profiles: eureka1 25 | application: 26 | name: sc-demo-microservice-eureka_1 27 | server: 28 | port: 8080 29 | eureka: 30 | instance: 31 | hostname: eureka1 32 | 33 | --- 34 | spring: 35 | profiles: eureka2 36 | application: 37 | name: sc-demo-microservice-eureka_2 38 | server: 39 | port: 8081 40 | eureka: 41 | instance: 42 | hostname: eureka2 43 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-movie/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | compile('org.springframework.boot:spring-boot-starter-web') 3 | compile('org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.2') 4 | compile('mysql:mysql-connector-java') 5 | compile("org.springframework.cloud:spring-cloud-starter-netflix-eureka-client") 6 | compile("org.springframework.cloud:spring-cloud-starter-netflix-ribbon") 7 | compile("org.springframework.cloud:spring-cloud-starter-openfeign") 8 | compile("org.springframework.cloud:spring-cloud-starter-netflix-hystrix") 9 | compile("org.springframework.cloud:spring-cloud-starter-zipkin") 10 | } 11 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-movie/out/production/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8089 3 | 4 | spring: 5 | application: 6 | name: sc-demo-microservice-movie #这个名字会注册到 Eureka 里去 7 | datasource: 8 | driver-class-name: com.mysql.jdbc.Driver 9 | url: jdbc:mysql://192.168.8.113:3306/scdemo?serverTimezone=Asia/Shanghai 10 | username: root 11 | password: 614 12 | 13 | #mybatis实体类名 14 | mybatis: 15 | type-aliases-package: com.skypyb.sc.entity 16 | configuration: 17 | #到下划线的表字段自动映射成驼峰命名法 18 | map-underscore-to-camel-case: true 19 | mapper-locations: classpath:mybatis/mapper/*.xml 20 | 21 | 22 | #Actuato 配置 23 | management: 24 | endpoint: 25 | # 暴露shutdown功能 26 | # shutdown: 27 | # enabled: true 28 | endpoints: 29 | web: 30 | exposure: 31 | include: '*' #暴露哪些端点 32 | exclude: #隐藏哪些端点 33 | 34 | #Eureka client端配置 35 | eureka: 36 | client: 37 | service-url: 38 | defaultZone: http://user:614@localhost:8080/eureka/,http://user:614@localhost:8081/eureka/ 39 | instance: 40 | prefer-ip-address: true #将自己ip注册到Eureka Server 41 | feign: 42 | hystrix: 43 | enabled: true #为 feign 打开 hystrix 支持 44 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-movie/src/main/java/com/skypyb/sc/MovieApplication.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.openfeign.EnableFeignClients; 6 | 7 | @SpringBootApplication 8 | @EnableFeignClients 9 | public class MovieApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication application = new SpringApplication(MovieApplication.class); 13 | application.run(args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-movie/src/main/java/com/skypyb/sc/config/FeignConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc.config; 2 | 3 | import feign.Logger; 4 | import feign.auth.BasicAuthRequestInterceptor; 5 | import org.springframework.context.annotation.Bean; 6 | 7 | public class FeignConfiguration { 8 | 9 | 10 | @Bean 11 | public Logger.Level feignLog() { 12 | return Logger.Level.FULL; 13 | } 14 | 15 | /** 16 | * 使用指定的用户名和密码验证所有请求 17 | * @return 18 | */ 19 | @Bean 20 | public BasicAuthRequestInterceptor basicAuthRequestInterceptor(){ 21 | return new BasicAuthRequestInterceptor("user","614"); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-movie/src/main/java/com/skypyb/sc/config/RestConfig.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc.config; 2 | 3 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.web.client.RestTemplate; 7 | 8 | @Configuration 9 | public class RestConfig { 10 | 11 | @Bean 12 | @LoadBalanced 13 | public RestTemplate restTemplate() { 14 | RestTemplate restTemplate = new RestTemplate(); 15 | 16 | return restTemplate; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-movie/src/main/java/com/skypyb/sc/controller/MovieController.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc.controller; 2 | 3 | import com.skypyb.sc.entity.User; 4 | import com.skypyb.sc.feign.UserFeignClient; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.cloud.client.ServiceInstance; 9 | import org.springframework.cloud.client.discovery.DiscoveryClient; 10 | import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; 11 | import org.springframework.web.bind.annotation.GetMapping; 12 | import org.springframework.web.bind.annotation.PathVariable; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.RestController; 15 | import org.springframework.web.client.RestTemplate; 16 | 17 | import java.util.List; 18 | 19 | @RestController 20 | @RequestMapping("/movie") 21 | public class MovieController { 22 | 23 | private Logger logger = LoggerFactory.getLogger(MovieController.class); 24 | 25 | @Autowired 26 | private UserFeignClient userFeignClient; 27 | 28 | 29 | @GetMapping("/user/{id}") 30 | public User getUser(@PathVariable("id") Long id) { 31 | return userFeignClient.getUser(id); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-movie/src/main/java/com/skypyb/sc/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc.entity; 2 | 3 | import java.io.Serializable; 4 | import java.math.BigDecimal; 5 | 6 | public class User implements Serializable { 7 | 8 | private Long id; 9 | private String userName; 10 | private String name; 11 | private Integer age; 12 | private BigDecimal balance; 13 | 14 | public Long getId() { 15 | return id; 16 | } 17 | 18 | public void setId(Long id) { 19 | this.id = id; 20 | } 21 | 22 | public String getUserName() { 23 | return userName; 24 | } 25 | 26 | public void setUserName(String userName) { 27 | this.userName = userName; 28 | } 29 | 30 | public String getName() { 31 | return name; 32 | } 33 | 34 | public void setName(String name) { 35 | this.name = name; 36 | } 37 | 38 | public Integer getAge() { 39 | return age; 40 | } 41 | 42 | public void setAge(Integer age) { 43 | this.age = age; 44 | } 45 | 46 | public BigDecimal getBalance() { 47 | return balance; 48 | } 49 | 50 | public void setBalance(BigDecimal balance) { 51 | this.balance = balance; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | final StringBuffer sb = new StringBuffer("User{"); 57 | sb.append("id=").append(id); 58 | sb.append(", userName='").append(userName).append('\''); 59 | sb.append(", name='").append(name).append('\''); 60 | sb.append(", age=").append(age); 61 | sb.append(", balance=").append(balance); 62 | sb.append('}'); 63 | return sb.toString(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-movie/src/main/java/com/skypyb/sc/feign/UserFeignClient.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc.feign; 2 | 3 | import com.skypyb.sc.config.FeignConfiguration; 4 | import com.skypyb.sc.entity.User; 5 | import org.springframework.cloud.openfeign.FeignClient; 6 | import org.springframework.web.bind.annotation.PathVariable; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | 10 | @FeignClient(name = "sc-demo-microservice-user", configuration = FeignConfiguration.class) 11 | public interface UserFeignClient { 12 | 13 | @RequestMapping(value = "/user/{id}", method = RequestMethod.GET) 14 | public User getUser(@PathVariable("id") Long id); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-movie/src/main/java/com/skypyb/sc/hystrix/UserFeignFallback.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc.hystrix; 2 | 3 | import com.skypyb.sc.entity.User; 4 | import com.skypyb.sc.feign.UserFeignClient; 5 | import feign.hystrix.FallbackFactory; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.stereotype.Component; 9 | 10 | 11 | /** 12 | * {@link com.skypyb.sc.feign.UserFeignClient} 类的fallbackFactory 13 | * Feign 整合 Hystrix 实现回退需要实现该接口,以获得异常检查回退原因 14 | */ 15 | @Component 16 | public class UserFeignFallback implements FallbackFactory { 17 | 18 | private static Logger logger = LoggerFactory.getLogger(UserFeignFallback.class); 19 | 20 | 21 | @Override 22 | public UserFeignClient create(Throwable cause) { 23 | 24 | logger.info("fallback; reason was: {}", cause); 25 | 26 | return new UserFeignClient() { 27 | 28 | @Override 29 | public User getUser(Long id) { 30 | User user = new User(); 31 | user.setId(-1L); 32 | user.setUserName("默认用户"); 33 | return user; 34 | } 35 | }; 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-movie/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8089 3 | 4 | spring: 5 | application: 6 | name: sc-demo-microservice-movie #这个名字会注册到 Eureka 里去 7 | datasource: 8 | driver-class-name: com.mysql.jdbc.Driver 9 | url: jdbc:mysql://192.168.8.113:3306/scdemo?serverTimezone=Asia/Shanghai 10 | username: root 11 | password: 614 12 | zipkin: 13 | base-url: http://localhost:9411 14 | sleuth: 15 | sampler: 16 | probability: 1.0 #采样百分比,这里设置的是100% 17 | logging: 18 | level: 19 | root: info 20 | org.springframework.web.servlet.DispatcherServlet: debug 21 | 22 | #mybatis实体类名 23 | mybatis: 24 | type-aliases-package: com.skypyb.sc.entity 25 | configuration: 26 | #到下划线的表字段自动映射成驼峰命名法 27 | map-underscore-to-camel-case: true 28 | mapper-locations: classpath:mybatis/mapper/*.xml 29 | 30 | 31 | #Actuato 配置 32 | management: 33 | endpoint: 34 | # 暴露shutdown功能 35 | # shutdown: 36 | # enabled: true 37 | endpoints: 38 | web: 39 | exposure: 40 | include: '*' #暴露哪些端点 41 | exclude: #隐藏哪些端点 42 | 43 | #Eureka client端配置 44 | eureka: 45 | client: 46 | service-url: 47 | defaultZone: http://user:614@localhost:8080/eureka/,http://user:614@localhost:8081/eureka/ 48 | instance: 49 | prefer-ip-address: true #将自己ip注册到Eureka Server 50 | feign: 51 | hystrix: 52 | enabled: true #为 feign 打开 hystrix 支持 53 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-user/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | compile('org.springframework.boot:spring-boot-starter-web') 3 | compile('org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.2') 4 | compile('mysql:mysql-connector-java') 5 | compile("org.springframework.cloud:spring-cloud-starter-netflix-eureka-client") 6 | compile("org.springframework.cloud:spring-cloud-starter-netflix-ribbon") 7 | compile("org.springframework.cloud:spring-cloud-starter-zipkin") 8 | } 9 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-user/out/production/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8088 3 | 4 | spring: 5 | application: 6 | name: sc-demo-microservice-user #这个名字会注册到 Eureka 里去 7 | datasource: 8 | driver-class-name: com.mysql.jdbc.Driver 9 | url: jdbc:mysql://192.168.8.113:3306/scdemo?serverTimezone=Asia/Shanghai 10 | username: root 11 | password: 614 12 | 13 | #mybatis实体类名 14 | mybatis: 15 | type-aliases-package: com.skypyb.sc.entity 16 | configuration: 17 | #到下划线的表字段自动映射成驼峰命名法 18 | map-underscore-to-camel-case: true 19 | mapper-locations: classpath:mybatis/mapper/*.xml 20 | 21 | #Actuato 配置 22 | management: 23 | endpoint: 24 | # 暴露shutdown功能 25 | # shutdown: 26 | # enabled: true 27 | endpoints: 28 | web: 29 | exposure: 30 | include: '*' #暴露哪些端点 31 | exclude: #隐藏哪些端点 32 | 33 | #Eureka client端配置 34 | eureka: 35 | client: 36 | service-url: 37 | defaultZone: http://user:614@localhost:8080/eureka/,http://user:614@localhost:8081/eureka/ 38 | instance: 39 | prefer-ip-address: true #将自己ip注册到Eureka Server -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-user/out/production/resources/schema.sql: -------------------------------------------------------------------------------- 1 | 2 | CREATE TABLE IF NOT EXISTS user 3 | ( 4 | id BIGINT(20) PRIMARY KEY NOT NULL AUTO_INCREMENT, 5 | user_name VARCHAR(40), 6 | name VARCHAR(20), 7 | age INT(3), 8 | balance DECIMAL(10,2) 9 | ); 10 | 11 | INSERT INTO user VALUES 12 | (NULL ,'account1','张三',25,100.00), 13 | (NULL ,'account2','王五',22,120.00) -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-user/src/main/java/com/skypyb/sc/UserApplication.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | @MapperScan("com.skypyb.sc.dao") 8 | @SpringBootApplication 9 | public class UserApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication application = new SpringApplication(UserApplication.class); 13 | application.run(args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-user/src/main/java/com/skypyb/sc/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc.controller; 2 | 3 | import com.skypyb.sc.entity.User; 4 | import com.skypyb.sc.service.UserService; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.PathVariable; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | @RestController 14 | @RequestMapping("/user") 15 | public class UserController { 16 | 17 | private Logger logger = LoggerFactory.getLogger(UserController.class); 18 | 19 | @Autowired 20 | private UserService userService; 21 | 22 | 23 | @GetMapping("/{id}") 24 | public User getUser(@PathVariable("id") Long id) { 25 | logger.info("access getUser method."); 26 | return userService.getUser(id); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-user/src/main/java/com/skypyb/sc/dao/UserDao.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc.dao; 2 | 3 | import com.skypyb.sc.entity.User; 4 | import org.apache.ibatis.annotations.Param; 5 | import org.apache.ibatis.annotations.Select; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface UserDao { 10 | 11 | 12 | @Select("SELECT * FROM user WHERE id=#{id}") 13 | User findById(@Param("id") Long id); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-user/src/main/java/com/skypyb/sc/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc.entity; 2 | 3 | import java.io.Serializable; 4 | import java.math.BigDecimal; 5 | 6 | public class User implements Serializable { 7 | 8 | private Long id; 9 | private String userName; 10 | private String name; 11 | private Integer age; 12 | private BigDecimal balance; 13 | 14 | public Long getId() { 15 | return id; 16 | } 17 | 18 | public void setId(Long id) { 19 | this.id = id; 20 | } 21 | 22 | public String getUserName() { 23 | return userName; 24 | } 25 | 26 | public void setUserName(String userName) { 27 | this.userName = userName; 28 | } 29 | 30 | public String getName() { 31 | return name; 32 | } 33 | 34 | public void setName(String name) { 35 | this.name = name; 36 | } 37 | 38 | public Integer getAge() { 39 | return age; 40 | } 41 | 42 | public void setAge(Integer age) { 43 | this.age = age; 44 | } 45 | 46 | public BigDecimal getBalance() { 47 | return balance; 48 | } 49 | 50 | public void setBalance(BigDecimal balance) { 51 | this.balance = balance; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | final StringBuffer sb = new StringBuffer("User{"); 57 | sb.append("id=").append(id); 58 | sb.append(", userName='").append(userName).append('\''); 59 | sb.append(", name='").append(name).append('\''); 60 | sb.append(", age=").append(age); 61 | sb.append(", balance=").append(balance); 62 | sb.append('}'); 63 | return sb.toString(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-user/src/main/java/com/skypyb/sc/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc.service; 2 | 3 | import com.skypyb.sc.dao.UserDao; 4 | import com.skypyb.sc.entity.User; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | 8 | @Service 9 | public class UserService { 10 | 11 | @Autowired 12 | private UserDao userDao; 13 | 14 | 15 | public User getUser(Long id){ 16 | return userDao.findById(id); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-user/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8088 3 | 4 | spring: 5 | application: 6 | name: sc-demo-microservice-user #这个名字会注册到 Eureka 里去 7 | datasource: 8 | driver-class-name: com.mysql.jdbc.Driver 9 | url: jdbc:mysql://192.168.8.113:3306/scdemo?serverTimezone=Asia/Shanghai 10 | username: root 11 | password: 614 12 | zipkin: 13 | base-url: http://localhost:9411 14 | sleuth: 15 | sampler: 16 | probability: 1.0 #采样百分比,这里设置的是100% 17 | 18 | 19 | logging: 20 | level: 21 | root: info 22 | org.springframework.web.servlet.DispatcherServlet: debug 23 | 24 | #mybatis实体类名 25 | mybatis: 26 | type-aliases-package: com.skypyb.sc.entity 27 | configuration: 28 | #到下划线的表字段自动映射成驼峰命名法 29 | map-underscore-to-camel-case: true 30 | mapper-locations: classpath:mybatis/mapper/*.xml 31 | 32 | #Actuato 配置 33 | management: 34 | endpoint: 35 | # 暴露shutdown功能 36 | # shutdown: 37 | # enabled: true 38 | endpoints: 39 | web: 40 | exposure: 41 | include: '*' #暴露哪些端点 42 | exclude: #隐藏哪些端点 43 | 44 | #Eureka client端配置 45 | eureka: 46 | client: 47 | service-url: 48 | defaultZone: http://user:614@localhost:8080/eureka/,http://user:614@localhost:8081/eureka/ 49 | instance: 50 | prefer-ip-address: true #将自己ip注册到Eureka Server -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-user/src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | 2 | CREATE TABLE IF NOT EXISTS user 3 | ( 4 | id BIGINT(20) PRIMARY KEY NOT NULL AUTO_INCREMENT, 5 | user_name VARCHAR(40), 6 | name VARCHAR(20), 7 | age INT(3), 8 | balance DECIMAL(10,2) 9 | ); 10 | 11 | INSERT INTO user VALUES 12 | (NULL ,'account1','张三',25,100.00), 13 | (NULL ,'account2','王五',22,120.00) -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-zuul/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | compile('org.springframework.boot:spring-boot-starter-web') 3 | compile("org.springframework.cloud:spring-cloud-starter-netflix-zuul") 4 | compile("org.springframework.cloud:spring-cloud-starter-netflix-eureka-client") 5 | // compile("org.springframework.cloud:spring-cloud-starter-netflix-ribbon") 6 | // compile("org.springframework.cloud:spring-cloud-starter-netflix-hystrix") 7 | } 8 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-zuul/src/main/java/com/skypyb/sc/ZuulApplication.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 6 | 7 | @SpringBootApplication 8 | @EnableZuulProxy//声明zuul代理 9 | public class ZuulApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(ZuulApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-zuul/src/main/java/com/skypyb/sc/config/RestConfig.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc.config; 2 | 3 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.web.client.RestTemplate; 7 | 8 | @Configuration 9 | public class RestConfig { 10 | 11 | @Bean 12 | @LoadBalanced 13 | public RestTemplate restTemplate() { 14 | RestTemplate restTemplate = new RestTemplate(); 15 | 16 | return restTemplate; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-zuul/src/main/java/com/skypyb/sc/config/ZuulFilterConfig.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc.config; 2 | 3 | import com.netflix.zuul.ZuulFilter; 4 | import com.netflix.zuul.context.RequestContext; 5 | import com.netflix.zuul.exception.ZuulException; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | 12 | import javax.servlet.http.HttpServletRequest; 13 | 14 | @Configuration 15 | public class ZuulFilterConfig { 16 | 17 | /** 18 | * 用起这个过滤器来 19 | * @return 20 | */ 21 | @Bean 22 | public PreRequestLogFilter preRequestLogFilter() { 23 | return new PreRequestLogFilter(); 24 | } 25 | 26 | /** 27 | * 请求在路由之前的过滤器 28 | */ 29 | public class PreRequestLogFilter extends ZuulFilter { 30 | 31 | private Logger logger = LoggerFactory.getLogger(PreRequestLogFilter.class); 32 | 33 | @Override 34 | public String filterType() { 35 | return FilterConstants.PRE_TYPE; 36 | } 37 | 38 | @Override 39 | public int filterOrder() { 40 | return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1; 41 | } 42 | 43 | @Override 44 | public boolean shouldFilter() { 45 | return true; 46 | } 47 | 48 | @Override 49 | public Object run() throws ZuulException { 50 | RequestContext ctx = RequestContext.getCurrentContext(); 51 | HttpServletRequest request = ctx.getRequest(); 52 | 53 | logger.info("send {} request to {}.", request.getMethod(), request.getRequestURI()); 54 | return null; 55 | } 56 | }//internal class end... 57 | } -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-zuul/src/main/java/com/skypyb/sc/controller/AggregationController.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc.controller; 2 | 3 | import com.google.common.collect.Maps; 4 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 5 | import com.skypyb.sc.entity.User; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.PathVariable; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import org.springframework.web.client.RestTemplate; 14 | 15 | import java.util.Collections; 16 | import java.util.Map; 17 | 18 | /** 19 | * 请求聚合 20 | * 客户端只需要发送一个请求到 zuul server ,由 zuul 帮忙将多个请求的数据合并 21 | */ 22 | @RestController 23 | @RequestMapping("/aggregate") 24 | public class AggregationController { 25 | 26 | private Logger logger = LoggerFactory.getLogger(AggregationController.class); 27 | 28 | @Autowired 29 | private RestTemplate restTemplate; 30 | 31 | @HystrixCommand(fallbackMethod = "fullbackUserAndMovieUser") 32 | @GetMapping("/user/user_movie/{id}") 33 | public Map userAndMovieUser(@PathVariable Long id) { 34 | User user = restTemplate.getForObject("http://sc-demo-microservice-user/user/{id}", User.class, id); 35 | User movieUser = restTemplate.getForObject("http://sc-demo-microservice-movie/movie/user/{id}", User.class, id); 36 | 37 | Map map = Maps.newHashMap(); 38 | map.put("user", user); 39 | map.put("movieUser", movieUser); 40 | return map; 41 | } 42 | 43 | //异常回退 44 | public Map fullbackUserAndMovieUser(Long id) { 45 | return Collections.EMPTY_MAP; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-zuul/src/main/java/com/skypyb/sc/controller/LocalController.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc.controller; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | /** 8 | * 本地转发示例 9 | */ 10 | @RestController 11 | @RequestMapping("/local") 12 | public class LocalController { 13 | 14 | 15 | @GetMapping("/test") 16 | public String test() { 17 | return "test"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-zuul/src/main/java/com/skypyb/sc/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.sc.entity; 2 | 3 | import java.io.Serializable; 4 | import java.math.BigDecimal; 5 | 6 | public class User implements Serializable { 7 | 8 | private Long id; 9 | private String userName; 10 | private String name; 11 | private Integer age; 12 | private BigDecimal balance; 13 | 14 | public Long getId() { 15 | return id; 16 | } 17 | 18 | public void setId(Long id) { 19 | this.id = id; 20 | } 21 | 22 | public String getUserName() { 23 | return userName; 24 | } 25 | 26 | public void setUserName(String userName) { 27 | this.userName = userName; 28 | } 29 | 30 | public String getName() { 31 | return name; 32 | } 33 | 34 | public void setName(String name) { 35 | this.name = name; 36 | } 37 | 38 | public Integer getAge() { 39 | return age; 40 | } 41 | 42 | public void setAge(Integer age) { 43 | this.age = age; 44 | } 45 | 46 | public BigDecimal getBalance() { 47 | return balance; 48 | } 49 | 50 | public void setBalance(BigDecimal balance) { 51 | this.balance = balance; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | final StringBuffer sb = new StringBuffer("User{"); 57 | sb.append("id=").append(id); 58 | sb.append(", userName='").append(userName).append('\''); 59 | sb.append(", name='").append(name).append('\''); 60 | sb.append(", age=").append(age); 61 | sb.append(", balance=").append(balance); 62 | sb.append('}'); 63 | return sb.toString(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /sc-demo-microservice/sc-demo-microservice-zuul/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8060 3 | 4 | spring: 5 | application: 6 | name: sc-demo-microservice-zuul #这个名字会注册到 Eureka 里去 7 | 8 | #Actuato 配置 9 | management: 10 | endpoint: 11 | # 暴露shutdown功能 12 | # shutdown: 13 | # enabled: true 14 | endpoints: 15 | web: 16 | exposure: 17 | include: '*' #暴露哪些端点 18 | exclude: #隐藏哪些端点 19 | 20 | #Eureka client端配置 21 | eureka: 22 | client: 23 | service-url: 24 | defaultZone: http://user:614@localhost:8080/eureka/,http://user:614@localhost:8081/eureka/ 25 | instance: 26 | prefer-ip-address: true #将自己ip注册到Eureka Server 27 | 28 | zuul: 29 | ribbon-isolation-strategy: thread #hystrix隔离策略改为线程 (默认是信号量 30 | thread-pool: 31 | use-separate-thread-pools: true #让每个路由使用它独立的线程池 32 | thread-pool-key-prefix: myprefix- #前缀 33 | routes: #路由配置 34 | local-router: 35 | url: local/test #本地转发 36 | path: forward:/local/test 37 | aggregate-router: 38 | url: aggregate/** 39 | path: forward:/aggregate/** 40 | user-router: 41 | sensitive-headers: Cookie,Set-Cookie,Authorization #指定敏感header 42 | service-id: sc-demo-microservice-user 43 | path: /zuul_user/** 44 | movie-router: 45 | service-id: sc-demo-microservice-movie 46 | path: /zuul_movie/** 47 | # ignored-services 指定微服务忽略它,不对它进行路由,使用"*" 忽略所有,只路由指定了的 48 | ignored-services: sc-demo-microservice-eureka_1,sc-demo-microservice-eureka_2 -------------------------------------------------------------------------------- /sc-demo-microservice/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'sc-demo-microservice' 2 | include 'sc-demo-microservice-user' 3 | include 'sc-demo-microservice-movie' 4 | include 'sc-demo-microservice-eureka' 5 | include 'sc-demo-microservice-zuul' 6 | 7 | -------------------------------------------------------------------------------- /shardingsphere-springboot/sharding-jdbc/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | springBootVersion = '2.2.5.RELEASE' 4 | } 5 | 6 | repositories { 7 | repositories { 8 | mavenLocal() 9 | maven { url = 'https://maven.aliyun.com/repository/jcenter' } 10 | maven { url = 'https://oss.sonatype.org/content/repositories/snapshots/' } 11 | maven { url = "https://plugins.gradle.org/m2/" } 12 | mavenCentral() 13 | } 14 | } 15 | dependencies { 16 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 17 | } 18 | } 19 | 20 | apply plugin: 'java' 21 | apply plugin: 'idea' 22 | apply plugin: 'org.springframework.boot' 23 | 24 | 25 | 26 | sourceCompatibility = 1.8 27 | targetCompatibility = 1.8 28 | 29 | allprojects { 30 | repositories { 31 | mavenLocal() 32 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 33 | mavenCentral() 34 | } 35 | 36 | tasks.withType(JavaCompile) { 37 | options.encoding = "UTF-8" 38 | } 39 | } 40 | 41 | 42 | dependencies { 43 | testCompile('org.springframework.boot:spring-boot-starter-test:2.2.5.RELEASE') 44 | compile('org.springframework.boot:spring-boot-starter-jdbc:2.2.5.RELEASE') 45 | compile ('org.apache.shardingsphere:sharding-jdbc-spring-boot-starter:4.1.0') 46 | compile('mysql:mysql-connector-java:5.1.48') 47 | compile("com.zaxxer:HikariCP:3.4.2") 48 | compile("tk.mybatis:mapper-spring-boot-starter:2.1.5") 49 | 50 | //lombok 51 | annotationProcessor('org.projectlombok:lombok:1.18.8') 52 | compileOnly('org.projectlombok:lombok:1.18.8') 53 | testAnnotationProcessor('org.projectlombok:lombok:1.18.8') 54 | testCompileOnly('org.projectlombok:lombok:1.18.8') 55 | } 56 | 57 | 58 | -------------------------------------------------------------------------------- /shardingsphere-springboot/sharding-jdbc/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'sharding-jdbc' 2 | 3 | -------------------------------------------------------------------------------- /shardingsphere-springboot/sharding-jdbc/src/main/java/com/skypyb/demo/sharding/ShardingJDBCApplication.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.demo.sharding; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import tk.mybatis.spring.annotation.MapperScan; 6 | 7 | @SpringBootApplication 8 | @MapperScan(value = {"com.skypyb.demo.sharding.**.dao"}) 9 | public class ShardingJDBCApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(ShardingJDBCApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /shardingsphere-springboot/sharding-jdbc/src/main/java/com/skypyb/demo/sharding/order/dao/OrderMapper.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.demo.sharding.order.dao; 2 | 3 | import com.skypyb.demo.sharding.order.entity.OrderDO; 4 | import tk.mybatis.mapper.common.Mapper; 5 | 6 | public interface OrderMapper extends Mapper { 7 | } -------------------------------------------------------------------------------- /shardingsphere-springboot/sharding-jdbc/src/main/java/com/skypyb/demo/sharding/order/entity/OrderDO.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.demo.sharding.order.entity; 2 | 3 | import javax.persistence.*; 4 | import lombok.Data; 5 | 6 | @Data 7 | @Table(name = "tb_order") 8 | public class OrderDO { 9 | @Id 10 | @Column(name = "order_id") 11 | private Long orderId; 12 | 13 | @Column(name = "order_no") 14 | private String orderNo; 15 | 16 | @Column(name = "item_id") 17 | private Long itemId; 18 | 19 | @Column(name = "user_id") 20 | private Long userId; 21 | 22 | @Column(name = "provider_id") 23 | private Long providerId; 24 | } -------------------------------------------------------------------------------- /shardingsphere-springboot/sharding-jdbc/src/main/java/com/skypyb/demo/sharding/order/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.demo.sharding.order.service; 2 | 3 | public interface OrderService { 4 | 5 | 6 | } 7 | -------------------------------------------------------------------------------- /shardingsphere-springboot/sharding-jdbc/src/main/java/com/skypyb/demo/sharding/order/service/impl/OrderServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.demo.sharding.order.service.impl; 2 | 3 | import org.springframework.stereotype.Service; 4 | import javax.annotation.Resource; 5 | import com.skypyb.demo.sharding.order.dao.OrderMapper; 6 | import com.skypyb.demo.sharding.order.service.OrderService; 7 | 8 | @Service 9 | public class OrderServiceImpl implements OrderService { 10 | 11 | @Resource 12 | private OrderMapper orderMapper; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /shardingsphere-springboot/sharding-jdbc/src/main/resources/init/schema.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE `skypyb-demo-test_0` CHARACTER SET UTF8MB4; 2 | CREATE DATABASE `skypyb-demo-test_1` CHARACTER SET UTF8MB4; 3 | 4 | create table `skypyb-demo-test_0`.`tb_order0` 5 | ( 6 | order_id BIGINT primary key, 7 | order_no varchar(64) not null, 8 | item_id BIGINT not null, 9 | user_id BIGINT not null, 10 | provider_id BIGINT not null 11 | ); 12 | 13 | create table `skypyb-demo-test_0`.`tb_order1` 14 | ( 15 | order_id BIGINT primary key, 16 | order_no varchar(64) not null, 17 | item_id BIGINT not null, 18 | user_id BIGINT not null, 19 | provider_id BIGINT not null 20 | ); 21 | 22 | create table `skypyb-demo-test_1`.`tb_order0` 23 | ( 24 | order_id BIGINT primary key, 25 | order_no varchar(64) not null, 26 | item_id BIGINT not null, 27 | user_id BIGINT not null, 28 | provider_id BIGINT not null 29 | ); 30 | 31 | create table `skypyb-demo-test_1`.`tb_order1` 32 | ( 33 | order_id BIGINT primary key, 34 | order_no varchar(64) not null, 35 | item_id BIGINT not null, 36 | user_id BIGINT not null, 37 | provider_id BIGINT not null 38 | ); 39 | 40 | -------------------------------------------------------------------------------- /shardingsphere-springboot/sharding-jdbc/src/main/resources/mybatis/mapper/OrderMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /shardingsphere-springboot/sharding-jdbc/src/test/java/com/skypyb/test/shardingjdbc/ShardingSphereTest.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.test.shardingjdbc; 2 | 3 | import com.skypyb.demo.sharding.ShardingJDBCApplication; 4 | import com.skypyb.demo.sharding.order.dao.OrderMapper; 5 | import com.skypyb.demo.sharding.order.entity.OrderDO; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.UUID; 13 | 14 | @SpringBootTest(classes = ShardingJDBCApplication.class) 15 | @RunWith(SpringRunner.class) 16 | public class ShardingSphereTest { 17 | 18 | @Resource 19 | private OrderMapper orderMapper; 20 | 21 | 22 | @Test 23 | public void testInsert() { 24 | OrderDO order = new OrderDO(); 25 | order.setOrderNo(UUID.randomUUID().toString()); 26 | order.setItemId(1L); 27 | order.setUserId(1L); 28 | order.setProviderId(1L); 29 | orderMapper.insertSelective(order); 30 | 31 | OrderDO order2 = new OrderDO(); 32 | order2.setOrderNo(UUID.randomUUID().toString()); 33 | order2.setItemId(2L); 34 | order2.setUserId(2L); 35 | order2.setProviderId(2L); 36 | orderMapper.insertSelective(order2); 37 | } 38 | 39 | 40 | @Test 41 | public void testSelect() { 42 | orderMapper.selectAll().forEach(System.out::println); 43 | } 44 | } -------------------------------------------------------------------------------- /spring-security-demo/README.md: -------------------------------------------------------------------------------- 1 | 使用技术为: SpringBoot+SpringSecurity+MyBatis+jjwt 2 | --- 3 | 4 | 标准的RBAC权限设计,基于动态查询数据库的权限判定 ( *以接口为粒度,即 Request URL+Request Method* ) 基于JWT的认证授权流程。 5 | 6 | 7 | 8 | 注: 此项目未写前端,所有的接口请求/API调用/测试 均使用第三方工具 (我是用的postman) 9 | 10 |
11 | 12 | #### 导入: 13 | * IDEA中选择[Project Structure]的Project子菜单, 进行如下操作导入: 14 | `绿色加号 -> Import Module -> 选择pom.xml -> OK -> ... ` 15 | * 导入pom.xml之后,再分别导入此项目下的两个子项目的pom.xml,同上 16 |
17 | 18 | #### 模块说明: 19 | - spring-security-demo: 总体架构,统一管理 20 | - spring-security-demo-dependencies: 依赖统一定义 21 | - spring-security-demo-server: 具体安全服务实现 22 | 23 | #### spring-security-demo-server 重要包目录: 24 | - com.skypyb.security.config: 核心配置,全体集成 25 | - com.skypyb.security.filter.access: 访问安全资源、决策管理 26 | - com.skypyb.security.filter.authentication: 认证控制器,分发令牌 27 | 28 |
29 |
30 | #### 注: 31 | 32 | 测试接口在 com.skypyb.test.controller 下 33 | resources 目录下的 init_sql 目录中含有 sql 脚本 34 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/SecurityServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.skypyb; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SecurityServerApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication application = new SpringApplication(SecurityServerApplication.class); 11 | application.run(args); 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/security/controller/advice/AuthenticationExceptionAdvice.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.security.controller.advice; 2 | 3 | import com.skypyb.security.exception.RequestValidationException; 4 | import com.skypyb.security.exception.SecurityAuthException; 5 | import com.skypyb.security.model.response.AuthenticationFailResponse; 6 | import com.skypyb.security.model.response.ValidationFailResponse; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.annotation.ControllerAdvice; 10 | import org.springframework.web.bind.annotation.ExceptionHandler; 11 | import org.springframework.web.bind.annotation.ResponseBody; 12 | 13 | @ControllerAdvice 14 | @ResponseBody 15 | public class AuthenticationExceptionAdvice { 16 | 17 | 18 | /** 19 | * 捕获到的异常 SecurityAuthException 不抛出报错,而是返回 AuthenticationFailResponse 20 | * 21 | * @param e SecurityAuthException 22 | * @return SecurityAuthException json 23 | */ 24 | @ExceptionHandler({SecurityAuthException.class}) 25 | public ResponseEntity handleSecurityAuthException(SecurityAuthException e) { 26 | return ResponseEntity.ok().body(AuthenticationFailResponse.asResponse(e)); 27 | } 28 | 29 | @ExceptionHandler({RequestValidationException.class}) 30 | public ResponseEntity handleRequestValidationException(RequestValidationException e) { 31 | return ResponseEntity.ok().body(ValidationFailResponse.from(e)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/security/exception/RequestValidationException.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.security.exception; 2 | 3 | public class RequestValidationException extends RuntimeException { 4 | 5 | private int code; 6 | 7 | private String message; 8 | 9 | public RequestValidationException(String message) { 10 | this.code = 400; 11 | this.message = message; 12 | } 13 | 14 | public int getCode() { 15 | return code; 16 | } 17 | 18 | public void setCode(int code) { 19 | this.code = code; 20 | } 21 | 22 | @Override 23 | public String getMessage() { 24 | return message; 25 | } 26 | 27 | public void setMessage(String message) { 28 | this.message = message; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/security/exception/SecurityAuthException.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.security.exception; 2 | 3 | 4 | import org.springframework.security.core.AuthenticationException; 5 | 6 | public class SecurityAuthException extends AuthenticationException { 7 | 8 | private int code; 9 | 10 | private String message; 11 | 12 | public SecurityAuthException(String message) { 13 | super(message); 14 | this.code = 401; 15 | this.message = message; 16 | } 17 | 18 | public int getCode() { 19 | return code; 20 | } 21 | 22 | public void setCode(int code) { 23 | this.code = code; 24 | } 25 | 26 | @Override 27 | public String getMessage() { 28 | return message; 29 | } 30 | 31 | public void setMessage(String message) { 32 | this.message = message; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/security/filter/AuthenticationFailEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.security.filter; 2 | 3 | import com.skypyb.security.model.response.AuthenticationFailResponse; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.security.core.AuthenticationException; 7 | import org.springframework.security.web.AuthenticationEntryPoint; 8 | 9 | import javax.servlet.ServletException; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.io.IOException; 13 | import java.io.PrintWriter; 14 | 15 | /** 16 | * 有人无凭据就想访问受保护的资源时,用这个处理 17 | * 返回默认的 json 字符串 18 | * 19 | * @author pyb 20 | * @date 2019/08/31 21 | */ 22 | public class AuthenticationFailEntryPoint implements AuthenticationEntryPoint { 23 | 24 | private Logger logger = LoggerFactory.getLogger("SECURITY"); 25 | 26 | @Override 27 | public void commence(HttpServletRequest httpServletRequest, 28 | HttpServletResponse httpServletResponse, 29 | AuthenticationException e) throws IOException, ServletException { 30 | 31 | PrintWriter writer = httpServletResponse.getWriter(); 32 | httpServletResponse.setContentType("application/json; charset=utf-8"); 33 | 34 | writer.print(AuthenticationFailResponse.asResponse(e).toJson()); 35 | writer.flush(); 36 | writer.close(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/security/filter/authentication/OptionsRequestFilter.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.security.filter.authentication; 2 | 3 | import org.springframework.web.filter.OncePerRequestFilter; 4 | 5 | import javax.servlet.FilterChain; 6 | import javax.servlet.ServletException; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | 11 | /** 12 | * 对于ajax的跨域请求,浏览器在发送真实请求之前,会向服务端发送OPTIONS请求,看服务端是否支持。 13 | * 对于options请求我直接返回header,不再进其它的filter浪费时间了 14 | */ 15 | public class OptionsRequestFilter extends OncePerRequestFilter { 16 | 17 | @Override 18 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 19 | throws ServletException, IOException { 20 | if (request.getMethod().equals("OPTIONS")) { 21 | response.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,HEAD"); 22 | response.setHeader("Access-Control-Allow-Headers", response.getHeader("Access-Control-Request-Headers")); 23 | return; 24 | } 25 | filterChain.doFilter(request, response); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/security/model/request/AuthenticationRequest.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.security.model.request; 2 | 3 | 4 | import javax.validation.constraints.NotBlank; 5 | import javax.validation.constraints.Size; 6 | 7 | /** 8 | * 登陆接口接收的请求 9 | * 10 | * @author pyb 11 | */ 12 | public class AuthenticationRequest { 13 | 14 | @NotBlank(message = "Username can not be blank!") 15 | private String userName; 16 | 17 | @NotBlank(message = "Password can not be blank!") 18 | @Size(min = 6, max = 36, message = "Password length is incorrect!") 19 | private String password; 20 | 21 | //Verification code ... 22 | 23 | public AuthenticationRequest() { 24 | } 25 | 26 | public AuthenticationRequest(String userName, String password) { 27 | this.userName = userName; 28 | this.password = password; 29 | } 30 | 31 | public String getUserName() { 32 | return userName; 33 | } 34 | 35 | public void setUserName(String userName) { 36 | this.userName = userName; 37 | } 38 | 39 | public String getPassword() { 40 | return password; 41 | } 42 | 43 | public void setPassword(String password) { 44 | this.password = password; 45 | } 46 | 47 | @Override 48 | public String toString() { 49 | final StringBuilder sb = new StringBuilder("AuthenticationRequest{"); 50 | sb.append("userName='").append(userName).append('\''); 51 | sb.append(", password='").append(password).append('\''); 52 | sb.append('}'); 53 | return sb.toString(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/security/model/response/AuthenticationFailResponse.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.security.model.response; 2 | 3 | 4 | import com.skypyb.security.exception.SecurityAuthException; 5 | import org.springframework.security.authentication.BadCredentialsException; 6 | import org.springframework.security.authentication.DisabledException; 7 | import org.springframework.security.authentication.InternalAuthenticationServiceException; 8 | import org.springframework.security.core.AuthenticationException; 9 | 10 | /** 11 | * 认证失败时返回给前台的响应 12 | */ 13 | public class AuthenticationFailResponse extends BasicResponse { 14 | 15 | 16 | public AuthenticationFailResponse(int code, String message) { 17 | super(code, message); 18 | } 19 | 20 | public static AuthenticationFailResponse asResponse(AuthenticationException e) { 21 | AuthenticationFailResponse unauthorized; 22 | 23 | if (e instanceof InternalAuthenticationServiceException) { 24 | e = (AuthenticationException) e.getCause(); 25 | } 26 | 27 | if (e instanceof SecurityAuthException) { 28 | SecurityAuthException ex = (SecurityAuthException) e; 29 | unauthorized = new AuthenticationFailResponse(ex.getCode(), ex.getMessage()); 30 | 31 | } else if (e instanceof DisabledException) { 32 | unauthorized = new AuthenticationFailResponse(401, "User is disabled!"); 33 | 34 | } else if (e instanceof BadCredentialsException) { 35 | unauthorized = new AuthenticationFailResponse(401, "Wrong credentials!"); 36 | 37 | } else { 38 | unauthorized = new AuthenticationFailResponse(401, "Unauthorized"); 39 | } 40 | 41 | return unauthorized; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/security/model/response/AuthenticationResponse.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.security.model.response; 2 | 3 | /** 4 | * 认证成功响应 5 | */ 6 | public class AuthenticationResponse extends BasicResponse { 7 | 8 | public AuthenticationResponse(String message) { 9 | super(200, message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/security/model/response/BasicResponse.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.security.model.response; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonIgnore; 5 | import org.codehaus.jackson.map.ObjectMapper; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * 基本的响应 11 | */ 12 | public class BasicResponse { 13 | 14 | @JsonIgnore 15 | private static final ObjectMapper MAPPER = new ObjectMapper(); 16 | 17 | private int code; 18 | private String message; 19 | 20 | 21 | public BasicResponse() { 22 | } 23 | 24 | public BasicResponse(int code, String message) { 25 | this.code = code; 26 | this.message = message; 27 | } 28 | 29 | public int getCode() { 30 | return code; 31 | } 32 | 33 | public String getMessage() { 34 | return message; 35 | } 36 | 37 | public String toJson() throws IOException { 38 | return MAPPER.writeValueAsString(this); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/security/model/response/ValidationFailResponse.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.security.model.response; 2 | 3 | 4 | import com.skypyb.security.exception.RequestValidationException; 5 | 6 | 7 | /** 8 | * 数据效验失败时返回的响应 9 | */ 10 | public class ValidationFailResponse extends BasicResponse { 11 | 12 | public ValidationFailResponse(int code, String message) { 13 | super(code, message); 14 | } 15 | 16 | public static ValidationFailResponse from(RequestValidationException e) { 17 | return new ValidationFailResponse(e.getCode(), e.getMessage()); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/test/controller/MethodProtectedRestController.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.test.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.security.access.prepost.PreAuthorize; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RequestMethod; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | /** 10 | * 测试获取资源 11 | */ 12 | @RestController 13 | public class MethodProtectedRestController { 14 | 15 | /** 16 | * This is an example of some different kinds of granular restriction for endpoints. You can use the built-in SPEL expressions 17 | * in @PreAuthorize such as 'hasRole()' to determine if a user has access. Remember that the hasRole expression assumes a 18 | * 'ROLE_' prefix on all role names. So 'ADMIN' here is actually stored as 'ROLE_ADMIN' in database! 19 | **/ 20 | @RequestMapping(value = "/protectedadmin", method = RequestMethod.GET) 21 | public ResponseEntity getProtectedAdmin() { 22 | return ResponseEntity.ok("Greetings from admin protected method!"); 23 | } 24 | 25 | @RequestMapping(value = "/protecteduser", method = RequestMethod.GET) 26 | public ResponseEntity getProtectedUser() { 27 | return ResponseEntity.ok("Greetings from user protected method!"); 28 | } 29 | 30 | 31 | @RequestMapping(value = "/test/one", method = RequestMethod.GET) 32 | public ResponseEntity testOne() { 33 | return ResponseEntity.ok("/test/one"); 34 | } 35 | 36 | @RequestMapping(value = "/test/two/two", method = RequestMethod.GET) 37 | public ResponseEntity testTwo() { 38 | return ResponseEntity.ok("/test/two/two"); 39 | } 40 | 41 | @RequestMapping(value = "/ignore/testget", method = RequestMethod.GET) 42 | public ResponseEntity testIgnoreGet() { 43 | return ResponseEntity.ok("/ignore/testget"); 44 | } 45 | 46 | @RequestMapping(value = "/ignore/testpost", method = RequestMethod.POST) 47 | public ResponseEntity testIgnorePost() { 48 | return ResponseEntity.ok("/ignore/testpost"); 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/user/config/UserConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.user.config; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | @Configuration 7 | @MapperScan("com.skypyb.user.dao") 8 | public class UserConfiguration { 9 | } 10 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/user/dao/UserDao.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.user.dao; 2 | 3 | import com.skypyb.user.model.dto.MinimumPermissionDTO; 4 | import com.skypyb.user.model.dto.MinimumRoleDTO; 5 | import com.skypyb.user.model.dto.MinimumUserDTO; 6 | import com.skypyb.user.model.dto.RolePermissionPO; 7 | import com.skypyb.user.model.po.UserPO; 8 | import org.apache.ibatis.annotations.Param; 9 | 10 | import java.util.List; 11 | import java.util.Optional; 12 | 13 | public interface UserDao { 14 | 15 | Optional findUserByUserName(@Param("userName") String userName); 16 | 17 | Optional findUserByUserId(@Param("userId") Long userId); 18 | 19 | Optional findMinimumUser(@Param("userName") String userName); 20 | 21 | List findUserMinimumPermission(@Param("userId") Long userId); 22 | 23 | List findAllMinimumPermission(); 24 | 25 | List findAllMinimumRoleDTO(); 26 | 27 | List findAllRolePermissionRelation(); 28 | 29 | List findUserMinimumRole(Long userId); 30 | } 31 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/user/model/dto/MinimumPermissionDTO.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.user.model.dto; 2 | 3 | import java.io.Serializable; 4 | import java.util.Objects; 5 | 6 | //基本的权限信息 7 | public class MinimumPermissionDTO implements Serializable { 8 | 9 | private Long permissionId; 10 | private String name; 11 | private String enName; 12 | private String url; 13 | private String method; 14 | 15 | public Long getPermissionId() { 16 | return permissionId; 17 | } 18 | 19 | public void setPermissionId(Long permissionId) { 20 | this.permissionId = permissionId; 21 | } 22 | 23 | public String getName() { 24 | return name; 25 | } 26 | 27 | public void setName(String name) { 28 | this.name = name; 29 | } 30 | 31 | public String getEnName() { 32 | return enName; 33 | } 34 | 35 | public void setEnName(String enName) { 36 | this.enName = enName; 37 | } 38 | 39 | public String getUrl() { 40 | return url; 41 | } 42 | 43 | public void setUrl(String url) { 44 | this.url = url; 45 | } 46 | 47 | public String getMethod() { 48 | return method; 49 | } 50 | 51 | public void setMethod(String method) { 52 | this.method = method; 53 | } 54 | 55 | @Override 56 | public boolean equals(Object o) { 57 | if (this == o) return true; 58 | if (o == null || getClass() != o.getClass()) return false; 59 | MinimumPermissionDTO that = (MinimumPermissionDTO) o; 60 | return Objects.equals(permissionId, that.permissionId); 61 | } 62 | 63 | @Override 64 | public int hashCode() { 65 | 66 | return Objects.hash(permissionId); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/user/model/dto/MinimumRoleDTO.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.user.model.dto; 2 | 3 | import java.util.Objects; 4 | 5 | //最基本的角色信息 6 | public class MinimumRoleDTO { 7 | 8 | private Long roleId; 9 | 10 | private Long parentId; 11 | 12 | private String name; 13 | 14 | private String enName; 15 | 16 | public Long getRoleId() { 17 | return roleId; 18 | } 19 | 20 | public void setRoleId(Long roleId) { 21 | this.roleId = roleId; 22 | } 23 | 24 | public Long getParentId() { 25 | return parentId; 26 | } 27 | 28 | public void setParentId(Long parentId) { 29 | this.parentId = parentId; 30 | } 31 | 32 | public String getName() { 33 | return name; 34 | } 35 | 36 | public void setName(String name) { 37 | this.name = name; 38 | } 39 | 40 | public String getEnName() { 41 | return enName; 42 | } 43 | 44 | public void setEnName(String enName) { 45 | this.enName = enName; 46 | } 47 | 48 | @Override 49 | public boolean equals(Object o) { 50 | if (this == o) return true; 51 | if (o == null || getClass() != o.getClass()) return false; 52 | MinimumRoleDTO that = (MinimumRoleDTO) o; 53 | return Objects.equals(roleId, that.roleId); 54 | } 55 | 56 | @Override 57 | public int hashCode() { 58 | 59 | return Objects.hash(roleId); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/user/model/dto/MinimumUserDTO.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.user.model.dto; 2 | 3 | import java.io.Serializable; 4 | import java.util.Objects; 5 | 6 | //最低限度的用户基本信息 7 | public class MinimumUserDTO implements Serializable { 8 | 9 | private Long userId; 10 | private String userName; 11 | private String password; 12 | 13 | public Long getUserId() { 14 | return userId; 15 | } 16 | 17 | public void setUserId(Long userId) { 18 | this.userId = userId; 19 | } 20 | 21 | public String getUserName() { 22 | return userName; 23 | } 24 | 25 | public void setUserName(String userName) { 26 | this.userName = userName; 27 | } 28 | 29 | public String getPassword() { 30 | return password; 31 | } 32 | 33 | public void setPassword(String password) { 34 | this.password = password; 35 | } 36 | 37 | @Override 38 | public boolean equals(Object o) { 39 | if (this == o) return true; 40 | if (o == null || getClass() != o.getClass()) return false; 41 | MinimumUserDTO that = (MinimumUserDTO) o; 42 | return Objects.equals(userId, that.userId); 43 | } 44 | 45 | @Override 46 | public int hashCode() { 47 | 48 | return Objects.hash(userId); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/user/model/dto/RolePermissionPO.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.user.model.dto; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 角色权限表的实体 7 | * 角色和权限的映射 8 | */ 9 | public class RolePermissionPO implements Serializable{ 10 | private Long id; 11 | private Long roleId; 12 | private Long permissionId; 13 | 14 | public Long getId() { 15 | return id; 16 | } 17 | 18 | public void setId(Long id) { 19 | this.id = id; 20 | } 21 | 22 | public Long getRoleId() { 23 | return roleId; 24 | } 25 | 26 | public void setRoleId(Long roleId) { 27 | this.roleId = roleId; 28 | } 29 | 30 | public Long getPermissionId() { 31 | return permissionId; 32 | } 33 | 34 | public void setPermissionId(Long permissionId) { 35 | this.permissionId = permissionId; 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/java/com/skypyb/user/model/po/UserPO.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.user.model.po; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | 6 | /** 7 | * tb_user 表映射的实体对象 8 | */ 9 | public class UserPO implements Serializable { 10 | 11 | private Long userId; 12 | private String userName; 13 | private String password; 14 | private Date createTime; 15 | private Date lastLoginTime; 16 | private Integer state; 17 | 18 | 19 | public Long getUserId() { 20 | return userId; 21 | } 22 | 23 | public void setUserId(Long userId) { 24 | this.userId = userId; 25 | } 26 | 27 | public String getUserName() { 28 | return userName; 29 | } 30 | 31 | public void setUserName(String userName) { 32 | this.userName = userName; 33 | } 34 | 35 | public String getPassword() { 36 | return password; 37 | } 38 | 39 | public void setPassword(String password) { 40 | this.password = password; 41 | } 42 | 43 | public Date getCreateTime() { 44 | return createTime; 45 | } 46 | 47 | public void setCreateTime(Date createTime) { 48 | this.createTime = createTime; 49 | } 50 | 51 | public Date getLastLoginTime() { 52 | return lastLoginTime; 53 | } 54 | 55 | public void setLastLoginTime(Date lastLoginTime) { 56 | this.lastLoginTime = lastLoginTime; 57 | } 58 | 59 | public Integer getState() { 60 | return state; 61 | } 62 | 63 | public void setState(Integer state) { 64 | this.state = state; 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | final StringBuilder sb = new StringBuilder("UserPO{"); 70 | sb.append("userId=").append(userId); 71 | sb.append(", userName='").append(userName).append('\''); 72 | sb.append(", password='").append(password).append('\''); 73 | sb.append(", createTime=").append(createTime); 74 | sb.append(", lastLoginTime=").append(lastLoginTime); 75 | sb.append(", state=").append(state); 76 | sb.append('}'); 77 | return sb.toString(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /spring-security-demo/spring-security-demo-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: security-demo 4 | jackson: 5 | serialization: 6 | indent_output: true 7 | datasource: 8 | type: com.zaxxer.hikari.HikariDataSource 9 | driver-class-name: com.mysql.cj.jdbc.Driver 10 | url: jdbc:mysql://192.168.1.14:3306/securitydemo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai 11 | username: root 12 | password: 614 13 | hikari: 14 | minimum-idle: 5 15 | idle-timeout: 600000 16 | maximum-pool-size: 10 17 | auto-commit: true 18 | pool-name: MyHikariCP 19 | max-lifetime: 1800000 20 | connection-timeout: 30000 21 | connection-test-query: SELECT 1 22 | 23 | mybatis: 24 | mapper-locations: classpath:mybatis/mapper/*.xml 25 | 26 | #设置服务器端口号 27 | server: 28 | port: 8080 29 | 30 | 31 | # SecurityProperties 配置 32 | demo: 33 | security: 34 | header: Authorization #请求头部属性名 35 | signing_key: pyb068@gmail.com #JWT 签名秘钥 36 | token_expiration: 108000000 #token失效时间 30*60*60*1000 37 | route: 38 | auth_path: /tk/auth 39 | refresh_path: /tk/refresh 40 | ignore: 41 | get: 42 | - /test/** 43 | - /ignore/testget 44 | post: 45 | - /ignore/testpost -------------------------------------------------------------------------------- /ssm-backstage/README.MD: -------------------------------------------------------------------------------- 1 | 一个使用Maven管理的、Spring+SpringMVC+MyBatis+Thymeleaf+Layui 完成的简单后台 2 | --- 3 | 4 | * IDEA中选择[Project Structure]的Project子菜单, 进行如下操作导入: 5 | `绿色加号 -> Import Module -> 选择 pom.xml -> OK -> ... ` 6 | 7 | #### 说明: 8 | SSM 均使用注解式开发。 9 | 完成了基础的数据 CRUD。 10 | 完成了基础的登陆。 11 | SpringMVC 设置了基础的拦截器。 12 | MyBatis 使用注解完成了基础的一对一、一对多语句。 13 | 基本上 HTML 均为 Thymeleaf layout 式的页面,前端使用 Layui 作为模板。 14 | 15 | `resources/sql/ 文件夹下有本项目 Entity 的建表语句` 16 | 17 | #### 本工程作用: 18 | 记录用, 方便二次使用,即拿即用。 19 | 好久没用 Maven+SSM 这套东西了,这 XML 配置真心怪麻烦的。 20 | 拦截器、Mybatis映射、Thymeleaf 这些玩意配置都得用 XML , 搞得头大。 21 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/java/com/skypyb/config/SecurityInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.config; 2 | 3 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 4 | 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | import javax.servlet.http.HttpSession; 8 | import java.io.IOException; 9 | 10 | public class SecurityInterceptor extends HandlerInterceptorAdapter { 11 | 12 | 13 | @Override 14 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { 15 | HttpSession session = request.getSession(); 16 | 17 | 18 | //判断是否已有用户登录的session 19 | if (session.getAttribute("loginUser") != null) { 20 | return true; 21 | } 22 | //没登录就跳转到登录页 23 | response.sendRedirect("/login"); 24 | return false; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/java/com/skypyb/controller/FeatureController.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.controller; 2 | 3 | import com.skypyb.entity.Feature; 4 | import com.skypyb.service.FeatureService; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.web.bind.annotation.*; 9 | 10 | import java.util.List; 11 | 12 | @RestController 13 | @RequestMapping("/feature") 14 | public class FeatureController { 15 | 16 | private Logger logger = LoggerFactory.getLogger(FeatureController.class); 17 | 18 | 19 | @Autowired 20 | private FeatureService featureService; 21 | 22 | @GetMapping("/authorityId/{authorityId}") 23 | public List getFeature(@PathVariable("authorityId") Long authorityId) { 24 | return featureService.getByAuthorityId(authorityId); 25 | } 26 | 27 | @DeleteMapping("/{id}") 28 | public String deleteFeature(@PathVariable("id") Long id) { 29 | 30 | logger.info("Access AuthorityController.deleteFeature() id={}", id); 31 | featureService.delete(id); 32 | return "success"; 33 | } 34 | 35 | @PutMapping("/{name}") 36 | public String addFeature(@PathVariable("name") String name) { 37 | 38 | logger.info("Access AuthorityController.addFeature() name={}", name); 39 | 40 | 41 | if (name != null && !name.trim().equals("")) 42 | featureService.add(name); 43 | 44 | return "success"; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/java/com/skypyb/controller/ViewController.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.controller; 2 | 3 | import com.skypyb.service.AuthorityService; 4 | import com.skypyb.service.FeatureService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | 10 | import java.util.Map; 11 | 12 | @Controller 13 | public class ViewController { 14 | 15 | @Autowired 16 | private AuthorityService authorityService; 17 | @Autowired 18 | private FeatureService featureService; 19 | 20 | @RequestMapping(value = "/", method = RequestMethod.GET) 21 | public String root() { 22 | return "index"; 23 | } 24 | 25 | @RequestMapping(value = "/index", method = RequestMethod.GET) 26 | public String index() { 27 | return "index"; 28 | } 29 | 30 | @RequestMapping(value = "/layout", method = RequestMethod.GET) 31 | public String layout() { 32 | return "layout"; 33 | } 34 | 35 | @RequestMapping(value = "/userManager", method = RequestMethod.GET) 36 | public String userManager() { 37 | return "userManager"; 38 | } 39 | 40 | @RequestMapping(value = "/login", method = RequestMethod.GET) 41 | public String login() { 42 | return "login"; 43 | } 44 | 45 | @RequestMapping(value = "/authorityManager", method = RequestMethod.GET) 46 | public String authorityManager(Map map) { 47 | 48 | map.put("authorityList", authorityService.findAll()); 49 | map.put("featureList", featureService.findAll()); 50 | 51 | return "authorityManager"; 52 | } 53 | 54 | } 55 | 56 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/java/com/skypyb/dao/FeatureDao.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.dao; 2 | 3 | import com.skypyb.entity.Feature; 4 | import org.apache.ibatis.annotations.Delete; 5 | import org.apache.ibatis.annotations.Insert; 6 | import org.apache.ibatis.annotations.Param; 7 | import org.apache.ibatis.annotations.Select; 8 | 9 | import java.util.List; 10 | 11 | public interface FeatureDao { 12 | 13 | @Select("SELECT f.feature_id,f.feature_name FROM feature_to_authority fta,feature f " + 14 | " WHERE fta.feature_id = f.feature_id AND fta.authority_id = #{authorityId}") 15 | List getByAuthorityId(@Param("authorityId") Long authorityId); 16 | 17 | 18 | @Select("SELECT * FROM feature") 19 | List findAll(); 20 | 21 | @Delete("DELETE FROM feature WHERE feature_id = #{featureId}") 22 | void delete(@Param("featureId") Long featureId); 23 | 24 | @Insert(("INSERT INTO feature VALUES(NULL,#{featureName})")) 25 | void add(@Param("featureName") String featureName); 26 | } 27 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/java/com/skypyb/dao/UserDao.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.dao; 2 | 3 | import com.skypyb.entity.User; 4 | import org.apache.ibatis.annotations.*; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | @Repository 10 | public interface UserDao { 11 | 12 | @Select("SELECT * FROM user WHERE user_id = #{id}") 13 | @Results(@Result(property = "authority", column = "authority", 14 | one = @One(select = "com.skypyb.dao.AuthorityDao.getByName"))) 15 | User getUserById(@Param("id") Long id); 16 | 17 | @Select("SELECT * FROM user WHERE user_name = #{userName}") 18 | @Results(@Result(property = "authority", column = "authority", 19 | one = @One(select = "com.skypyb.dao.AuthorityDao.getByName"))) 20 | User getUserByName(@Param("userName") String userName); 21 | 22 | @Select("SELECT * FROM user") 23 | @Results(@Result(property = "authority", column = "authority", 24 | one = @One(select = "com.skypyb.dao.AuthorityDao.getByName"))) 25 | List findAll(); 26 | 27 | @Select("SELECT * FROM user Limit #{page},#{limit}") 28 | @Results(@Result(property = "authority", column = "authority", 29 | one = @One(select = "com.skypyb.dao.AuthorityDao.getByName"))) 30 | List findAllByPage(@Param("page") int page, @Param("limit") int limit); 31 | 32 | @Delete("DELETE FROM user WHERE user_id = #{userId}") 33 | void delete(@Param("userId") Long userId); 34 | 35 | @Select("SELECT COUNT(user_id) FROM user") 36 | int count(); 37 | 38 | @Insert("INSERT INTO user VALUES(NULL,#{userName},#{password},#{idCard},#{phone},#{sex},#{authority.authorityName})") 39 | int addUser(User user); 40 | 41 | @Update("UPDATE user SET user_name=#{userName},password=#{password}," + 42 | "id_card=#{idCard},phone=#{phone},sex=#{sex},authority=#{authority.authorityName} WHERE user_id=#{userId}") 43 | int editUser(User user); 44 | } 45 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/java/com/skypyb/entity/Authority.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.entity; 2 | 3 | 4 | import java.io.Serializable; 5 | 6 | /** 7 | * 权限表 8 | */ 9 | public class Authority implements Serializable { 10 | private Long authorityId; 11 | private String authorityName; 12 | 13 | 14 | public Long getAuthorityId() { 15 | return authorityId; 16 | } 17 | 18 | public void setAuthorityId(Long authorityId) { 19 | this.authorityId = authorityId; 20 | } 21 | 22 | public String getAuthorityName() { 23 | return authorityName; 24 | } 25 | 26 | public void setAuthorityName(String authorityName) { 27 | this.authorityName = authorityName; 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | final StringBuffer sb = new StringBuffer("Authority{"); 33 | sb.append("authorityId=").append(authorityId); 34 | sb.append(", authorityName='").append(authorityName).append('\''); 35 | sb.append('}'); 36 | return sb.toString(); 37 | } 38 | } -------------------------------------------------------------------------------- /ssm-backstage/src/main/java/com/skypyb/entity/AuthorityToFeature.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.entity; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 权限功能一对多模型 7 | */ 8 | public class AuthorityToFeature extends Authority { 9 | 10 | 11 | private List features; 12 | 13 | public List getFeatures() { 14 | return features; 15 | } 16 | 17 | public void setFeatures(List features) { 18 | this.features = features; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/java/com/skypyb/entity/Feature.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 功能表 7 | */ 8 | public class Feature implements Serializable { 9 | 10 | private Long featureId; 11 | private String featureName; 12 | 13 | public Long getFeatureId() { 14 | return featureId; 15 | } 16 | 17 | public void setFeatureId(Long featureId) { 18 | this.featureId = featureId; 19 | } 20 | 21 | public String getFeatureName() { 22 | return featureName; 23 | } 24 | 25 | public void setFeatureName(String featureName) { 26 | this.featureName = featureName; 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | final StringBuffer sb = new StringBuffer("Feature{"); 32 | sb.append("featureId=").append(featureId); 33 | sb.append(", featureName='").append(featureName).append('\''); 34 | sb.append('}'); 35 | return sb.toString(); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/java/com/skypyb/model/LaydataResponse.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.model; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * layui 的表格功能需要的参数必须是这个格式 7 | */ 8 | public class LaydataResponse { 9 | private int code; 10 | private String msg; 11 | private int count; 12 | private List data; 13 | 14 | public int getCode() { 15 | return code; 16 | } 17 | 18 | public void setCode(int code) { 19 | this.code = code; 20 | } 21 | 22 | public String getMsg() { 23 | return msg; 24 | } 25 | 26 | public void setMsg(String msg) { 27 | this.msg = msg; 28 | } 29 | 30 | public int getCount() { 31 | return count; 32 | } 33 | 34 | public void setCount(int count) { 35 | this.count = count; 36 | } 37 | 38 | public List getData() { 39 | return data; 40 | } 41 | 42 | public void setData(List data) { 43 | this.data = data; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/java/com/skypyb/service/AuthorityService.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.service; 2 | 3 | import com.skypyb.dao.AuthorityDao; 4 | import com.skypyb.entity.Authority; 5 | import com.skypyb.entity.AuthorityToFeature; 6 | import org.apache.ibatis.annotations.*; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | import java.util.List; 11 | 12 | @Service 13 | public class AuthorityService { 14 | 15 | @Autowired 16 | private AuthorityDao authorityDao; 17 | 18 | public Authority getById(Long id) { 19 | return authorityDao.getById(id); 20 | } 21 | 22 | public Authority getByName(String name) { 23 | return authorityDao.getByName(name); 24 | } 25 | 26 | public List findAll() { 27 | return authorityDao.findAll(); 28 | } 29 | 30 | 31 | public AuthorityToFeature findAtfById(Long authorityId) { 32 | return authorityDao.findAtfById(authorityId); 33 | } 34 | 35 | public List findAtfAll() { 36 | return authorityDao.findAtfAll(); 37 | } 38 | 39 | 40 | public void delete(Long authorityId) { 41 | authorityDao.delete(authorityId); 42 | deleteAtfByAid(authorityId); 43 | } 44 | public void add(String authorityName) { 45 | authorityDao.add(authorityName); 46 | } 47 | 48 | 49 | 50 | 51 | public void deleteAtfByAid(Long authorityId) { 52 | authorityDao.deleteAtfByAid(authorityId); 53 | } 54 | 55 | 56 | public void insertAtf(Long authorityId, Long featureId) { 57 | authorityDao.insertAtf(authorityId, featureId); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/java/com/skypyb/service/FeatureService.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.service; 2 | 3 | import com.skypyb.dao.AuthorityDao; 4 | import com.skypyb.dao.FeatureDao; 5 | import com.skypyb.entity.Feature; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | import java.util.List; 10 | 11 | @Service 12 | public class FeatureService { 13 | 14 | @Autowired 15 | private FeatureDao featureDao; 16 | @Autowired 17 | private AuthorityDao authorityDao; 18 | 19 | public List getByAuthorityId(Long authorityId) { 20 | return featureDao.getByAuthorityId(authorityId); 21 | } 22 | 23 | 24 | public List findAll() { 25 | return featureDao.findAll(); 26 | } 27 | 28 | public void delete(Long featureId) { 29 | featureDao.delete(featureId); 30 | authorityDao.deleteAtfByFid(featureId); 31 | } 32 | 33 | public void add(String featureName) { 34 | featureDao.add(featureName); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/java/com/skypyb/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.skypyb.service; 2 | 3 | import com.skypyb.dao.UserDao; 4 | import com.skypyb.entity.User; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.util.List; 9 | 10 | @Service 11 | public class UserService { 12 | @Autowired 13 | private UserDao userDao; 14 | 15 | 16 | public User getUser(Long id) { 17 | return userDao.getUserById(id); 18 | } 19 | 20 | public User getUser(String userName) { 21 | return userDao.getUserByName(userName); 22 | } 23 | 24 | public List findAll() { 25 | return userDao.findAll(); 26 | } 27 | 28 | public List findAllByPage(int page, int limit) { 29 | return userDao.findAllByPage(page, limit); 30 | } 31 | 32 | public int count() { 33 | return userDao.count(); 34 | } 35 | 36 | public void delete(Long userId) { 37 | userDao.delete(userId); 38 | } 39 | 40 | public int addUser(User user) { 41 | return userDao.addUser(user); 42 | } 43 | 44 | public int editUser(User user) { 45 | User temp = null; 46 | 47 | if (user.getUserId() != null) { 48 | temp = userDao.getUserById(user.getUserId()); 49 | } else if (user.getUserName() != null) { 50 | temp = userDao.getUserByName(user.getUserName()); 51 | } else { 52 | throw new IllegalArgumentException("No such user."); 53 | } 54 | 55 | user.setUserId(temp.getUserId()); 56 | user.setUserName(temp.getUserName()); 57 | user.setPassword(temp.getPassword()); 58 | 59 | return userDao.editUser(user); 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootCategory=ERROR,stdout 2 | log4j.logger.org.springframework=ERROR 3 | 4 | 5 | log4j.appender.console=org.apache.log4j.ConsoleAppender 6 | log4j.appender.console.encoding=UTF-8 7 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 8 | log4j.appender.console.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%l] - [%p] %m%n 9 | 10 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 11 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 12 | log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n 13 | 14 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/resources/mybatis.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/resources/mysql.properties: -------------------------------------------------------------------------------- 1 | 2 | driver=com.mysql.cj.jdbc.Driver 3 | url=jdbc:mysql://localhost:3306/ztbdemo?serverTimezone=Asia/Shanghai 4 | username=root 5 | password=614 6 | 7 | 8 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/resources/sql/schema.sql: -------------------------------------------------------------------------------- 1 | 2 | CREATE DATABASE ztbdemo; 3 | USE ztbdemo; 4 | --- 5 | CREATE TABLE user 6 | ( 7 | user_id INT(10) PRIMARY KEY NOT NULL AUTO_INCREMENT, 8 | user_name VARCHAR(20) NOT NULL, 9 | password VARCHAR(20) NOT NULL, 10 | id_card VARCHAR(20), 11 | phone VARCHAR(20), 12 | sex VARCHAR(2), 13 | authority VARCHAR(20) 14 | ); 15 | CREATE UNIQUE INDEX user_user_name_uindex ON user (user_name); 16 | 17 | INSERT INTO user VALUES (null,'admin','123456','43310019880505666x','18823231454','男','管理员'); 18 | 19 | --- 20 | 21 | CREATE TABLE authority 22 | ( 23 | authority_id INT(10) PRIMARY KEY NOT NULL AUTO_INCREMENT, 24 | authority_name VARCHAR(20) NOT NULL 25 | ); 26 | CREATE UNIQUE INDEX authority_authority_name_uindex ON authority (authority_name); 27 | 28 | INSERT INTO authority VALUES (null,'管理员'),(null,'普通用户'); 29 | 30 | --- 31 | 32 | CREATE TABLE feature 33 | ( 34 | feature_id INT(10) PRIMARY KEY NOT NULL AUTO_INCREMENT, 35 | feature_name VARCHAR(50) NOT NULL 36 | ); 37 | CREATE UNIQUE INDEX feature_feature_name_uindex ON feature (feature_name); 38 | 39 | --- 40 | 41 | CREATE TABLE feature_to_authority 42 | ( 43 | fta_id INT(10) PRIMARY KEY NOT NULL AUTO_INCREMENT, 44 | authority_id INT(10) NOT NULL, 45 | feature_id INT(10) NOT NULL 46 | ); 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/WEB-INF/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | index 7 | 8 | 9 |
10 | 11 | 12 | 13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/css/authorityManager.css: -------------------------------------------------------------------------------- 1 | .wrap { 2 | display: flex; 3 | flex-direction: row; 4 | flex-wrap: wrap; 5 | } 6 | 7 | .wrap > div { 8 | padding: 9px; 9 | margin-right: 5px; 10 | min-height: 200px; 11 | width: 300px; 12 | } -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/js/layout.js: -------------------------------------------------------------------------------- 1 | var $, layer; 2 | 3 | //主动加载jquery模块 4 | layui.use(['jquery', 'layer'], function () { 5 | $ = layui.$ //重点处 6 | , layer = layui.layer; 7 | }); -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/css/modules/code.css: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #e2e2e2;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:32px;line-height:32px;border-bottom:1px solid #e2e2e2}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 5px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none} -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/css/modules/layer/default/icon-ext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/css/modules/layer/default/icon-ext.png -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/css/modules/layer/default/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/css/modules/layer/default/icon.png -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/css/modules/layer/default/loading-0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/css/modules/layer/default/loading-0.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/css/modules/layer/default/loading-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/css/modules/layer/default/loading-1.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/css/modules/layer/default/loading-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/css/modules/layer/default/loading-2.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/font/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/font/iconfont.eot -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/font/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/font/iconfont.ttf -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/font/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/font/iconfont.woff -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/0.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/1.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/10.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/10.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/11.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/11.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/12.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/12.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/13.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/13.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/14.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/14.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/15.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/15.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/16.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/17.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/17.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/18.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/18.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/19.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/19.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/2.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/20.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/20.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/21.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/21.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/22.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/22.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/23.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/23.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/24.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/24.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/25.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/25.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/26.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/26.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/27.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/27.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/28.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/28.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/29.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/29.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/3.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/30.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/30.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/31.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/31.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/32.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/32.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/33.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/33.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/34.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/34.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/35.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/35.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/36.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/36.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/37.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/37.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/38.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/38.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/39.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/39.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/4.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/40.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/40.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/41.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/41.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/42.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/42.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/43.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/43.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/44.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/44.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/45.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/45.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/46.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/46.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/47.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/47.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/48.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/48.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/49.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/49.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/5.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/50.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/50.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/51.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/51.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/52.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/52.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/53.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/53.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/54.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/54.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/55.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/55.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/56.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/56.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/57.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/57.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/58.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/58.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/59.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/59.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/6.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/60.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/60.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/61.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/61.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/62.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/62.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/63.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/63.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/64.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/64.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/65.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/65.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/66.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/66.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/67.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/67.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/68.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/68.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/69.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/69.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/7.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/7.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/70.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/70.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/71.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/71.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/8.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/8.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/images/face/9.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sorakylin/code_demo/f4d77aaf5ffeb32b3b1462e379a4c349741c24b5/ssm-backstage/src/main/webapp/layui/images/face/9.gif -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/lay/modules/code.js: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | ;layui.define("jquery",function(e){"use strict";var a=layui.$,l="http://www.layui.com/doc/modules/code.html";e("code",function(e){var t=[];e=e||{},e.elem=a(e.elem||".layui-code"),e.about=!("about"in e)||e.about,e.elem.each(function(){t.push(this)}),layui.each(t.reverse(),function(t,i){var c=a(i),o=c.html();(c.attr("lay-encode")||e.encode)&&(o=o.replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""")),c.html('
  1. '+o.replace(/[\r\t\n]+/g,"
  2. ")+"
"),c.find(">.layui-code-h3")[0]||c.prepend('

'+(c.attr("lay-title")||e.title||"code")+(e.about?'layui.code':"")+"

");var d=c.find(">.layui-code-ol");c.addClass("layui-box layui-code-view"),(c.attr("lay-skin")||e.skin)&&c.addClass("layui-code-"+(c.attr("lay-skin")||e.skin)),(d.find("li").length/100|0)>0&&d.css("margin-left",(d.find("li").length/100|0)+"px"),(c.attr("lay-height")||e.height)&&d.css("max-height",c.attr("lay-height")||e.height)})})}).addcss("modules/code.css","skincodecss"); -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/lay/modules/flow.js: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | ;layui.define("jquery",function(e){"use strict";var l=layui.$,o=function(e){},t='';o.prototype.load=function(e){var o,i,n,r,a=this,c=0;e=e||{};var f=l(e.elem);if(f[0]){var m=l(e.scrollElem||document),u=e.mb||50,s=!("isAuto"in e)||e.isAuto,v=e.end||"没有更多了",y=e.scrollElem&&e.scrollElem!==document,d="加载更多",h=l('");f.find(".layui-flow-more")[0]||f.append(h);var p=function(e,t){e=l(e),h.before(e),t=0==t||null,t?h.html(v):h.find("a").html(d),i=t,o=null,n&&n()},g=function(){o=!0,h.find("a").html(t),"function"==typeof e.done&&e.done(++c,p)};if(g(),h.find("a").on("click",function(){l(this);i||o||g()}),e.isLazyimg)var n=a.lazyimg({elem:e.elem+" img",scrollElem:e.scrollElem});return s?(m.on("scroll",function(){var e=l(this),t=e.scrollTop();r&&clearTimeout(r),i||(r=setTimeout(function(){var i=y?e.height():l(window).height(),n=y?e.prop("scrollHeight"):document.documentElement.scrollHeight;n-t-i<=u&&(o||g())},100))}),a):a}},o.prototype.lazyimg=function(e){var o,t=this,i=0;e=e||{};var n=l(e.scrollElem||document),r=e.elem||"img",a=e.scrollElem&&e.scrollElem!==document,c=function(e,l){var o=n.scrollTop(),r=o+l,c=a?function(){return e.offset().top-n.offset().top+o}():e.offset().top;if(c>=o&&c<=r&&!e.attr("src")){var m=e.attr("lay-src");layui.img(m,function(){var l=t.lazyimg.elem.eq(i);e.attr("src",m).removeAttr("lay-src"),l[0]&&f(l),i++})}},f=function(e,o){var f=a?(o||n).height():l(window).height(),m=n.scrollTop(),u=m+f;if(t.lazyimg.elem=l(r),e)c(e,f);else for(var s=0;su)break}};if(f(),!o){var m;n.on("scroll",function(){var e=l(this);m&&clearTimeout(m),m=setTimeout(function(){f(null,e)},50)}),o=!0}return f},e("flow",new o)}); -------------------------------------------------------------------------------- /ssm-backstage/src/main/webapp/layui/lay/modules/laytpl.js: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | ;layui.define(function(e){"use strict";var r={open:"{{",close:"}}"},c={exp:function(e){return new RegExp(e,"g")},query:function(e,c,t){var o=["#([\\s\\S])+?","([^{#}])*?"][e||0];return n((c||"")+r.open+o+r.close+(t||""))},escape:function(e){return String(e||"").replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""")},error:function(e,r){var c="Laytpl Error:";return"object"==typeof console&&console.error(c+e+"\n"+(r||"")),c+e}},n=c.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=n("^"+r.open+"#",""),l=n(r.close+"$","");e=e.replace(/\s+|\r|\t|\n/g," ").replace(n(r.open+"#"),r.open+"# ").replace(n(r.close+"}"),"} "+r.close).replace(/\\/g,"\\\\").replace(n(r.open+"!(.+?)!"+r.close),function(e){return e=e.replace(n("^"+r.open+"!"),"").replace(n("!"+r.close),"").replace(n(r.open+"|"+r.close),function(e){return e.replace(/(.)/g,"\\$1")})}).replace(/(?="|')/g,"\\").replace(c.query(),function(e){return e=e.replace(a,"").replace(l,""),'";'+e.replace(/\\/g,"")+';view+="'}).replace(c.query(1),function(e){var c='"+(';return e.replace(/\s/g,"")===r.open+r.close?"":(e=e.replace(n(r.open+"|"+r.close),""),/^=/.test(e)&&(e=e.replace(/^=/,""),c='"+_escape_('),c+e.replace(/\\/g,"")+')+"')}),e='"use strict";var view = "'+e+'";return view;';try{return o.cache=e=new Function("d, _escape_",e),e(t,c.escape)}catch(u){return delete o.cache,c.error(u,p)}},t.pt.render=function(e,r){var n,t=this;return e?(n=t.cache?t.cache(e,c.escape):t.parse(t.tpl,e),r?void r(n):n):c.error("no data")};var o=function(e){return"string"!=typeof e?c.error("Template not found"):new t(e)};o.config=function(e){e=e||{};for(var c in e)r[c]=e[c]},o.v="1.2.0",e("laytpl",o)}); --------------------------------------------------------------------------------