├── pom.xml ├── rademe.txt ├── spring-boo-practice-custom-datasource ├── pom.xml ├── readme.txt └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── foo │ │ │ ├── CustomDataSourceApplicationStarter.java │ │ │ ├── conf │ │ │ └── CustomConfiguration.java │ │ │ ├── model │ │ │ └── Customer.java │ │ │ └── service │ │ │ ├── CustomerService.java │ │ │ └── impl │ │ │ └── CustomerServiceImpl.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── foo │ └── services │ └── test │ └── TestCustomerService.java ├── spring-boot-practice-atomikos ├── pom.xml ├── readme.txt └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── foo │ │ │ ├── AtomikosApplicationStarter.java │ │ │ ├── conf │ │ │ ├── CustomConfiguration.java │ │ │ └── DruidDataSourceProperties.java │ │ │ ├── model │ │ │ ├── AccountBOC.java │ │ │ └── AccountCCB.java │ │ │ └── service │ │ │ ├── AccountBocService.java │ │ │ ├── AccountCcbService.java │ │ │ └── impl │ │ │ ├── AccountBocServiceImpl.java │ │ │ └── AccountCcbServiceImpl.java │ ├── resources │ │ └── application.yml │ └── webapp │ │ ├── WEB-INF │ │ └── web.xml │ │ └── index.jsp │ └── test │ └── java │ └── com │ └── foo │ └── AccountServiceTest.java ├── spring-boot-practice-data-jpa ├── _order.sql ├── order_item.sql ├── pom.xml ├── readme.txt └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── foo │ │ │ ├── DataJpaApplicationStarter.java │ │ │ ├── configura │ │ │ └── Conf.java │ │ │ ├── dao │ │ │ ├── OrderDao.java │ │ │ └── impl │ │ │ │ └── OrderDaoImpl.java │ │ │ ├── model │ │ │ ├── Order.java │ │ │ └── OrderItem.java │ │ │ ├── services │ │ │ ├── OrderService.java │ │ │ └── impl │ │ │ │ └── OrderServiceImpl.java │ │ │ └── utils │ │ │ └── IdUtils.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── foo │ └── services │ └── test │ └── TestOrderService.java ├── spring-boot-practice-filter ├── pom.xml └── src │ └── main │ └── java │ └── foo │ ├── SimpleApplicationStarter.java │ ├── controller │ └── IndexController.java │ └── filter │ ├── anno │ └── MyAnnotationFilter.java │ └── bean │ ├── FilterConfiguration.java │ └── MyBeanFilter.java ├── spring-boot-practice-html ├── pom.xml ├── readme.txt └── src │ └── main │ ├── java │ └── com │ │ └── foo │ │ ├── HtmlApplicationStarter.java │ │ └── controller │ │ ├── IndexController.java │ │ └── WelcomeController.java │ └── resources │ ├── application.properties │ └── static │ ├── dist │ └── home.html │ └── index.html ├── spring-boot-practice-jsp ├── pom.xml ├── readme.txt └── src │ └── main │ ├── java │ └── com │ │ └── foo │ │ ├── JspApplicationStarter.java │ │ └── controller │ │ └── WelcomeController.java │ ├── resources │ └── application.properties │ └── webapp │ └── WEB-INF │ └── jsp │ └── welcome.jsp ├── spring-boot-practice-multiple-datasource ├── pom.xml ├── readme.txt └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── foo │ │ │ ├── MultipleDataSourceApplicationStarter.java │ │ │ ├── conf │ │ │ ├── CustomConfiguration.java │ │ │ └── DruidDataSourceProperties.java │ │ │ ├── model │ │ │ ├── AccountBOC.java │ │ │ └── AccountCCB.java │ │ │ └── service │ │ │ ├── AccountBocService.java │ │ │ ├── AccountCcbService.java │ │ │ └── impl │ │ │ ├── AccountBocServiceImpl.java │ │ │ └── AccountCcbServiceImpl.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── foo │ └── AccountServiceTest.java ├── spring-boot-practice-mybatis ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── foo │ │ ├── MybatisApplicationRunner.java │ │ ├── config │ │ └── MyBatisConfig.java │ │ ├── dao │ │ └── CityDao.java │ │ ├── mapper │ │ ├── CityMapper.java │ │ └── CountryMapper.java │ │ └── model │ │ ├── City.java │ │ └── Country.java │ └── resources │ ├── application.yml │ └── config │ └── mapper │ └── CountryMapper.xml ├── spring-boot-practice-redis ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── foo │ │ │ ├── RedisApplicationStarter.java │ │ │ └── service │ │ │ ├── RedisCacheService.java │ │ │ └── RedisService.java │ └── resources │ │ ├── application.properties │ │ └── logback.xml │ ├── readme.dm │ └── test │ └── java │ └── com │ └── foo │ └── test │ └── TestRedis.java ├── spring-boot-practice-simple ├── pom.xml ├── readme.txt └── src │ └── main │ ├── java │ └── com │ │ └── foo │ │ ├── SimpleApplicationStarter.java │ │ └── controller │ │ └── HelloWorldController.java │ └── webapp │ ├── WEB-INF │ └── web.xml │ └── index.jsp ├── spring-boot-practice-websocket ├── pom.xml └── src │ └── main │ ├── java │ ├── com │ │ └── foo │ │ │ └── websocket │ │ │ ├── WebSocketTestApplication.java │ │ │ ├── api │ │ │ └── SendMessageCtrl.java │ │ │ ├── config │ │ │ └── WebSocketConfig.java │ │ │ └── handler │ │ │ └── MyHandler.java │ └── samples │ │ └── websocket │ │ └── tomcat │ │ ├── SampleTomcatWebSocketApplication.java │ │ ├── client │ │ ├── GreetingService.java │ │ ├── SimpleClientWebSocketHandler.java │ │ └── SimpleGreetingService.java │ │ ├── echo │ │ ├── DefaultEchoService.java │ │ ├── EchoService.java │ │ └── EchoWebSocketHandler.java │ │ ├── reverse │ │ └── ReverseWebSocketEndpoint.java │ │ └── snake │ │ ├── Direction.java │ │ ├── Location.java │ │ ├── Snake.java │ │ ├── SnakeTimer.java │ │ ├── SnakeUtils.java │ │ └── SnakeWebSocketHandler.java │ └── resources │ └── static │ ├── echo.html │ ├── index.html │ ├── reverse.html │ ├── snake.html │ └── websocket.html ├── spring-boot-pratice-activemq ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── foo │ │ ├── SampleActiveMQApplication.java │ │ ├── consumer │ │ └── Consumer.java │ │ ├── producer │ │ └── Producer.java │ │ └── queue │ │ └── QueueConfiguration.java │ └── resources │ └── application.properties └── spring-boot-reference.pdf /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.foo 8 | spring-boot-practice 9 | pom 10 | 1.0.0-SNAPSHOT 11 | 12 | spring-boot-practice-simple 13 | spring-boot-practice-jsp 14 | spring-boot-practice-html 15 | spring-boot-practice-data-jpa 16 | spring-boo-practice-custom-datasource 17 | spring-boot-practice-multiple-datasource 18 | spring-boot-practice-atomikos 19 | spring-boot-practice-redis 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-parent 25 | 2.1.1.RELEASE 26 | 27 | 28 | 29 | 30 | com.google.guava 31 | guava 32 | 19.0 33 | 34 | 35 | org.projectlombok 36 | lombok 37 | 1.16.10 38 | 39 | 40 | 41 | 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-maven-plugin 46 | 47 | 48 | org.apache.maven.plugins 49 | maven-compiler-plugin 50 | 51 | 1.7 52 | 1.7 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /rademe.txt: -------------------------------------------------------------------------------- 1 | ps: 2 | 1、所有的代码基于springboot 1.4.2.RELEASE 3 | 2、部分代码引用于springboot官方例子 4 | 3、为了方便parent、guava、lombok包在父工程引入,如需将子工程单独以jar包(war包在Tomcat容器)运行,将父工程的依赖单独引入,再打包运行。 5 | -------------------------------------------------------------------------------- /spring-boo-practice-custom-datasource/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | spring-boot-practice 5 | com.foo 6 | 1.0.0-SNAPSHOT 7 | 8 | 4.0.0 9 | spring-boo-practice-custom-datasource 10 | jar 11 | spring-boo-practice-custom-datasource 12 | http://maven.apache.org 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-web 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-test 21 | test 22 | 23 | 24 | mysql 25 | mysql-connector-java 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-data-jpa 30 | 31 | 32 | com.alibaba 33 | druid 34 | 1.0.9 35 | 36 | 37 | 38 | spring-boo-practice-custom-datasource 39 | 40 | 41 | -------------------------------------------------------------------------------- /spring-boo-practice-custom-datasource/readme.txt: -------------------------------------------------------------------------------- 1 | 1、@Bean("dataSource")注入一个datasource 2 | 2、 -------------------------------------------------------------------------------- /spring-boo-practice-custom-datasource/src/main/java/com/foo/CustomDataSourceApplicationStarter.java: -------------------------------------------------------------------------------- 1 | package com.foo; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | 8 | /** 9 | * @author JasonLin 10 | * @version V1.0 11 | * @date 2017/12/01 12 | */ 13 | @SpringBootApplication 14 | public class CustomDataSourceApplicationStarter { 15 | 16 | private static final Log LOG = LogFactory.getLog(CustomDataSourceApplicationStarter.class); 17 | 18 | public static void main(String[] args) throws Exception { 19 | SpringApplication.run(CustomDataSourceApplicationStarter.class, args); 20 | LOG.info("spring-boot-practice-data-custom-datasource is started."); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /spring-boo-practice-custom-datasource/src/main/java/com/foo/conf/CustomConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.foo.conf; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.core.env.PropertySource; 8 | import org.springframework.core.env.StandardEnvironment; 9 | 10 | import javax.sql.DataSource; 11 | import java.util.Map; 12 | import java.util.Properties; 13 | 14 | /** 15 | * @author JasonLin 16 | * @version V1.0 17 | * @date 2017/12/1 18 | */ 19 | @Configuration 20 | public class CustomConfiguration { 21 | 22 | @Value("${spring.datasource.url}") 23 | String url; 24 | 25 | @Value("${spring.datasource.username}") 26 | String username; 27 | 28 | @Value("${spring.datasource.password}") 29 | String password; 30 | 31 | @Value("${spring.datasource.driver-class-name}") 32 | String driverClassName; 33 | 34 | @Bean("dataSource") 35 | public DataSource druidDataSource(StandardEnvironment env) { 36 | Properties properties = new Properties(); 37 | DruidDataSource druidDataSource = new DruidDataSource(); 38 | PropertySource appProperties = env.getPropertySources().get("applicationConfig: [classpath:/application.yml]"); 39 | Map source = (Map) appProperties.getSource(); 40 | properties.putAll(source); 41 | druidDataSource.configFromPropety(properties); 42 | druidDataSource.setUrl(url); 43 | druidDataSource.setPassword(username); 44 | druidDataSource.setUsername(password); 45 | druidDataSource.setDriverClassName(driverClassName); 46 | return druidDataSource; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /spring-boo-practice-custom-datasource/src/main/java/com/foo/model/Customer.java: -------------------------------------------------------------------------------- 1 | package com.foo.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.GeneratedValue; 9 | import javax.persistence.GenerationType; 10 | import javax.persistence.Id; 11 | import javax.persistence.Table; 12 | import java.io.Serializable; 13 | 14 | /** 15 | * @author JasonLin 16 | * @version V1.0 17 | * @date 2017/12/1 18 | */ 19 | @Setter 20 | @Getter 21 | @Entity 22 | @Table(name = "customer") 23 | public class Customer implements Serializable { 24 | private static final long serialVersionUID = -7896459795783095454L; 25 | 26 | @Id 27 | @GeneratedValue(strategy = GenerationType.IDENTITY) 28 | private Long id; 29 | 30 | @Column(name = "nike_name") 31 | private String nikeName; 32 | 33 | @Column 34 | private String email; 35 | 36 | @Column 37 | private String mobile; 38 | 39 | @Column 40 | private String phone; 41 | 42 | @Column 43 | private String address; 44 | } 45 | -------------------------------------------------------------------------------- /spring-boo-practice-custom-datasource/src/main/java/com/foo/service/CustomerService.java: -------------------------------------------------------------------------------- 1 | package com.foo.service; 2 | 3 | import com.foo.model.Customer; 4 | 5 | /** 6 | * @author JasonLin 7 | * @version V1.0 8 | * @date 2017/12/1 9 | */ 10 | public interface CustomerService { 11 | 12 | void create(Customer customer); 13 | } 14 | -------------------------------------------------------------------------------- /spring-boo-practice-custom-datasource/src/main/java/com/foo/service/impl/CustomerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.foo.service.impl; 2 | 3 | import com.foo.model.Customer; 4 | import com.foo.service.CustomerService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.jdbc.core.JdbcTemplate; 7 | import org.springframework.stereotype.Service; 8 | import org.springframework.transaction.annotation.Transactional; 9 | 10 | 11 | /** 12 | * @author JasonLin 13 | * @version V1.0 14 | * @date 2017/12/1 15 | */ 16 | @Service("customerService") 17 | @Transactional(rollbackFor = Exception.class) 18 | public class CustomerServiceImpl implements CustomerService { 19 | 20 | private static final String INSERT_CUSTOMER = "INSERT INTO customer (nike_name,email,mobile,phone,address) VALUES (?,?,?,?,?);"; 21 | 22 | @Autowired 23 | private JdbcTemplate jdbcTemplate; 24 | 25 | @Override 26 | public void create(Customer customer) { 27 | jdbcTemplate.update(INSERT_CUSTOMER, customer.getNikeName(), 28 | customer.getEmail(), customer.getMobile(), 29 | customer.getPhone(), customer.getAddress()); 30 | if("rollbackUser".equals(customer.getNikeName())){ 31 | throw new RuntimeException("test rollback on runtimeException."); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /spring-boo-practice-custom-datasource/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | url: jdbc:mysql://localhost:3306/db1?useSSL=false&requireSSL=false 4 | driver-class-name: com.mysql.jdbc.Driver 5 | username: root 6 | password: root 7 | 8 | druid: 9 | filters: stat 10 | maxActive: 20 11 | initialSize: 1 12 | maxWait: 30000 13 | minIdle: 10 14 | maxIdle: 15 15 | timeBetweenEvictionRunsMillis: 60000 16 | minEvictableIdleTimeMillis: 300000 17 | validationQuery: SELECT 1 18 | testWhileIdle: true 19 | testOnBorrow: false 20 | testOnReturn: false 21 | maxOpenPreparedStatements: 20 22 | removeAbandoned: true 23 | removeAbandonedTimeout: 1800 24 | logAbandoned: true 25 | -------------------------------------------------------------------------------- /spring-boo-practice-custom-datasource/src/test/java/com/foo/services/test/TestCustomerService.java: -------------------------------------------------------------------------------- 1 | package com.foo.services.test; 2 | 3 | import com.foo.model.Customer; 4 | import com.foo.service.CustomerService; 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.jdbc.core.JdbcTemplate; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | import org.springframework.util.Assert; 12 | 13 | /** 14 | * @author JasonLin 15 | * @version V1.0 16 | * @date 2017/12/1 17 | */ 18 | @RunWith(SpringRunner.class) 19 | @SpringBootTest 20 | public class TestCustomerService { 21 | 22 | @Autowired 23 | private CustomerService customerService; 24 | 25 | @Autowired 26 | private JdbcTemplate jdbcTemplate; 27 | 28 | @Test 29 | public void testCreateCustomer(){ 30 | Customer customer = new Customer(); 31 | customer.setAddress("四川成都"); 32 | customer.setEmail("xxx@qq.com"); 33 | customer.setMobile("15708111111"); 34 | customer.setNikeName("JasonLin"); 35 | customer.setPhone("028-125468"); 36 | customerService.create(customer); 37 | } 38 | 39 | @Test 40 | public void testRollback(){ 41 | Customer customer = new Customer(); 42 | customer.setAddress("四川成都"); 43 | customer.setEmail("xxx@qq.com"); 44 | customer.setMobile("15708111111"); 45 | customer.setNikeName("rollbackUser"); 46 | customer.setPhone("028-125468"); 47 | customerService.create(customer); 48 | } 49 | 50 | @Test 51 | public void testSearchCustomer() { 52 | String sql = "SELECT id FROM customer WHERE nike_name = 'JasonLin'"; 53 | Assert.notEmpty(jdbcTemplate.queryForList(sql, Long.class)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /spring-boot-practice-atomikos/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | spring-boot-practice 5 | com.foo 6 | 1.0.0-SNAPSHOT 7 | 8 | 4.0.0 9 | spring-boot-practice-atomikos 10 | war 11 | spring-boot-practice-atomikos Maven Webapp 12 | http://maven.apache.org 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-web 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-test 21 | test 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-data-jpa 26 | 27 | 28 | mysql 29 | mysql-connector-java 30 | 31 | 32 | com.alibaba 33 | druid 34 | 1.1.6 35 | 36 | 37 | mysql 38 | mysql-connector-java 39 | 40 | 41 | 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter-jta-atomikos 46 | 47 | 48 | 49 | spring-boot-practice-atomikos 50 | 51 | 52 | -------------------------------------------------------------------------------- /spring-boot-practice-atomikos/readme.txt: -------------------------------------------------------------------------------- 1 | 1、引入atomikos相关依赖 2 | -------------------------------------------------------------------------------- /spring-boot-practice-atomikos/src/main/java/com/foo/AtomikosApplicationStarter.java: -------------------------------------------------------------------------------- 1 | package com.foo; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | 8 | /** 9 | * @author JasonLin 10 | * @version V1.0 11 | * @date 2017/12/01 12 | */ 13 | @SpringBootApplication 14 | public class AtomikosApplicationStarter { 15 | 16 | private static final Log LOG = LogFactory.getLog(AtomikosApplicationStarter.class); 17 | 18 | public static void main(String[] args) throws Exception { 19 | SpringApplication.run(AtomikosApplicationStarter.class, args); 20 | LOG.info("spring-boot-practice-data-custom-datasource is started."); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /spring-boot-practice-atomikos/src/main/java/com/foo/conf/CustomConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.foo.conf; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import com.alibaba.druid.pool.xa.DruidXADataSource; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.beans.factory.annotation.Qualifier; 7 | import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.context.annotation.Primary; 13 | import org.springframework.jdbc.core.JdbcTemplate; 14 | 15 | import javax.sql.DataSource; 16 | import java.sql.SQLException; 17 | 18 | /** 19 | * @author JasonLin 20 | * @version V1.0 21 | * @date 2017/12/1 22 | */ 23 | @Configuration 24 | public class CustomConfiguration { 25 | 26 | @Autowired 27 | private DruidDataSourceProperties druidDataSourceProperties; 28 | 29 | @Bean 30 | @Primary 31 | @ConfigurationProperties(prefix = "boc.datasource") 32 | public DataSourceProperties bocDataSourceProperties() { 33 | return new DataSourceProperties(); 34 | } 35 | 36 | @Bean 37 | @ConfigurationProperties(prefix = "ccb.datasource") 38 | public DataSourceProperties ccbDataSourceProperties() { 39 | return new DataSourceProperties(); 40 | } 41 | 42 | @Bean 43 | @Primary 44 | @ConfigurationProperties(prefix = "boc.datasource") 45 | public DataSource bocDataSource(@Qualifier("bocDataSourceProperties") DataSourceProperties dataSourceProperties) throws SQLException { 46 | DruidXADataSource druidXADataSource = new DruidXADataSource(); 47 | InitDruidDataSource(druidXADataSource, dataSourceProperties); 48 | 49 | AtomikosDataSourceBean atomikosDataSource = new AtomikosDataSourceBean(); 50 | atomikosDataSource.setUniqueResourceName("bocDataSource"); 51 | atomikosDataSource.setXaDataSource(druidXADataSource); 52 | atomikosDataSource.setTestQuery("SELECT 1"); 53 | return atomikosDataSource; 54 | } 55 | 56 | @Bean 57 | @ConfigurationProperties(prefix = "ccb.datasource") 58 | public DataSource ccbDataSource(@Qualifier("ccbDataSourceProperties") DataSourceProperties dataSourceProperties) throws SQLException { 59 | DruidXADataSource druidXADataSource = new DruidXADataSource(); 60 | InitDruidDataSource(druidXADataSource, dataSourceProperties); 61 | 62 | //也可以使用mysql默认的xa数据源 63 | //MysqlXADataSource mysqlXADataSource = new MysqlXADataSource(); 64 | //mysqlXADataSource.setUrl(dataSourceProperties.getUrl()); 65 | //mysqlXADataSource.setUser(dataSourceProperties.getUsername()); 66 | //mysqlXADataSource.setPassword(dataSourceProperties.getPassword()); 67 | 68 | AtomikosDataSourceBean atomikosDataSource = new AtomikosDataSourceBean(); 69 | atomikosDataSource.setUniqueResourceName("ccbDataSource"); 70 | atomikosDataSource.setXaDataSource(druidXADataSource); 71 | atomikosDataSource.setTestQuery("SELECT 1"); 72 | return atomikosDataSource; 73 | } 74 | 75 | @Bean 76 | public JdbcTemplate bocJdbcTemplate(@Qualifier("bocDataSource") DataSource bocDataSource) { 77 | return new JdbcTemplate(bocDataSource); 78 | } 79 | 80 | @Bean 81 | public JdbcTemplate ccbJdbcTemplate(@Qualifier("ccbDataSource") DataSource ccbDataSource) { 82 | return new JdbcTemplate(ccbDataSource); 83 | } 84 | 85 | private void InitDruidDataSource(DruidDataSource druidDataSource, DataSourceProperties properties) throws SQLException { 86 | druidDataSource.setUrl(properties.getUrl()); 87 | druidDataSource.setUsername(properties.getUsername()); 88 | druidDataSource.setPassword(properties.getPassword()); 89 | druidDataSource.setDriverClassName(properties.getDriverClassName()); 90 | //属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: 91 | //监控统计用的filter:stat 92 | //日志用的filter:log4j 93 | //防御sql注入的filter:wall 94 | druidDataSource.setFilters(druidDataSourceProperties.getFilters()); 95 | //最大连接池数量 96 | druidDataSource.setMaxActive(druidDataSourceProperties.getMaxActive()); 97 | // 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时 98 | druidDataSource.setInitialSize(druidDataSourceProperties.getInitialSize()); 99 | //获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。 100 | druidDataSource.setMaxWait(druidDataSourceProperties.getMaxWait()); 101 | //最小连接池数量 102 | druidDataSource.setMinIdle(druidDataSourceProperties.getMinIdle()); 103 | //有两个含义: 104 | //1) Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。 105 | //2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明 106 | druidDataSource.setTimeBetweenEvictionRunsMillis(druidDataSourceProperties.getTimeBetweenEvictionRunsMillis()); 107 | //连接保持空闲而不被驱逐的最小时间 108 | druidDataSource.setMinEvictableIdleTimeMillis(druidDataSourceProperties.getMinEvictableIdleTimeMillis()); 109 | druidDataSource.setValidationQuery(druidDataSourceProperties.getValidationQuery()); 110 | //建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis, 111 | //(空闲时测试)执行validationQuery检测连接是否有效。 112 | druidDataSource.setTestWhileIdle(druidDataSourceProperties.isTestWhileIdle()); 113 | //申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 114 | druidDataSource.setTestOnBorrow(druidDataSourceProperties.isTestOnBorrow()); 115 | //归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 116 | druidDataSource.setTestOnReturn(druidDataSourceProperties.isTestOnReturn()); 117 | //移除泄露的链接 118 | druidDataSource.setRemoveAbandoned(druidDataSourceProperties.isRemoveAbandoned()); 119 | //泄露连接的定义时间(要超过最大事务的处理时间) 120 | druidDataSource.setRemoveAbandonedTimeout(druidDataSourceProperties.getRemoveAbandonedTimeout()); 121 | //移除泄露连接发生是是否记录日志 122 | druidDataSource.setLogAbandoned(druidDataSourceProperties.isLogAbandoned()); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /spring-boot-practice-atomikos/src/main/java/com/foo/conf/DruidDataSourceProperties.java: -------------------------------------------------------------------------------- 1 | package com.foo.conf; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | /** 9 | * @author JasonLin 10 | * @version V1.0 11 | * @date 2017/12/4 12 | */ 13 | @Getter 14 | @Setter 15 | @Configuration 16 | @ConfigurationProperties(prefix = "druid") 17 | public class DruidDataSourceProperties { 18 | private String filters; 19 | private int maxActive; 20 | private int initialSize; 21 | private int maxWait; 22 | private int minIdle; 23 | private long timeBetweenEvictionRunsMillis; 24 | private long minEvictableIdleTimeMillis; 25 | private String validationQuery; 26 | private boolean testWhileIdle; 27 | private boolean testOnBorrow; 28 | private boolean testOnReturn; 29 | private int maxOpenPreparedStatements; 30 | private boolean removeAbandoned; 31 | private int removeAbandonedTimeout; 32 | private boolean logAbandoned; 33 | } 34 | -------------------------------------------------------------------------------- /spring-boot-practice-atomikos/src/main/java/com/foo/model/AccountBOC.java: -------------------------------------------------------------------------------- 1 | package com.foo.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.GeneratedValue; 9 | import javax.persistence.GenerationType; 10 | import javax.persistence.Id; 11 | import javax.persistence.Table; 12 | import java.io.Serializable; 13 | import java.math.BigDecimal; 14 | 15 | /** 16 | * @author JasonLin 17 | * @version V1.0 18 | * @date 2017/12/4 19 | */ 20 | @Setter 21 | @Getter 22 | @Entity 23 | @Table(name = "account_boc") 24 | public class AccountBOC implements Serializable { 25 | 26 | private static final long serialVersionUID = 1820150874495571704L; 27 | 28 | @Id 29 | @GeneratedValue(strategy = GenerationType.IDENTITY) 30 | private Long id; 31 | 32 | @Column 33 | private Long customer; 34 | 35 | @Column 36 | private BigDecimal balance; 37 | } 38 | -------------------------------------------------------------------------------- /spring-boot-practice-atomikos/src/main/java/com/foo/model/AccountCCB.java: -------------------------------------------------------------------------------- 1 | package com.foo.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.GeneratedValue; 9 | import javax.persistence.GenerationType; 10 | import javax.persistence.Id; 11 | import javax.persistence.Table; 12 | import java.io.Serializable; 13 | import java.math.BigDecimal; 14 | 15 | /** 16 | * @author JasonLin 17 | * @version V1.0 18 | * @date 2017/12/4 19 | */ 20 | @Setter 21 | @Getter 22 | @Entity 23 | @Table(name = "account_ccb") 24 | public class AccountCCB implements Serializable{ 25 | 26 | private static final long serialVersionUID = 1476688047241463855L; 27 | 28 | @Id 29 | @GeneratedValue(strategy = GenerationType.IDENTITY) 30 | private Long id; 31 | 32 | @Column 33 | private Long customer; 34 | 35 | @Column 36 | private BigDecimal balance; 37 | } 38 | -------------------------------------------------------------------------------- /spring-boot-practice-atomikos/src/main/java/com/foo/service/AccountBocService.java: -------------------------------------------------------------------------------- 1 | package com.foo.service; 2 | 3 | import java.math.BigDecimal; 4 | 5 | /** 6 | * @author JasonLin 7 | * @version V1.0 8 | * @date 2017/12/4 9 | */ 10 | public interface AccountBocService { 11 | 12 | void updateBalance(Long customer, BigDecimal amount); 13 | } 14 | -------------------------------------------------------------------------------- /spring-boot-practice-atomikos/src/main/java/com/foo/service/AccountCcbService.java: -------------------------------------------------------------------------------- 1 | package com.foo.service; 2 | 3 | import java.math.BigDecimal; 4 | 5 | /** 6 | * @author JasonLin 7 | * @version V1.0 8 | * @date 2017/12/4 9 | */ 10 | public interface AccountCcbService { 11 | 12 | void transferAccountToBoc(Long customer, BigDecimal amount); 13 | 14 | void updateBalance(Long customer, BigDecimal amount); 15 | } 16 | -------------------------------------------------------------------------------- /spring-boot-practice-atomikos/src/main/java/com/foo/service/impl/AccountBocServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.foo.service.impl; 2 | 3 | import com.foo.service.AccountBocService; 4 | import org.apache.commons.logging.Log; 5 | import org.apache.commons.logging.LogFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.jdbc.core.JdbcTemplate; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | import java.math.BigDecimal; 12 | 13 | /** 14 | * @author JasonLin 15 | * @version V1.0 16 | * @date 2017/12/4 17 | */ 18 | @Service("accountBocService") 19 | @Transactional(rollbackFor = Exception.class) 20 | public class AccountBocServiceImpl implements AccountBocService { 21 | 22 | private static final String UPDATE_BALANCE = "UPDATE account_boc SET balance = balance+? WHERE customer = ?;"; 23 | 24 | private final Log log = LogFactory.getLog(getClass()); 25 | 26 | @Autowired 27 | private JdbcTemplate bocJdbcTemplate; 28 | 29 | @Override 30 | public void updateBalance(Long customer, BigDecimal amount) { 31 | bocJdbcTemplate.update(UPDATE_BALANCE, amount, customer); 32 | if(customer.equals(10002L)){ 33 | throw new RuntimeException("test rollbace on runtimeException."); 34 | } 35 | log.info(String.format("update balance ,[customer:%s,amount%s]", customer, amount)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /spring-boot-practice-atomikos/src/main/java/com/foo/service/impl/AccountCcbServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.foo.service.impl; 2 | 3 | import com.foo.service.AccountBocService; 4 | import com.foo.service.AccountCcbService; 5 | import org.apache.commons.logging.Log; 6 | import org.apache.commons.logging.LogFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.jdbc.core.JdbcTemplate; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.transaction.annotation.Transactional; 11 | 12 | import java.math.BigDecimal; 13 | 14 | /** 15 | * @author JasonLin 16 | * @version V1.0 17 | * @date 2017/12/4 18 | */ 19 | @Service("accountCcbService") 20 | @Transactional(rollbackFor = Exception.class) 21 | public class AccountCcbServiceImpl implements AccountCcbService { 22 | 23 | private static final String UPDATE_BALANCE = "UPDATE account_ccb SET balance = balance+? WHERE customer = ?;"; 24 | 25 | private final Log log = LogFactory.getLog(getClass()); 26 | 27 | @Autowired 28 | private JdbcTemplate ccbJdbcTemplate; 29 | 30 | @Autowired 31 | private AccountBocService accountBocService; 32 | 33 | @Override 34 | public void transferAccountToBoc(Long customer, BigDecimal amount) { 35 | updateBalance(customer, amount.multiply(new BigDecimal("-1"))); 36 | accountBocService.updateBalance(customer, amount); 37 | log.info(String.format("transfer balance to boc ,[customer:%s,amount:%s]", customer, amount)); 38 | } 39 | 40 | @Override 41 | public void updateBalance(Long customer, BigDecimal amount) { 42 | ccbJdbcTemplate.update(UPDATE_BALANCE, amount, customer); 43 | log.info(String.format("update balance ,[customer:%s,amount:%s]", customer, amount)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /spring-boot-practice-atomikos/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | boc: 2 | datasource: 3 | url: jdbc:mysql://localhost:3306/db1?useSSL=false&requireSSL=false 4 | driver-class-name: com.mysql.jdbc.Driver 5 | username: root 6 | password: root 7 | 8 | ccb: 9 | datasource: 10 | url: jdbc:mysql://localhost:3306/db2?useSSL=false&requireSSL=false 11 | driver-class-name: com.mysql.jdbc.Driver 12 | username: root 13 | password: root 14 | 15 | druid: 16 | filters: stat, wall 17 | maxActive: 20 18 | initialSize: 1 19 | maxWait: 60000 20 | minIdle: 10 21 | timeBetweenEvictionRunsMillis: 60000 22 | minEvictableIdleTimeMillis: 300000 23 | validationQuery: SELECT 1 24 | testWhileIdle: true 25 | testOnBorrow: false 26 | testOnReturn: false 27 | removeAbandoned: true 28 | removeAbandonedTimeout: 1800 29 | logAbandoned: false 30 | 31 | spring: 32 | jta: 33 | atomikos: 34 | properties: 35 | max-actives: 50 36 | max-timeout: 300000 37 | default-jta-timeout: 10000 38 | enable-logging: true 39 | -------------------------------------------------------------------------------- /spring-boot-practice-atomikos/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | Archetype Created Web Application 7 | 8 | -------------------------------------------------------------------------------- /spring-boot-practice-atomikos/src/main/webapp/index.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Hello World!

4 | 5 | 6 | -------------------------------------------------------------------------------- /spring-boot-practice-atomikos/src/test/java/com/foo/AccountServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.foo; 2 | 3 | import com.foo.service.AccountBocService; 4 | import com.foo.service.AccountCcbService; 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.math.BigDecimal; 12 | 13 | /** 14 | * @author JasonLin 15 | * @version V1.0 16 | * @date 2017/12/4 17 | */ 18 | @RunWith(SpringRunner.class) 19 | @SpringBootTest 20 | public class AccountServiceTest { 21 | 22 | @Autowired 23 | private AccountCcbService accountCcbService; 24 | 25 | @Autowired 26 | private AccountBocService accountBocService; 27 | 28 | @Test 29 | public void testTransferAccountCcbToBoc() { 30 | accountCcbService.transferAccountToBoc(10001L, new BigDecimal(-100)); 31 | } 32 | 33 | @Test 34 | public void testTransferAccountCcbToBocOnException() { 35 | accountCcbService.transferAccountToBoc(10002L, new BigDecimal(100)); 36 | } 37 | 38 | @Test 39 | public void testUpdateCcbBalance() { 40 | accountCcbService.updateBalance(10001L, new BigDecimal(100)); 41 | } 42 | 43 | @Test 44 | public void testUpdateBocBalance() { 45 | accountBocService.updateBalance(10001L, new BigDecimal(100)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /spring-boot-practice-data-jpa/_order.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat MySQL Data Transfer 3 | 4 | Source Server : localhost 5 | Source Server Version : 50714 6 | Source Host : localhost:3306 7 | Source Database : db_order 8 | 9 | Target Server Type : MYSQL 10 | Target Server Version : 50714 11 | File Encoding : 65001 12 | 13 | Date: 2018-08-01 19:01:05 14 | */ 15 | 16 | SET FOREIGN_KEY_CHECKS=0; 17 | 18 | -- ---------------------------- 19 | -- Table structure for _order 20 | -- ---------------------------- 21 | DROP TABLE IF EXISTS `_order`; 22 | CREATE TABLE `_order` ( 23 | `id` varchar(20) NOT NULL, 24 | `total_list_price` decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '总码洋', 25 | `total_sale_price` decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '总实洋', 26 | `purchase_quantity` int(11) NOT NULL DEFAULT '0' COMMENT '购买数量', 27 | `purchase_kinds` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '品种数', 28 | `customer` varchar(255) NOT NULL COMMENT '客户(正常情况下是客户ID)', 29 | PRIMARY KEY (`id`) 30 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 31 | -------------------------------------------------------------------------------- /spring-boot-practice-data-jpa/order_item.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat MySQL Data Transfer 3 | 4 | Source Server : localhost 5 | Source Server Version : 50714 6 | Source Host : localhost:3306 7 | Source Database : db_order 8 | 9 | Target Server Type : MYSQL 10 | Target Server Version : 50714 11 | File Encoding : 65001 12 | 13 | Date: 2018-08-01 19:00:57 14 | */ 15 | 16 | SET FOREIGN_KEY_CHECKS=0; 17 | 18 | -- ---------------------------- 19 | -- Table structure for order_item 20 | -- ---------------------------- 21 | DROP TABLE IF EXISTS `order_item`; 22 | CREATE TABLE `order_item` ( 23 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 24 | `_order` varchar(20) NOT NULL COMMENT '订单号', 25 | `product_sale` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '商品id', 26 | `purchase_quantity` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '购买数量', 27 | `list_price` decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '码洋', 28 | `sale_price` decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '实洋', 29 | PRIMARY KEY (`id`) 30 | ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; 31 | -------------------------------------------------------------------------------- /spring-boot-practice-data-jpa/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | spring-boot-practice 5 | com.foo 6 | 1.0.0-SNAPSHOT 7 | 8 | 4.0.0 9 | spring-boot-paractice-data-jpa 10 | jar 11 | spring-boot-paractice-data-jpa 12 | http://maven.apache.org 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-data-jpa 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-web 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-test 25 | test 26 | 27 | 28 | mysql 29 | mysql-connector-java 30 | 31 | 32 | 33 | spring-boot-paractice-data 34 | 35 | 36 | -------------------------------------------------------------------------------- /spring-boot-practice-data-jpa/readme.txt: -------------------------------------------------------------------------------- 1 | 1、使用jpa包自动添加hibernate依赖 2 | 2、使用hibernateTemplate需要设置sessionFactory 3 | 3、springboot会自动注入DataSource,但是在配置文件中必须以sprping.datasource.*开头的配置项, 4 | 4、默认使用Tomcat连接池 5 | 5、springboot自动注入JdbcTemplate -------------------------------------------------------------------------------- /spring-boot-practice-data-jpa/src/main/java/com/foo/DataJpaApplicationStarter.java: -------------------------------------------------------------------------------- 1 | package com.foo; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | 8 | /** 9 | * @author JasonLin 10 | * @version V1.0 11 | * @date 2017/12/01 12 | */ 13 | @SpringBootApplication 14 | public class DataJpaApplicationStarter { 15 | 16 | private static final Log LOG = LogFactory.getLog(DataJpaApplicationStarter.class); 17 | 18 | public static void main(String[] args) throws Exception { 19 | SpringApplication.run(DataJpaApplicationStarter.class, args); 20 | LOG.info("spring-boot-practice-data-jpa is started."); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /spring-boot-practice-data-jpa/src/main/java/com/foo/configura/Conf.java: -------------------------------------------------------------------------------- 1 | package com.foo.configura; 2 | 3 | import org.hibernate.SessionFactory; 4 | import org.springframework.beans.factory.annotation.Qualifier; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.orm.hibernate5.HibernateTemplate; 8 | import org.springframework.orm.hibernate5.HibernateTransactionManager; 9 | import org.springframework.orm.hibernate5.LocalSessionFactoryBean; 10 | 11 | import javax.sql.DataSource; 12 | import java.util.Properties; 13 | 14 | /** 15 | * @author JasonLin 16 | * @version V1.0 17 | * @date 2017/12/1 18 | */ 19 | @Configuration 20 | public class Conf { 21 | 22 | @Bean(name = "sessionFactory") 23 | public LocalSessionFactoryBean sessionFactory(DataSource dataSource) { 24 | LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); 25 | sessionFactory.setDataSource(dataSource); 26 | Properties properties = new Properties(); 27 | properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect"); 28 | properties.put("hibernate.show_sql", true); 29 | properties.put("hibernate.connection.release_mode", "after_transaction"); 30 | properties.put("hibernate.cache.use_second_level_cache", false); 31 | properties.put("hibernate.cache.use_query_cache", false); 32 | sessionFactory.setHibernateProperties(properties); 33 | sessionFactory.setPackagesToScan("com.foo.model"); 34 | return sessionFactory; 35 | } 36 | 37 | @Bean("transactionManager") 38 | HibernateTransactionManager getHibernateTransactionManager(@Qualifier("sessionFactory") SessionFactory sessionFactory){ 39 | return new HibernateTransactionManager(sessionFactory); 40 | } 41 | 42 | @Bean("hibernateTemplate") 43 | HibernateTemplate getHibernateTemplate(@Qualifier("sessionFactory") SessionFactory sessionFactory) { 44 | HibernateTemplate hibernateTemplate = new HibernateTemplate(); 45 | hibernateTemplate.setSessionFactory(sessionFactory); 46 | return hibernateTemplate; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /spring-boot-practice-data-jpa/src/main/java/com/foo/dao/OrderDao.java: -------------------------------------------------------------------------------- 1 | package com.foo.dao; 2 | 3 | import com.foo.model.Order; 4 | 5 | /** 6 | * @author JasonLin 7 | * @version V1.0 8 | * @date 2017/12/1 9 | */ 10 | public interface OrderDao { 11 | void save(Order order); 12 | } 13 | -------------------------------------------------------------------------------- /spring-boot-practice-data-jpa/src/main/java/com/foo/dao/impl/OrderDaoImpl.java: -------------------------------------------------------------------------------- 1 | package com.foo.dao.impl; 2 | 3 | import com.foo.dao.OrderDao; 4 | import com.foo.model.Order; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.orm.hibernate5.HibernateTemplate; 7 | import org.springframework.stereotype.Repository; 8 | 9 | /** 10 | * @author JasonLin 11 | * @version V1.0 12 | * @date 2017/12/1 13 | */ 14 | @Repository("orderDao") 15 | public class OrderDaoImpl implements OrderDao{ 16 | 17 | @Autowired 18 | private HibernateTemplate hibernateTemplate; 19 | 20 | @Override 21 | public void save(Order order) { 22 | hibernateTemplate.save(order); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /spring-boot-practice-data-jpa/src/main/java/com/foo/model/Order.java: -------------------------------------------------------------------------------- 1 | package com.foo.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.persistence.CascadeType; 7 | import javax.persistence.Column; 8 | import javax.persistence.Entity; 9 | import javax.persistence.GeneratedValue; 10 | import javax.persistence.GenerationType; 11 | import javax.persistence.Id; 12 | import javax.persistence.ManyToOne; 13 | import javax.persistence.OneToMany; 14 | import javax.persistence.Table; 15 | import java.io.Serializable; 16 | import java.math.BigDecimal; 17 | import java.util.List; 18 | import java.util.Set; 19 | 20 | /** 21 | * @author JasonLin 22 | * @version V1.0 23 | * @date 2017/12/1 24 | */ 25 | @Getter 26 | @Setter 27 | @Entity 28 | @Table(name = "_order") 29 | public class Order implements Serializable { 30 | 31 | private static final long serialVersionUID = 1854996605034612378L; 32 | 33 | @Id 34 | private String id; 35 | 36 | @Column(name = "total_list_price") 37 | private BigDecimal totalListPrice; 38 | 39 | @Column(name = "total_sale_price") 40 | private BigDecimal totalSalePrice; 41 | 42 | @Column(name = "purchase_quantity") 43 | private Integer purchaseQuantity; 44 | 45 | /** 46 | * 品种数量 47 | */ 48 | @Column(name = "purchase_kinds") 49 | private Integer purchaseKinds; 50 | 51 | @Column 52 | //正常情况下存储的是客户ID 53 | private String customer; 54 | 55 | @OneToMany(cascade = CascadeType.ALL, mappedBy = "order", targetEntity = OrderItem.class) 56 | private Set itemList; 57 | } 58 | -------------------------------------------------------------------------------- /spring-boot-practice-data-jpa/src/main/java/com/foo/model/OrderItem.java: -------------------------------------------------------------------------------- 1 | package com.foo.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.GeneratedValue; 9 | import javax.persistence.GenerationType; 10 | import javax.persistence.Id; 11 | import javax.persistence.JoinColumn; 12 | import javax.persistence.ManyToOne; 13 | import javax.persistence.Table; 14 | import java.io.Serializable; 15 | import java.math.BigDecimal; 16 | 17 | /** 18 | * @author JasonLin 19 | * @version V1.0 20 | * @date 2017/12/1 21 | */ 22 | @Getter 23 | @Setter 24 | @Entity 25 | @Table(name = "order_item") 26 | public class OrderItem implements Serializable{ 27 | private static final long serialVersionUID = 8272679709545182358L; 28 | 29 | @Id 30 | @GeneratedValue(strategy = GenerationType.IDENTITY) 31 | private Long id; 32 | 33 | @ManyToOne 34 | @JoinColumn(name = "_order") 35 | private Order order; 36 | 37 | /** 38 | * 商品ID 39 | */ 40 | @Column(name = "product_sale") 41 | private Long productSale; 42 | 43 | /** 44 | * 购买数量 45 | */ 46 | @Column(name = "purchase_quantity") 47 | private Integer purchaseQuantity; 48 | 49 | /** 50 | * 码洋 51 | */ 52 | @Column(name = "list_price") 53 | private BigDecimal listPrice; 54 | 55 | /** 56 | * 实洋 57 | */ 58 | @Column(name = "sale_price") 59 | private BigDecimal salePrice; 60 | 61 | } 62 | -------------------------------------------------------------------------------- /spring-boot-practice-data-jpa/src/main/java/com/foo/services/OrderService.java: -------------------------------------------------------------------------------- 1 | package com.foo.services; 2 | 3 | import com.foo.model.Order; 4 | 5 | /** 6 | * @author JasonLin 7 | * @version V1.0 8 | * @date 2017/12/1 9 | */ 10 | public interface OrderService { 11 | 12 | void create(Order order); 13 | } 14 | -------------------------------------------------------------------------------- /spring-boot-practice-data-jpa/src/main/java/com/foo/services/impl/OrderServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.foo.services.impl; 2 | 3 | import com.foo.dao.OrderDao; 4 | import com.foo.model.Order; 5 | import com.foo.model.OrderItem; 6 | import com.foo.services.OrderService; 7 | import com.google.common.base.Preconditions; 8 | import org.apache.commons.logging.Log; 9 | import org.apache.commons.logging.LogFactory; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.transaction.annotation.Transactional; 13 | import org.springframework.util.CollectionUtils; 14 | 15 | import java.math.BigDecimal; 16 | 17 | 18 | /** 19 | * @author JasonLin 20 | * @version V1.0 21 | * @date 2017/12/1 22 | */ 23 | @Service("orderService") 24 | @Transactional(rollbackFor = Exception.class) 25 | public class OrderServiceImpl implements OrderService { 26 | 27 | private static final Log LOG = LogFactory.getLog(OrderServiceImpl.class); 28 | 29 | @Autowired 30 | private OrderDao orderDao; 31 | 32 | @Override 33 | public void create(Order order) { 34 | checkOrder(order); 35 | initOrder(order); 36 | orderDao.save(order); 37 | LOG.info("create order successed,orderId:" + order.getId()); 38 | // throw new RuntimeException("test exception"); 39 | } 40 | 41 | private void checkOrder(Order order) { 42 | Preconditions.checkNotNull(order, "order is null."); 43 | Preconditions.checkArgument(!CollectionUtils.isEmpty(order.getItemList()), "OrderItem is empty."); 44 | } 45 | 46 | private void initOrder(Order order) { 47 | BigDecimal totalListPrice = BigDecimal.ZERO; 48 | BigDecimal totalSalePrice = BigDecimal.ZERO; 49 | Integer purchaseQuantity = 0; 50 | Integer purchaseKind = order.getItemList().size(); 51 | for (OrderItem orderItem : order.getItemList()) { 52 | totalListPrice = totalListPrice.add(orderItem.getListPrice()); 53 | totalSalePrice = totalSalePrice.add(orderItem.getSalePrice()); 54 | purchaseQuantity += orderItem.getPurchaseQuantity(); 55 | } 56 | order.setTotalListPrice(totalListPrice); 57 | order.setTotalSalePrice(totalSalePrice); 58 | order.setPurchaseKinds(purchaseKind); 59 | order.setPurchaseQuantity(purchaseQuantity); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /spring-boot-practice-data-jpa/src/main/java/com/foo/utils/IdUtils.java: -------------------------------------------------------------------------------- 1 | package com.foo.utils; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * 7 | * @author JiaSonglin 8 | * @version V1.0 9 | * 2017年6月29日 10 | */ 11 | public class IdUtils { 12 | 13 | private static Date date = new Date(); 14 | private static StringBuilder buf = new StringBuilder(); 15 | private static int seq = 0; 16 | private static final int ROTATION = 99999; 17 | 18 | public static synchronized long next() { 19 | if (seq > ROTATION){ 20 | seq = 0; 21 | } 22 | buf.delete(0, buf.length()); 23 | date.setTime(System.currentTimeMillis()); 24 | String str = String.format("%1$tY%1$tm%1$td%1$tk%1$tM%1$tS%2$05d", date, seq++); 25 | return Long.parseLong(str); 26 | } 27 | 28 | public static synchronized String next(String prefix) { 29 | return prefix+next(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /spring-boot-practice-data-jpa/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | url: jdbc:mysql://localhost:3306/db_order?useSSL=false&requireSSL=false 4 | driver-class-name: com.mysql.jdbc.Driver 5 | username: root 6 | password: 123456 7 | tomcat: 8 | max-wait: 10000 9 | min-idle: 0 10 | initial-size: 25 11 | validation-query: SELECT 1 12 | test-on-borrow: false 13 | test-while-idle: true 14 | time-between-eviction-runs-millis: 18800 15 | remove-abandoned: true 16 | remove-abandoned-timeout: 180 -------------------------------------------------------------------------------- /spring-boot-practice-data-jpa/src/test/java/com/foo/services/test/TestOrderService.java: -------------------------------------------------------------------------------- 1 | package com.foo.services.test; 2 | 3 | import com.foo.model.Order; 4 | import com.foo.model.OrderItem; 5 | import com.foo.services.OrderService; 6 | import com.foo.utils.IdUtils; 7 | import org.assertj.core.util.Sets; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.boot.test.context.SpringBootTest; 12 | import org.springframework.test.context.junit4.SpringRunner; 13 | 14 | import java.math.BigDecimal; 15 | import java.util.Set; 16 | 17 | /** 18 | * @author JasonLin 19 | * @version V1.0 20 | * @date 2017/12/1 21 | */ 22 | @RunWith(SpringRunner.class) 23 | @SpringBootTest 24 | public class TestOrderService { 25 | 26 | @Autowired 27 | private OrderService orderService; 28 | 29 | @Test 30 | public void testCreate(){ 31 | Order order = new Order(); 32 | Set orderItems = Sets.newHashSet(); 33 | 34 | OrderItem orderItem1 = new OrderItem(); 35 | orderItem1.setListPrice(new BigDecimal("11.02")); 36 | orderItem1.setSalePrice(new BigDecimal("9.99")); 37 | orderItem1.setOrder(order); 38 | orderItem1.setProductSale(1222021L); 39 | orderItem1.setPurchaseQuantity(1); 40 | 41 | OrderItem orderItem2 = new OrderItem(); 42 | orderItem2.setListPrice(new BigDecimal("8.5")); 43 | orderItem2.setSalePrice(new BigDecimal("8.0")); 44 | orderItem2.setOrder(order); 45 | orderItem2.setProductSale(1222056L); 46 | orderItem2.setPurchaseQuantity(2); 47 | 48 | orderItems.add(orderItem1); 49 | orderItems.add(orderItem2); 50 | 51 | order.setId(String.valueOf(IdUtils.next())); 52 | order.setCustomer("jasonLin"); 53 | order.setItemList(orderItems); 54 | orderService.create(order); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /spring-boot-practice-filter/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | spring-boot-practice 5 | com.foo 6 | 1.0.0-SNAPSHOT 7 | 8 | 4.0.0 9 | spring-boot-practice-filter 10 | war 11 | spring-boot-practice-filter Maven Webapp 12 | http://maven.apache.org 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-web 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-test 21 | test 22 | 23 | 24 | 25 | spring-boot-practice-filter 26 | 27 | 28 | -------------------------------------------------------------------------------- /spring-boot-practice-filter/src/main/java/foo/SimpleApplicationStarter.java: -------------------------------------------------------------------------------- 1 | package foo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.web.servlet.ServletComponentScan; 6 | 7 | /** 8 | *

Description:

9 | * @author JiaSonglin 10 | * @version V1.0,2017年4月1日 上午9:43:16 11 | */ 12 | @SpringBootApplication 13 | @ServletComponentScan 14 | public class SimpleApplicationStarter { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(SimpleApplicationStarter.class, args); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /spring-boot-practice-filter/src/main/java/foo/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | package foo.controller; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | @RestController 7 | public class IndexController { 8 | 9 | @RequestMapping("/index") 10 | public String index(){ 11 | return "hello world"; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /spring-boot-practice-filter/src/main/java/foo/filter/anno/MyAnnotationFilter.java: -------------------------------------------------------------------------------- 1 | package foo.filter.anno; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.Filter; 6 | import javax.servlet.FilterChain; 7 | import javax.servlet.FilterConfig; 8 | import javax.servlet.ServletException; 9 | import javax.servlet.ServletRequest; 10 | import javax.servlet.ServletResponse; 11 | import javax.servlet.annotation.WebFilter; 12 | 13 | /** 14 | * 注解方式配置Filter,需在启动类上加入 15 | * 16 | * @ServletComponentScan注解 17 | * 18 | */ 19 | @WebFilter 20 | public class MyAnnotationFilter implements Filter { 21 | 22 | @Override 23 | public void init(FilterConfig filterConfig) throws ServletException { 24 | System.out.println("init MyAnnotationFilter..."); 25 | } 26 | 27 | @Override 28 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 29 | throws IOException, ServletException { 30 | chain.doFilter(request, response); 31 | System.out.println("do MyAnnotationFilter..."); 32 | } 33 | 34 | @Override 35 | public void destroy() { 36 | System.out.println("destroy MyAnnotationFilter..."); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /spring-boot-practice-filter/src/main/java/foo/filter/bean/FilterConfiguration.java: -------------------------------------------------------------------------------- 1 | package foo.filter.bean; 2 | 3 | import java.util.Arrays; 4 | 5 | import javax.servlet.DispatcherType; 6 | 7 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | 11 | @Configuration 12 | public class FilterConfiguration { 13 | 14 | @Bean 15 | public FilterRegistrationBean myFilterRegistrationBean(MyBeanFilter myBeanFilter){ 16 | FilterRegistrationBean registration = new FilterRegistrationBean(); 17 | registration.setDispatcherTypes(DispatcherType.REQUEST); 18 | registration.setFilter(myBeanFilter); 19 | registration.setUrlPatterns(Arrays.asList("/index")); 20 | return registration; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /spring-boot-practice-filter/src/main/java/foo/filter/bean/MyBeanFilter.java: -------------------------------------------------------------------------------- 1 | package foo.filter.bean; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.Filter; 6 | import javax.servlet.FilterChain; 7 | import javax.servlet.FilterConfig; 8 | import javax.servlet.ServletException; 9 | import javax.servlet.ServletRequest; 10 | import javax.servlet.ServletResponse; 11 | 12 | import org.springframework.stereotype.Component; 13 | 14 | @Component 15 | public class MyBeanFilter implements Filter{ 16 | 17 | @Override 18 | public void init(FilterConfig filterConfig) throws ServletException { 19 | System.out.println("init MyBeanFilter..."); 20 | } 21 | 22 | @Override 23 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 24 | throws IOException, ServletException { 25 | chain.doFilter(request, response); 26 | System.out.println("do MyBeanFilter..."); 27 | } 28 | 29 | @Override 30 | public void destroy() { 31 | System.out.println("destroy MyBeanFilter..."); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /spring-boot-practice-html/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | spring-boot-practice 5 | com.foo 6 | 1.0.0-SNAPSHOT 7 | 8 | 4.0.0 9 | spring-boot-paractice-html 10 | jar 11 | spring-boot-paractice-html 12 | http://maven.apache.org 13 | 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-web 18 | 19 | 20 | 21 | 22 | spring-boot-paractice-html 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-maven-plugin 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /spring-boot-practice-html/readme.txt: -------------------------------------------------------------------------------- 1 | 1、jsp需要进行编译,而html等模板文件不需要。 2 | 2、springboot可以访问resources/static目录下的资源文件。resources/static默认的资源访问路径为/ 3 | 也可以自定义资源文件访问路径。eg: 4 | 资源文件路径为: resources/static/dist/ 那么要访问/dist目录下的资源文件,则默认的访问路径就是/dist 5 | 要更改访问路径/dist为/,只需要添加配置: spring.resources.static-locations=classpath:/static/dist/ 6 | 3、建议前后端分离,springboot只提供restful接口,前端单独一个工程。 7 | 4、 8 | org.springframework.boot 9 | spring-boot-maven-plugin 10 | 11 | 该插件能将springboot工程打包为一个可以执行的jar包。可直接运行不需要外部容器(使用内嵌的Tomcat容器)。所以springboot更适合做微服务。 12 | 13 | -------------------------------------------------------------------------------- /spring-boot-practice-html/src/main/java/com/foo/HtmlApplicationStarter.java: -------------------------------------------------------------------------------- 1 | package com.foo; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | 8 | /** 9 | * @author JasonLin 10 | * @version V1.0 11 | * @date 2017/12/01 12 | */ 13 | @SpringBootApplication 14 | public class HtmlApplicationStarter { 15 | 16 | private static final Log LOG = LogFactory.getLog(HtmlApplicationStarter.class); 17 | 18 | public static void main(String[] args) throws Exception { 19 | SpringApplication.run(HtmlApplicationStarter.class, args); 20 | LOG.info("spring-boot-practice-html is started."); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /spring-boot-practice-html/src/main/java/com/foo/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.foo.controller; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | import org.springframework.web.servlet.ModelAndView; 6 | 7 | /** 8 | * @author JasonLin 9 | * @version V1.0 10 | * @date 2017/12/1 11 | */ 12 | @RestController 13 | public class IndexController { 14 | 15 | @RequestMapping("/") 16 | public ModelAndView index() { 17 | return new ModelAndView("index"); 18 | } 19 | 20 | // @RequestMapping("/homeAction") 21 | // public ModelAndView home() { 22 | // return new ModelAndView("home"); 23 | // } 24 | } 25 | -------------------------------------------------------------------------------- /spring-boot-practice-html/src/main/java/com/foo/controller/WelcomeController.java: -------------------------------------------------------------------------------- 1 | package com.foo.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | /** 11 | * @author JasonLin 12 | * @version V1.0 13 | * @date 2017/11/30 14 | */ 15 | @RestController 16 | public class WelcomeController { 17 | 18 | @Value("${application.message:Hello World}") 19 | private String message = "Hello World"; 20 | 21 | @RequestMapping("/welcome") 22 | public Map welcome() { 23 | Map ret = new HashMap(); 24 | ret.put("message", message); 25 | return ret; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /spring-boot-practice-html/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #variable 2 | application.message=Hello JasonLin 3 | #port 4 | server.port=8089 5 | #MVC 6 | spring.mvc.view.prefix=/ 7 | spring.mvc.view.suffix=.html 8 | #spring.resources.static-locations=classpath:/static/dist/ -------------------------------------------------------------------------------- /spring-boot-practice-html/src/main/resources/static/dist/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | -----home page!------ 9 | 10 | -------------------------------------------------------------------------------- /spring-boot-practice-html/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | -----hello jasonLin!------ 9 | 10 | -------------------------------------------------------------------------------- /spring-boot-practice-jsp/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | spring-boot-practice 5 | com.foo 6 | 1.0.0-SNAPSHOT 7 | 8 | 4.0.0 9 | spring-boot-practice-jsp 10 | war 11 | spring-boot-practice-jsp 12 | http://maven.apache.org 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-web 17 | 18 | 19 | javax.servlet 20 | jstl 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-tomcat 25 | provided 26 | 27 | 28 | org.apache.tomcat.embed 29 | tomcat-embed-jasper 30 | provided 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-test 35 | test 36 | 37 | 38 | 39 | spring-boot-practice-jsp 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-maven-plugin 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /spring-boot-practice-jsp/readme.txt: -------------------------------------------------------------------------------- 1 | 1、jsp项目需要引入tomcat-embed-jasper和jstl 2 | 2、jsp web项目需要发布在Tomcat中以war包运行,直接打jar包,web-inf目录下的资源文件不会打包在jar包中,会使view无法访问. 3 | 3、war在Tomcat容器里面运行容器已经包含Tomcat相关的包,发布到容器需将Tomcat和jasper的scope设置为: provided 4 | 4、springboot会默认加载application.properties文件. 5 | server.port 端口 6 | spring.mvc.view.prefix 资源文件前缀 7 | spring.mvc.view.suffix 资源文件后缀 -------------------------------------------------------------------------------- /spring-boot-practice-jsp/src/main/java/com/foo/JspApplicationStarter.java: -------------------------------------------------------------------------------- 1 | package com.foo; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.boot.builder.SpringApplicationBuilder; 8 | import org.springframework.boot.web.support.SpringBootServletInitializer; 9 | 10 | /** 11 | * @author JasonLin 12 | * @version V1.0 13 | * @date 2017/11/30 14 | */ 15 | @SpringBootApplication 16 | public class JspApplicationStarter extends SpringBootServletInitializer { 17 | 18 | private static final Log LOG = LogFactory.getLog(JspApplicationStarter.class); 19 | 20 | @Override 21 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 22 | return application.sources(JspApplicationStarter.class); 23 | } 24 | 25 | public static void main(String[] args) throws Exception { 26 | SpringApplication.run(JspApplicationStarter.class, args); 27 | LOG.info("spring-boot-practice-jsp is started."); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /spring-boot-practice-jsp/src/main/java/com/foo/controller/WelcomeController.java: -------------------------------------------------------------------------------- 1 | package com.foo.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.stereotype.Controller; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.servlet.ModelAndView; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * @author JasonLin 12 | * @version V1.0 13 | * @date 2017/11/30 14 | */ 15 | @Controller 16 | public class WelcomeController { 17 | 18 | @Value("${application.message:Hello World}") 19 | private String message = "Hello World"; 20 | 21 | @RequestMapping("/") 22 | public ModelAndView welcome() { 23 | ModelAndView modelAndView = new ModelAndView("/welcome"); 24 | modelAndView.addObject("message", this.message); 25 | modelAndView.addObject("time", new Date()); 26 | return modelAndView; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /spring-boot-practice-jsp/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #variable 2 | application.message=Hello JasonLin 3 | #port 4 | server.port=8089 5 | #MVC 6 | spring.mvc.view.prefix=/WEB-INF/jsp 7 | spring.mvc.view.suffix=.jsp -------------------------------------------------------------------------------- /spring-boot-practice-jsp/src/main/webapp/WEB-INF/jsp/welcome.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> 4 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 5 | 6 | 7 | 8 | 9 | 10 | 11 | Spring URL: ${springUrl} at ${time} 12 |
13 | JSTL URL: ${url} 14 |
15 | Message: ${message} 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /spring-boot-practice-multiple-datasource/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | spring-boot-practice 5 | com.foo 6 | 1.0.0-SNAPSHOT 7 | 8 | 4.0.0 9 | spring-boot-practice-multiple-datasource 10 | jar 11 | spring-boot-practice-multiple-datasource 12 | http://maven.apache.org 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-web 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-test 21 | test 22 | 23 | 24 | mysql 25 | mysql-connector-java 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-data-jpa 30 | 31 | 32 | com.alibaba 33 | druid 34 | 1.0.9 35 | 36 | 37 | 38 | spring-boot-practice-multiple-datasource 39 | 40 | 41 | -------------------------------------------------------------------------------- /spring-boot-practice-multiple-datasource/readme.txt: -------------------------------------------------------------------------------- 1 | 1、@ConfigurationProperties(prefix = "druid") 会将application.yml里面的配置自动注入到类中 2 | 2、当使用多数据源时必须通过@Primary指定主要的数据源,使用@ConfigurationProperties与此类似 3 | 3、多数据源如果使用默认的datasourceManager会产生跨库事物问题 4 | 4、@Bean bean名称默认为方法名称 -------------------------------------------------------------------------------- /spring-boot-practice-multiple-datasource/src/main/java/com/foo/MultipleDataSourceApplicationStarter.java: -------------------------------------------------------------------------------- 1 | package com.foo; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | 8 | /** 9 | * @author JasonLin 10 | * @version V1.0 11 | * @date 2017/12/01 12 | */ 13 | @SpringBootApplication 14 | public class MultipleDataSourceApplicationStarter { 15 | 16 | private static final Log LOG = LogFactory.getLog(MultipleDataSourceApplicationStarter.class); 17 | 18 | public static void main(String[] args) throws Exception { 19 | SpringApplication.run(MultipleDataSourceApplicationStarter.class, args); 20 | LOG.info("spring-boot-practice-data-custom-datasource is started."); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /spring-boot-practice-multiple-datasource/src/main/java/com/foo/conf/CustomConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.foo.conf; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.beans.factory.annotation.Qualifier; 6 | import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; 7 | import org.springframework.boot.context.properties.ConfigurationProperties; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.context.annotation.Primary; 11 | import org.springframework.jdbc.core.JdbcTemplate; 12 | 13 | import javax.sql.DataSource; 14 | import java.sql.SQLException; 15 | 16 | /** 17 | * @author JasonLin 18 | * @version V1.0 19 | * @date 2017/12/1 20 | */ 21 | @Configuration 22 | public class CustomConfiguration { 23 | 24 | @Autowired 25 | private DruidDataSourceProperties druidDataSourceProperties; 26 | 27 | @Bean 28 | @Primary 29 | @ConfigurationProperties(prefix = "boc.datasource") 30 | public DataSourceProperties bocDataSourceProperties() { 31 | return new DataSourceProperties(); 32 | } 33 | 34 | @Bean 35 | @ConfigurationProperties(prefix = "ccb.datasource") 36 | public DataSourceProperties ccbDataSourceProperties() { 37 | return new DataSourceProperties(); 38 | } 39 | 40 | @Bean 41 | @Primary 42 | @ConfigurationProperties(prefix = "boc.datasource") 43 | public DruidDataSource bocDataSource(@Qualifier("bocDataSourceProperties") DataSourceProperties dataSourceProperties) throws SQLException { 44 | DruidDataSource druidDataSource = new DruidDataSource(); 45 | InitDruidDataSource(druidDataSource, dataSourceProperties); 46 | return druidDataSource; 47 | } 48 | 49 | @Bean 50 | @ConfigurationProperties(prefix = "ccb.datasource") 51 | public DruidDataSource ccbDataSource(@Qualifier("ccbDataSourceProperties") DataSourceProperties dataSourceProperties) throws SQLException { 52 | DruidDataSource druidDataSource = new DruidDataSource(); 53 | InitDruidDataSource(druidDataSource, dataSourceProperties); 54 | return druidDataSource; 55 | } 56 | 57 | @Bean 58 | public JdbcTemplate bocJdbcTemplate(@Qualifier("bocDataSource") DataSource bocDataSource) { 59 | return new JdbcTemplate(bocDataSource); 60 | } 61 | 62 | @Bean 63 | public JdbcTemplate ccbJdbcTemplate(@Qualifier("ccbDataSource") DataSource ccbDataSource) { 64 | return new JdbcTemplate(ccbDataSource); 65 | } 66 | 67 | private void InitDruidDataSource(DruidDataSource druidDataSource, DataSourceProperties properties) throws SQLException { 68 | druidDataSource.setUrl(properties.getUrl()); 69 | druidDataSource.setUsername(properties.getUsername()); 70 | druidDataSource.setPassword(properties.getPassword()); 71 | druidDataSource.setDriverClassName(properties.getDriverClassName()); 72 | //属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: 73 | //监控统计用的filter:stat 74 | //日志用的filter:log4j 75 | //防御sql注入的filter:wall 76 | druidDataSource.setFilters(druidDataSourceProperties.getFilters()); 77 | //最大连接池数量 78 | druidDataSource.setMaxActive(druidDataSourceProperties.getMaxActive()); 79 | // 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时 80 | druidDataSource.setInitialSize(druidDataSourceProperties.getInitialSize()); 81 | //获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。 82 | druidDataSource.setMaxWait(druidDataSourceProperties.getMaxWait()); 83 | //最小连接池数量 84 | druidDataSource.setMinIdle(druidDataSourceProperties.getMinIdle()); 85 | //有两个含义: 86 | //1) Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。 87 | //2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明 88 | druidDataSource.setTimeBetweenEvictionRunsMillis(druidDataSourceProperties.getTimeBetweenEvictionRunsMillis()); 89 | //连接保持空闲而不被驱逐的最小时间 90 | druidDataSource.setMinEvictableIdleTimeMillis(druidDataSourceProperties.getMinEvictableIdleTimeMillis()); 91 | druidDataSource.setValidationQuery(druidDataSourceProperties.getValidationQuery()); 92 | //建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis, 93 | //(空闲时测试)执行validationQuery检测连接是否有效。 94 | druidDataSource.setTestWhileIdle(druidDataSourceProperties.isTestWhileIdle()); 95 | //申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 96 | druidDataSource.setTestOnBorrow(druidDataSourceProperties.isTestOnBorrow()); 97 | //归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 98 | druidDataSource.setTestOnReturn(druidDataSourceProperties.isTestOnReturn()); 99 | //移除泄露的链接 100 | druidDataSource.setRemoveAbandoned(druidDataSourceProperties.isRemoveAbandoned()); 101 | //泄露连接的定义时间(要超过最大事务的处理时间) 102 | druidDataSource.setRemoveAbandonedTimeout(druidDataSourceProperties.getRemoveAbandonedTimeout()); 103 | //移除泄露连接发生是是否记录日志 104 | druidDataSource.setLogAbandoned(druidDataSourceProperties.isLogAbandoned()); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /spring-boot-practice-multiple-datasource/src/main/java/com/foo/conf/DruidDataSourceProperties.java: -------------------------------------------------------------------------------- 1 | package com.foo.conf; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | /** 9 | * @author JasonLin 10 | * @version V1.0 11 | * @date 2017/12/4 12 | */ 13 | @Getter 14 | @Setter 15 | @Configuration 16 | @ConfigurationProperties(prefix = "druid") 17 | public class DruidDataSourceProperties { 18 | private String filters; 19 | private int maxActive; 20 | private int initialSize; 21 | private int maxWait; 22 | private int minIdle; 23 | private long timeBetweenEvictionRunsMillis; 24 | private long minEvictableIdleTimeMillis; 25 | private String validationQuery; 26 | private boolean testWhileIdle; 27 | private boolean testOnBorrow; 28 | private boolean testOnReturn; 29 | private int maxOpenPreparedStatements; 30 | private boolean removeAbandoned; 31 | private int removeAbandonedTimeout; 32 | private boolean logAbandoned; 33 | } 34 | -------------------------------------------------------------------------------- /spring-boot-practice-multiple-datasource/src/main/java/com/foo/model/AccountBOC.java: -------------------------------------------------------------------------------- 1 | package com.foo.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.GeneratedValue; 9 | import javax.persistence.GenerationType; 10 | import javax.persistence.Id; 11 | import javax.persistence.Table; 12 | import java.io.Serializable; 13 | import java.math.BigDecimal; 14 | 15 | /** 16 | * @author JasonLin 17 | * @version V1.0 18 | * @date 2017/12/4 19 | */ 20 | @Setter 21 | @Getter 22 | @Entity 23 | @Table(name = "account_boc") 24 | public class AccountBOC implements Serializable { 25 | 26 | private static final long serialVersionUID = 1820150874495571704L; 27 | 28 | @Id 29 | @GeneratedValue(strategy = GenerationType.IDENTITY) 30 | private Long id; 31 | 32 | @Column 33 | private Long customer; 34 | 35 | @Column 36 | private BigDecimal balance; 37 | } 38 | -------------------------------------------------------------------------------- /spring-boot-practice-multiple-datasource/src/main/java/com/foo/model/AccountCCB.java: -------------------------------------------------------------------------------- 1 | package com.foo.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.GeneratedValue; 9 | import javax.persistence.GenerationType; 10 | import javax.persistence.Id; 11 | import javax.persistence.Table; 12 | import java.io.Serializable; 13 | import java.math.BigDecimal; 14 | 15 | /** 16 | * @author JasonLin 17 | * @version V1.0 18 | * @date 2017/12/4 19 | */ 20 | @Setter 21 | @Getter 22 | @Entity 23 | @Table(name = "account_ccb") 24 | public class AccountCCB implements Serializable{ 25 | 26 | private static final long serialVersionUID = 1476688047241463855L; 27 | 28 | @Id 29 | @GeneratedValue(strategy = GenerationType.IDENTITY) 30 | private Long id; 31 | 32 | @Column 33 | private Long customer; 34 | 35 | @Column 36 | private BigDecimal balance; 37 | } 38 | -------------------------------------------------------------------------------- /spring-boot-practice-multiple-datasource/src/main/java/com/foo/service/AccountBocService.java: -------------------------------------------------------------------------------- 1 | package com.foo.service; 2 | 3 | import java.math.BigDecimal; 4 | 5 | /** 6 | * @author JasonLin 7 | * @version V1.0 8 | * @date 2017/12/4 9 | */ 10 | public interface AccountBocService { 11 | 12 | void updateBalance(Long customer, BigDecimal amount); 13 | } 14 | -------------------------------------------------------------------------------- /spring-boot-practice-multiple-datasource/src/main/java/com/foo/service/AccountCcbService.java: -------------------------------------------------------------------------------- 1 | package com.foo.service; 2 | 3 | import java.math.BigDecimal; 4 | 5 | /** 6 | * @author JasonLin 7 | * @version V1.0 8 | * @date 2017/12/4 9 | */ 10 | public interface AccountCcbService { 11 | 12 | void transferAccountToBoc(Long customer, BigDecimal amount); 13 | 14 | void updateBalance(Long customer, BigDecimal amount); 15 | } 16 | -------------------------------------------------------------------------------- /spring-boot-practice-multiple-datasource/src/main/java/com/foo/service/impl/AccountBocServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.foo.service.impl; 2 | 3 | import com.foo.service.AccountBocService; 4 | import org.apache.commons.logging.Log; 5 | import org.apache.commons.logging.LogFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.jdbc.core.JdbcTemplate; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | import java.math.BigDecimal; 12 | 13 | /** 14 | * @author JasonLin 15 | * @version V1.0 16 | * @date 2017/12/4 17 | */ 18 | @Service("accountBocService") 19 | @Transactional(rollbackFor = Exception.class) 20 | public class AccountBocServiceImpl implements AccountBocService { 21 | 22 | private static final String UPDATE_BALANCE = "UPDATE account_boc SET balance = balance+? WHERE customer = ?;"; 23 | 24 | private final Log log = LogFactory.getLog(getClass()); 25 | 26 | @Autowired 27 | private JdbcTemplate bocJdbcTemplate; 28 | 29 | @Override 30 | public void updateBalance(Long customer, BigDecimal amount) { 31 | bocJdbcTemplate.update(UPDATE_BALANCE, amount, customer); 32 | if(customer.equals(10002L)){ 33 | throw new RuntimeException("test rollbace on runtimeException."); 34 | } 35 | log.info(String.format("update balance ,[customer:%s,amount%s]", customer, amount)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /spring-boot-practice-multiple-datasource/src/main/java/com/foo/service/impl/AccountCcbServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.foo.service.impl; 2 | 3 | import com.foo.service.AccountBocService; 4 | import com.foo.service.AccountCcbService; 5 | import org.apache.commons.logging.Log; 6 | import org.apache.commons.logging.LogFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.jdbc.core.JdbcTemplate; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.transaction.annotation.Transactional; 11 | 12 | import java.math.BigDecimal; 13 | 14 | /** 15 | * @author JasonLin 16 | * @version V1.0 17 | * @date 2017/12/4 18 | */ 19 | @Service("accountCcbService") 20 | @Transactional(rollbackFor = Exception.class) 21 | public class AccountCcbServiceImpl implements AccountCcbService { 22 | 23 | private static final String UPDATE_BALANCE = "UPDATE account_ccb SET balance = balance+? WHERE customer = ?;"; 24 | 25 | private final Log log = LogFactory.getLog(getClass()); 26 | 27 | @Autowired 28 | private JdbcTemplate ccbJdbcTemplate; 29 | 30 | @Autowired 31 | private AccountBocService accountBocService; 32 | 33 | @Override 34 | public void transferAccountToBoc(Long customer, BigDecimal amount) { 35 | updateBalance(customer, amount.multiply(new BigDecimal("-1"))); 36 | accountBocService.updateBalance(customer, amount); 37 | log.info(String.format("transfer balance to boc ,[customer:%s,amount:%s]", customer, amount)); 38 | } 39 | 40 | @Override 41 | public void updateBalance(Long customer, BigDecimal amount) { 42 | ccbJdbcTemplate.update(UPDATE_BALANCE, amount, customer); 43 | log.info(String.format("update balance ,[customer:%s,amount:%s]", customer, amount)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /spring-boot-practice-multiple-datasource/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | boc: 2 | datasource: 3 | url: jdbc:mysql://localhost:3306/db1?useSSL=false&requireSSL=false 4 | driver-class-name: com.mysql.jdbc.Driver 5 | username: root 6 | password: root 7 | 8 | ccb: 9 | datasource: 10 | url: jdbc:mysql://localhost:3306/db2?useSSL=false&requireSSL=false 11 | driver-class-name: com.mysql.jdbc.Driver 12 | username: root 13 | password: root 14 | 15 | druid: 16 | filters: stat, wall 17 | maxActive: 20 18 | initialSize: 1 19 | maxWait: 60000 20 | minIdle: 10 21 | timeBetweenEvictionRunsMillis: 60000 22 | minEvictableIdleTimeMillis: 300000 23 | validationQuery: SELECT 1 24 | testWhileIdle: true 25 | testOnBorrow: false 26 | testOnReturn: false 27 | removeAbandoned: true 28 | removeAbandonedTimeout: 1800 29 | logAbandoned: false 30 | -------------------------------------------------------------------------------- /spring-boot-practice-multiple-datasource/src/test/java/com/foo/AccountServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.foo; 2 | 3 | import com.foo.service.AccountBocService; 4 | import com.foo.service.AccountCcbService; 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.math.BigDecimal; 12 | 13 | /** 14 | * @author JasonLin 15 | * @version V1.0 16 | * @date 2017/12/4 17 | */ 18 | @RunWith(SpringRunner.class) 19 | @SpringBootTest 20 | public class AccountServiceTest { 21 | 22 | @Autowired 23 | private AccountCcbService accountCcbService; 24 | 25 | @Autowired 26 | private AccountBocService accountBocService; 27 | 28 | @Test 29 | public void testTransferAccountCcbToBoc() { 30 | accountCcbService.transferAccountToBoc(10001L, new BigDecimal(-100)); 31 | } 32 | 33 | @Test 34 | public void testTransferAccountCcbToBocOnException() { 35 | accountCcbService.transferAccountToBoc(10002L, new BigDecimal(100)); 36 | } 37 | 38 | @Test 39 | public void testUpdateCcbBalance() { 40 | accountCcbService.updateBalance(10001L, new BigDecimal(100)); 41 | } 42 | 43 | @Test 44 | public void testUpdateBocBalance() { 45 | accountBocService.updateBalance(10001L, new BigDecimal(100)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /spring-boot-practice-mybatis/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | spring-boot-practice 7 | com.foo 8 | 1.0.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | spring-boot-practice-mybatis 13 | jar 14 | 15 | spring-boot-practice-mybatis 16 | 17 | 18 | UTF-8 19 | 1.7 20 | 1.7 21 | 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-web 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-test 31 | test 32 | 33 | 34 | mysql 35 | mysql-connector-java 36 | 37 | 38 | org.mybatis.spring.boot 39 | mybatis-spring-boot-starter 40 | 2.1.0 41 | 42 | 43 | com.alibaba 44 | druid-spring-boot-starter 45 | 1.1.18 46 | 47 | 48 | 49 | 50 | spring-boot-practice-mybatis 51 | 52 | 53 | 54 | maven-clean-plugin 55 | 3.1.0 56 | 57 | 58 | 59 | maven-resources-plugin 60 | 3.0.2 61 | 62 | 63 | maven-compiler-plugin 64 | 3.8.0 65 | 66 | 67 | maven-surefire-plugin 68 | 2.22.1 69 | 70 | 71 | maven-war-plugin 72 | 3.2.2 73 | 74 | 75 | maven-install-plugin 76 | 2.5.2 77 | 78 | 79 | maven-deploy-plugin 80 | 2.8.2 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /spring-boot-practice-mybatis/src/main/java/com/foo/MybatisApplicationRunner.java: -------------------------------------------------------------------------------- 1 | package com.foo; 2 | 3 | import com.foo.dao.CityDao; 4 | import com.foo.mapper.CityMapper; 5 | import com.foo.mapper.CountryMapper; 6 | import com.foo.model.Country; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.CommandLineRunner; 9 | import org.springframework.boot.SpringApplication; 10 | import org.springframework.boot.autoconfigure.SpringBootApplication; 11 | 12 | /** 13 | * @author JasonLin 14 | * @version V1.0 15 | * @date 2019/8/20 16 | */ 17 | @SpringBootApplication 18 | public class MybatisApplicationRunner implements CommandLineRunner { 19 | 20 | private final CityMapper cityMapper; 21 | @Autowired 22 | private CityDao cityDao; 23 | @Autowired 24 | private CountryMapper countryMapper; 25 | 26 | public MybatisApplicationRunner(CityMapper cityMapper) { 27 | this.cityMapper = cityMapper; 28 | } 29 | 30 | public static void main(String[] args) { 31 | SpringApplication.run(MybatisApplicationRunner.class, args); 32 | } 33 | 34 | @Override 35 | public void run(String... args) throws Exception { 36 | // System.out.println(this.cityMapper.findByState("成都市")); 37 | // System.out.println(cityDao.selectCityById(1L)); 38 | // System.out.println(countryMapper.findById(20L)); 39 | Country contry = new Country("大国"); 40 | System.out.println(countryMapper.create(contry)); 41 | System.out.println(contry.getId()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /spring-boot-practice-mybatis/src/main/java/com/foo/config/MyBatisConfig.java: -------------------------------------------------------------------------------- 1 | package com.foo.config; 2 | 3 | import org.apache.ibatis.session.SqlSessionFactory; 4 | import org.mybatis.spring.SqlSessionFactoryBean; 5 | import org.mybatis.spring.boot.autoconfigure.SpringBootVFS; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | import javax.sql.DataSource; 11 | 12 | /** 13 | * @author JasonLin 14 | * @version V1.0 15 | * @date 2019/8/20 16 | */ 17 | //@Configuration 18 | public class MyBatisConfig { 19 | 20 | @Autowired 21 | private DataSource dataSource; 22 | 23 | @Bean 24 | public SqlSessionFactory masterSqlSessionFactory() throws Exception { 25 | SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); 26 | factoryBean.setDataSource(dataSource); 27 | factoryBean.setVfs(SpringBootVFS.class); // Sets the SpringBootVFS class into SqlSessionFactoryBean 28 | return factoryBean.getObject(); 29 | } 30 | } -------------------------------------------------------------------------------- /spring-boot-practice-mybatis/src/main/java/com/foo/dao/CityDao.java: -------------------------------------------------------------------------------- 1 | package com.foo.dao; 2 | 3 | import com.foo.model.City; 4 | import org.apache.ibatis.session.SqlSession; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | * @author JasonLin 9 | * @version V1.0 10 | * @date 2019/8/20 11 | */ 12 | @Repository 13 | public class CityDao { 14 | 15 | private final SqlSession sqlSession; 16 | 17 | public CityDao(SqlSession sqlSession) { 18 | this.sqlSession = sqlSession; 19 | } 20 | 21 | public City selectCityById(long id) { 22 | return this.sqlSession.selectOne("selectCityById", id); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /spring-boot-practice-mybatis/src/main/java/com/foo/mapper/CityMapper.java: -------------------------------------------------------------------------------- 1 | package com.foo.mapper; 2 | 3 | import com.foo.model.City; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.apache.ibatis.annotations.Select; 7 | 8 | /** 9 | * @author JasonLin 10 | * @version V1.0 11 | * @date 2019/8/20 12 | */ 13 | @Mapper 14 | public interface CityMapper { 15 | 16 | @Select("SELECT * FROM CITY WHERE NAME = #{state}") 17 | City findByState(@Param("state") String state); 18 | 19 | @Select("SELECT * FROM CITY WHERE ID = #{id}") 20 | City selectCityById(@Param("id") Long id); 21 | 22 | } -------------------------------------------------------------------------------- /spring-boot-practice-mybatis/src/main/java/com/foo/mapper/CountryMapper.java: -------------------------------------------------------------------------------- 1 | package com.foo.mapper; 2 | 3 | import com.foo.model.Country; 4 | import org.apache.ibatis.annotations.Mapper; 5 | 6 | /** 7 | * @author JasonLin 8 | * @version V1.0 9 | * @date 2019/8/20 10 | */ 11 | @Mapper 12 | public interface CountryMapper { 13 | 14 | Country findById(Long id); 15 | 16 | Long create(Country country); 17 | } 18 | -------------------------------------------------------------------------------- /spring-boot-practice-mybatis/src/main/java/com/foo/model/City.java: -------------------------------------------------------------------------------- 1 | package com.foo.model; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author JasonLin 7 | * @version V1.0 8 | * @date 2019/8/20 9 | */ 10 | @Data 11 | public class City { 12 | private Long id; 13 | private String name; 14 | } 15 | -------------------------------------------------------------------------------- /spring-boot-practice-mybatis/src/main/java/com/foo/model/Country.java: -------------------------------------------------------------------------------- 1 | package com.foo.model; 2 | 3 | 4 | import lombok.Data; 5 | 6 | /** 7 | * @author JasonLin 8 | * @version V1.0 9 | * @date 2019/8/20 10 | */ 11 | @Data 12 | public class Country { 13 | private Long id; 14 | private String name; 15 | 16 | public Country(String name) { 17 | this.name = name; 18 | } 19 | public Country() { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /spring-boot-practice-mybatis/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | mybatis: 2 | type-aliases-package: com.foo.model 3 | type-handlers-package: com.foo.typehandler 4 | mapper-locations: classpath:config/mapper/*.xml 5 | configuration: 6 | map-underscore-to-camel-case: true 7 | default-fetch-size: 100 8 | default-statement-timeout: 30 9 | 10 | 11 | spring: 12 | profiles: 13 | active: dev 14 | datasource: 15 | driver-class-name: com.mysql.jdbc.Driver 16 | url: jdbc:mysql://localhost:3306/db1?useSSL=false&requireSSL=false&serverTimezone=GMT%2B8 17 | username: root 18 | password: root 19 | druid: 20 | max-active: 200 21 | min-idle: 1 22 | initialize: false 23 | max-wait: 30000 24 | test-on-borrow: false 25 | test-on-return: false 26 | test-while-idle: true 27 | validation-query: SELECT 1 28 | time-between-eviction-runs-millis: 30000 29 | min-evictable-idle-time-millis: 300000 -------------------------------------------------------------------------------- /spring-boot-practice-mybatis/src/main/resources/config/mapper/CountryMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 11 | 12 | 15 | 16 | 22 | 23 | 24 | 25 | select @@IDENTITY as id 26 | 27 | insert into Country (`name`) values (#{name}) 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /spring-boot-practice-redis/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | spring-boot-practice 7 | com.foo 8 | 1.0.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | spring-boot-practice-redis 13 | war 14 | 15 | spring-boot-practice-redis Maven Webapp 16 | 17 | http://www.example.com 18 | 19 | 20 | UTF-8 21 | 1.7 22 | 1.7 23 | 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-web 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-test 33 | test 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-data-redis 38 | 39 | 40 | io.lettuce 41 | lettuce-core 42 | 43 | 44 | 45 | 46 | org.apache.commons 47 | commons-pool2 48 | 2.6.0 49 | 50 | 51 | redis.clients 52 | jedis 53 | 54 | 55 | 56 | 57 | spring-boot-practice-redis 58 | 59 | 60 | -------------------------------------------------------------------------------- /spring-boot-practice-redis/src/main/java/com/foo/RedisApplicationStarter.java: -------------------------------------------------------------------------------- 1 | package com.foo; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.cache.annotation.EnableCaching; 8 | 9 | /** 10 | * @author JasonLin 11 | * @version V1.0 12 | * @date 2017/11/30 13 | */ 14 | @EnableCaching 15 | @SpringBootApplication 16 | public class RedisApplicationStarter { 17 | 18 | private static final Log LOG = LogFactory.getLog(RedisApplicationStarter.class); 19 | 20 | public static void main(String[] args) { 21 | SpringApplication.run(RedisApplicationStarter.class, args); 22 | LOG.info("spring-boot-practice-redis is started."); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /spring-boot-practice-redis/src/main/java/com/foo/service/RedisCacheService.java: -------------------------------------------------------------------------------- 1 | package com.foo.service; 2 | 3 | import com.google.common.collect.Maps; 4 | import org.apache.commons.logging.Log; 5 | import org.apache.commons.logging.LogFactory; 6 | import org.springframework.cache.annotation.Cacheable; 7 | import org.springframework.stereotype.Service; 8 | 9 | import java.util.Map; 10 | 11 | /** 12 | * @author JasonLin 13 | * @version V1.0 14 | * @date 2019/1/4 15 | */ 16 | @Service 17 | public class RedisCacheService { 18 | 19 | private static final Log LOG = LogFactory.getLog(RedisCacheService.class); 20 | 21 | private static Map DATA_SOURCE = Maps.newHashMap(); 22 | 23 | static { 24 | DATA_SOURCE.put("key1","val1"); 25 | DATA_SOURCE.put("key2","val2"); 26 | DATA_SOURCE.put("key3","val3"); 27 | } 28 | 29 | @Cacheable(cacheNames="spring-chech",key = "#key") 30 | public String getValue(String key){ 31 | String val = DATA_SOURCE.get(key); 32 | LOG.info(val); 33 | return val; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /spring-boot-practice-redis/src/main/java/com/foo/service/RedisService.java: -------------------------------------------------------------------------------- 1 | package com.foo.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.data.redis.core.StringRedisTemplate; 5 | import org.springframework.stereotype.Service; 6 | 7 | /** 8 | * @author JasonLin 9 | * @version V1.0 10 | * @date 2018/12/29 11 | */ 12 | @Service 13 | public class RedisService { 14 | 15 | @Autowired 16 | private StringRedisTemplate stringRedisTemplate; 17 | 18 | public void lpushValues(String key, String... value) { 19 | stringRedisTemplate.opsForList().leftPushAll(key, value); 20 | } 21 | 22 | public void lpush(String key, String value) { 23 | stringRedisTemplate.opsForList().leftPush(key, value); 24 | } 25 | 26 | public void lpop(String key) { 27 | stringRedisTemplate.opsForList().leftPop(key); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /spring-boot-practice-redis/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #redis 2 | #redis基础配置 3 | spring.redis.database=1 4 | spring.redis.host=10.100.12.108 5 | spring.redis.password= 6 | spring.redis.port=6380 7 | spring.redis.timeout=1000 8 | #redis lettuce连接池配置 使用的common-pool2的连接池 9 | #shutdown的超时时间 10 | #spring.redis.lettuce.shutdown-timeout=100ms 11 | #连接池最大活跃连接数 12 | #spring.redis.lettuce.pool.max-active=8 13 | #连接池最大空闲连接数 14 | #spring.redis.lettuce.pool.max-idle=8 15 | #当连接池达到最大连接数时,等待可用的连接的等待时间 16 | #spring.redis.lettuce.pool.max-wait=-1ms 17 | #连接池最小空闲连接数 18 | #spring.redis.lettuce.pool.min-idle=0 19 | #redis集群配置 20 | #spring.redis.cluster.max-redirects= 10 21 | #spring.redis.cluster.nodes= # Comma-separated list of "host:port" pairs to bootstrap from. 22 | #redis jedis连接配置 23 | spring.redis.jedis.pool.max-active=8 24 | spring.redis.jedis.pool.max-idle=8 25 | spring.redis.jedis.pool.max-wait=-1ms 26 | spring.redis.jedis.pool.min-idle=0 27 | #哨兵配置 28 | #spring.redis.sentinel.master= 29 | #spring.redis.sentinel.nodes= 30 | #其它 31 | #spring.redis.ssl=false 32 | #spring.redis.url= 33 | spring.cache.redis.time-to-live=600000 34 | spring.cache.cache-names=spring-chech -------------------------------------------------------------------------------- /spring-boot-practice-redis/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ${log.context.name} 9 | 10 | 11 | 12 | 13 | ${log.pattern} 14 | 15 | 16 | 17 | 18 | 19 | 20 | ${log.pattern} 21 | ${log.charset} 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ../logs/${log.context.name}-%d{yyyy-MM-dd}.%i.log 30 | 31 | 32 | 200MB 33 | 34 | 35 | 36 | 37 | 38 | DEBUG 39 | 40 | 41 | true 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /spring-boot-practice-redis/src/readme.dm: -------------------------------------------------------------------------------- 1 | # spring boot整合redis 2 | ##1. 在pom.xml加入依赖spring-boot-starter-data-redis 3 | ##2. 在配置文件中配置相关参数 4 | ##3. spring boot有两种连接redis的方式一种是:jedis;一种是lettuce 5 | ##4. spring boot默认使用lettuce连接redis 6 | ##5. 如果使用 Jedis 替代 Lettuce 则需要排除lettuce,并引入jedis 7 | ##6. 要使用连接池的时候需要引入commons-pool2 8 | jedis:是Redis的Java实现客户端,提供了比较全面的Redis命令的支持, 9 | lettuce:高级Redis客户端,用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器。 10 | Jedis 在实现上是直接连接 Redis-Server,在多个线程间共享一个 Jedis 实例时是线程不安全的,如果想要在多线程场景下使用 Jedis,需要使用连接池,每个线程都使用自己的 Jedis 实例,当连接数量增多时,会消耗较多的物理资源。 11 | 12 | 与 Jedis 相比,Lettuce 则完全克服了其线程不安全的缺点:Lettuce 是一个可伸缩的线程安全的 Redis 客户端,支持同步、异步和响应式模式。多个线程可以共享一个连接实例,而不必担心多线程并发问题。它基于优秀 Netty NIO 框架构建,支持 Redis 的高级功能,如 Sentinel,集群,流水线,自动重新连接和 Redis 数据模型。 13 | 14 | lettuce既然是线程安全的那为什么也有连接池的配置呢? 15 | lettuce有如下几种情况你不能在线程之间复用连接: 16 | 1. 请求批量下发,即禁止调用命令后立即flush 17 | 2. 使用`BLPOP`这种阻塞命令 18 | 3. 事务操作 19 | 4. 有多个数据库的情况 20 | 21 | 所以LettuceConnectionFactory在使用阻塞命令或者事务操作的时候才会使用到连接池 22 | -------------------------------------------------------------------------------- /spring-boot-practice-redis/src/test/java/com/foo/test/TestRedis.java: -------------------------------------------------------------------------------- 1 | package com.foo.test; 2 | 3 | import com.foo.RedisApplicationStarter; 4 | import com.foo.service.RedisCacheService; 5 | import com.foo.service.RedisService; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | 12 | /** 13 | * @author JasonLin 14 | * @version V1.0 15 | * @date 2018/12/28 16 | */ 17 | 18 | @SpringBootTest(classes = RedisApplicationStarter.class) 19 | @RunWith(SpringRunner.class) 20 | public class TestRedis { 21 | 22 | 23 | @Autowired 24 | RedisService redisServie; 25 | 26 | @Autowired 27 | RedisCacheService redisCacheService; 28 | 29 | @Test 30 | public void lpushValuesTest() { 31 | redisServie.lpushValues("spring-data-redis", "aaa", "fsd", "45646"); 32 | } 33 | 34 | @Test 35 | public void lpopTest() { 36 | redisServie.lpop("spring-data-redis"); 37 | } 38 | 39 | @Test 40 | public void cacheTest() { 41 | redisCacheService.getValue("key2"); 42 | redisCacheService.getValue("key1"); 43 | redisCacheService.getValue("key3"); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /spring-boot-practice-simple/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | spring-boot-practice 5 | com.foo 6 | 1.0.0-SNAPSHOT 7 | 8 | 9 | 4.0.0 10 | spring-boot-practice-simple 11 | war 12 | spring-boot-practice-simple 13 | http://maven.apache.org 14 | 15 | 16 | 17 | 18 | org.springframework.boot 19 | spring-boot-starter-web 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-test 24 | test 25 | 26 | 27 | 28 | spring-boot-practice-simple 29 | 30 | 31 | -------------------------------------------------------------------------------- /spring-boot-practice-simple/readme.txt: -------------------------------------------------------------------------------- 1 | note: 2 | 1、@SpringBootApplication 注解标注应用启动类 3 | 等同于同时标注 @Configuration @EnableAutoConfiguration @ComponentScan 4 | 2、@RestController 返回jason字符串 5 | 3、默认http端口8080 6 | 4、启动类不能直接放在main/java文件夹下,必须放在某一包下 -------------------------------------------------------------------------------- /spring-boot-practice-simple/src/main/java/com/foo/SimpleApplicationStarter.java: -------------------------------------------------------------------------------- 1 | package com.foo; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | 8 | @SpringBootApplication 9 | public class SimpleApplicationStarter { 10 | 11 | private static final Log LOG = LogFactory.getLog(SimpleApplicationStarter.class); 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(SimpleApplicationStarter.class, args); 15 | LOG.info("spring-boot-practice is started."); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /spring-boot-practice-simple/src/main/java/com/foo/controller/HelloWorldController.java: -------------------------------------------------------------------------------- 1 | package com.foo.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | /** 8 | * @author JasonLin 9 | * @version V1.0 10 | * @date 2017/11/30 11 | */ 12 | @RestController 13 | public class HelloWorldController { 14 | 15 | @Value("${message:hello world!}") 16 | private String message; 17 | 18 | @RequestMapping("/") 19 | public String helloWorld(){ 20 | return message; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /spring-boot-practice-simple/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | Archetype Created Web Application 7 | 8 | -------------------------------------------------------------------------------- /spring-boot-practice-simple/src/main/webapp/index.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Hello World!

4 | 5 | 6 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | spring-boot-practice 7 | com.foo 8 | 1.0.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | spring-boot-practice-websocket 13 | war 14 | 15 | spring-boot-practice-websocket 16 | 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-websocket 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-test 27 | test 28 | 29 | 30 | 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-maven-plugin 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/com/foo/websocket/WebSocketTestApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.foo.websocket; 18 | 19 | import org.springframework.boot.SpringApplication; 20 | import org.springframework.boot.autoconfigure.SpringBootApplication; 21 | 22 | /** 23 | * Sample application to demonstrate testing. 24 | * 25 | * @author Phillip Webb 26 | */ 27 | @SpringBootApplication 28 | public class WebSocketTestApplication { 29 | 30 | public static void main(String[] args) { 31 | SpringApplication.run(WebSocketTestApplication.class, args); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/com/foo/websocket/api/SendMessageCtrl.java: -------------------------------------------------------------------------------- 1 | package com.foo.websocket.api; 2 | 3 | import com.foo.websocket.handler.MyHandler; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | import org.springframework.web.socket.TextMessage; 9 | 10 | /** 11 | * @author JasonLin 12 | * @version V1.0 13 | * @date 2019/7/10 14 | */ 15 | @RestController 16 | @Slf4j 17 | public class SendMessageCtrl { 18 | 19 | @Autowired 20 | private MyHandler myHandler; 21 | 22 | @RequestMapping("/send") 23 | public void sendMessage(String message) { 24 | myHandler.sendMessage(new TextMessage(message)); 25 | log.info("send message :" + message); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/com/foo/websocket/config/WebSocketConfig.java: -------------------------------------------------------------------------------- 1 | package com.foo.websocket.config; 2 | 3 | import com.foo.websocket.handler.MyHandler; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.web.socket.WebSocketHandler; 8 | import org.springframework.web.socket.config.annotation.EnableWebSocket; 9 | import org.springframework.web.socket.config.annotation.WebSocketConfigurer; 10 | import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; 11 | import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean; 12 | import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; 13 | 14 | /** 15 | * @author JasonLin 16 | * @version V1.0 17 | * @date 2019/7/10 18 | */ 19 | @Configuration 20 | @EnableWebSocket 21 | public class WebSocketConfig implements WebSocketConfigurer { 22 | 23 | @Autowired 24 | private MyHandler myHandler; 25 | 26 | @Override 27 | public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) { 28 | webSocketHandlerRegistry.addHandler(myHandler, "/myHandler") 29 | .addInterceptors(new HttpSessionHandshakeInterceptor()); 30 | } 31 | 32 | @Bean 33 | public ServletServerContainerFactoryBean createWebSocketContainer() { 34 | ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean(); 35 | container.setMaxTextMessageBufferSize(81920); 36 | container.setMaxBinaryMessageBufferSize(81920); 37 | return container; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/com/foo/websocket/handler/MyHandler.java: -------------------------------------------------------------------------------- 1 | package com.foo.websocket.handler; 2 | 3 | import com.google.common.collect.Lists; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.stereotype.Component; 6 | import org.springframework.util.CollectionUtils; 7 | import org.springframework.web.socket.CloseStatus; 8 | import org.springframework.web.socket.TextMessage; 9 | import org.springframework.web.socket.WebSocketSession; 10 | import org.springframework.web.socket.handler.TextWebSocketHandler; 11 | 12 | import java.io.IOException; 13 | import java.util.List; 14 | import java.util.Map; 15 | import java.util.concurrent.ConcurrentHashMap; 16 | 17 | /** 18 | * @author JasonLin 19 | * @version V1.0 20 | * @date 2019/7/10 21 | */ 22 | @Slf4j 23 | @Component 24 | public class MyHandler extends TextWebSocketHandler { 25 | 26 | private Map sessionMap = new ConcurrentHashMap<>(); 27 | 28 | @Override 29 | public void afterConnectionEstablished(WebSocketSession session) throws Exception { 30 | sessionMap.put(session.getId(), session); 31 | log.info(session.getId() + " established a connection"); 32 | } 33 | 34 | @Override 35 | public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { 36 | sessionMap.remove(session.getId()); 37 | log.info(session.getId() + " closed a connection"); 38 | } 39 | 40 | @Override 41 | public void handleTextMessage(WebSocketSession session, TextMessage message) { 42 | log.info(String.format("receive a message from[%s] message:%s", session.getId(), message.toString())); 43 | } 44 | 45 | public void sendMessage(TextMessage message) { 46 | List closedSessions = Lists.newArrayList(); 47 | for (Map.Entry sessionEntry : sessionMap.entrySet()) { 48 | WebSocketSession session = sessionEntry.getValue(); 49 | if (null != session && session.isOpen()) { 50 | try { 51 | session.sendMessage(message); 52 | } catch (IOException e) { 53 | log.error("websocket send message error, " + e.getMessage(), e); 54 | } 55 | } else { 56 | closedSessions.add(sessionEntry.getKey()); 57 | } 58 | } 59 | if (!CollectionUtils.isEmpty(closedSessions)) { 60 | for (String sessionId : closedSessions) { 61 | sessionMap.remove(sessionId); 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/samples/websocket/tomcat/SampleTomcatWebSocketApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package samples.websocket.tomcat; 18 | 19 | import samples.websocket.tomcat.client.GreetingService; 20 | import samples.websocket.tomcat.client.SimpleGreetingService; 21 | import samples.websocket.tomcat.echo.DefaultEchoService; 22 | import samples.websocket.tomcat.echo.EchoService; 23 | import samples.websocket.tomcat.echo.EchoWebSocketHandler; 24 | import samples.websocket.tomcat.reverse.ReverseWebSocketEndpoint; 25 | import samples.websocket.tomcat.snake.SnakeWebSocketHandler; 26 | 27 | import org.springframework.boot.SpringApplication; 28 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 29 | import org.springframework.boot.builder.SpringApplicationBuilder; 30 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 31 | import org.springframework.context.annotation.Bean; 32 | import org.springframework.context.annotation.Configuration; 33 | import org.springframework.web.socket.WebSocketHandler; 34 | import org.springframework.web.socket.config.annotation.EnableWebSocket; 35 | import org.springframework.web.socket.config.annotation.WebSocketConfigurer; 36 | import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; 37 | import org.springframework.web.socket.handler.PerConnectionWebSocketHandler; 38 | import org.springframework.web.socket.server.standard.ServerEndpointExporter; 39 | 40 | @Configuration 41 | @EnableAutoConfiguration 42 | @EnableWebSocket 43 | public class SampleTomcatWebSocketApplication extends SpringBootServletInitializer 44 | implements WebSocketConfigurer { 45 | 46 | @Override 47 | public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { 48 | registry.addHandler(echoWebSocketHandler(), "/echo").withSockJS(); 49 | registry.addHandler(snakeWebSocketHandler(), "/snake").withSockJS(); 50 | } 51 | 52 | @Override 53 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 54 | return application.sources(SampleTomcatWebSocketApplication.class); 55 | } 56 | 57 | @Bean 58 | public EchoService echoService() { 59 | return new DefaultEchoService("Did you say \"%s\"?"); 60 | } 61 | 62 | @Bean 63 | public GreetingService greetingService() { 64 | return new SimpleGreetingService(); 65 | } 66 | 67 | @Bean 68 | public WebSocketHandler echoWebSocketHandler() { 69 | return new EchoWebSocketHandler(echoService()); 70 | } 71 | 72 | @Bean 73 | public WebSocketHandler snakeWebSocketHandler() { 74 | return new PerConnectionWebSocketHandler(SnakeWebSocketHandler.class); 75 | } 76 | 77 | @Bean 78 | public ReverseWebSocketEndpoint reverseWebSocketEndpoint() { 79 | return new ReverseWebSocketEndpoint(); 80 | } 81 | 82 | @Bean 83 | public ServerEndpointExporter serverEndpointExporter() { 84 | return new ServerEndpointExporter(); 85 | } 86 | 87 | public static void main(String[] args) { 88 | SpringApplication.run(SampleTomcatWebSocketApplication.class, args); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/samples/websocket/tomcat/client/GreetingService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package samples.websocket.tomcat.client; 18 | 19 | public interface GreetingService { 20 | 21 | String getGreeting(); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/samples/websocket/tomcat/client/SimpleClientWebSocketHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package samples.websocket.tomcat.client; 18 | 19 | import java.util.concurrent.CountDownLatch; 20 | import java.util.concurrent.atomic.AtomicReference; 21 | 22 | import org.apache.commons.logging.Log; 23 | import org.apache.commons.logging.LogFactory; 24 | 25 | import org.springframework.web.socket.TextMessage; 26 | import org.springframework.web.socket.WebSocketSession; 27 | import org.springframework.web.socket.handler.TextWebSocketHandler; 28 | 29 | public class SimpleClientWebSocketHandler extends TextWebSocketHandler { 30 | 31 | protected Log logger = LogFactory.getLog(SimpleClientWebSocketHandler.class); 32 | 33 | private final GreetingService greetingService; 34 | 35 | private final CountDownLatch latch; 36 | 37 | private final AtomicReference messagePayload; 38 | 39 | public SimpleClientWebSocketHandler(GreetingService greetingService, 40 | CountDownLatch latch, AtomicReference message) { 41 | this.greetingService = greetingService; 42 | this.latch = latch; 43 | this.messagePayload = message; 44 | } 45 | 46 | @Override 47 | public void afterConnectionEstablished(WebSocketSession session) throws Exception { 48 | TextMessage message = new TextMessage(this.greetingService.getGreeting()); 49 | session.sendMessage(message); 50 | } 51 | 52 | @Override 53 | public void handleTextMessage(WebSocketSession session, TextMessage message) 54 | throws Exception { 55 | this.logger.info("Received: " + message + " (" + this.latch.getCount() + ")"); 56 | session.close(); 57 | this.messagePayload.set(message.getPayload()); 58 | this.latch.countDown(); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/samples/websocket/tomcat/client/SimpleGreetingService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package samples.websocket.tomcat.client; 18 | 19 | public class SimpleGreetingService implements GreetingService { 20 | 21 | @Override 22 | public String getGreeting() { 23 | return "Hello world!"; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/samples/websocket/tomcat/echo/DefaultEchoService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package samples.websocket.tomcat.echo; 18 | 19 | public class DefaultEchoService implements EchoService { 20 | 21 | private final String echoFormat; 22 | 23 | public DefaultEchoService(String echoFormat) { 24 | this.echoFormat = (echoFormat != null) ? echoFormat : "%s"; 25 | } 26 | 27 | @Override 28 | public String getMessage(String message) { 29 | return String.format(this.echoFormat, message); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/samples/websocket/tomcat/echo/EchoService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package samples.websocket.tomcat.echo; 18 | 19 | public interface EchoService { 20 | 21 | String getMessage(String message); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/samples/websocket/tomcat/echo/EchoWebSocketHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package samples.websocket.tomcat.echo; 18 | 19 | import org.apache.commons.logging.Log; 20 | import org.apache.commons.logging.LogFactory; 21 | 22 | import org.springframework.web.socket.CloseStatus; 23 | import org.springframework.web.socket.TextMessage; 24 | import org.springframework.web.socket.WebSocketHandler; 25 | import org.springframework.web.socket.WebSocketSession; 26 | import org.springframework.web.socket.handler.TextWebSocketHandler; 27 | 28 | /** 29 | * Echo messages by implementing a Spring {@link WebSocketHandler} abstraction. 30 | */ 31 | public class EchoWebSocketHandler extends TextWebSocketHandler { 32 | 33 | private static Log logger = LogFactory.getLog(EchoWebSocketHandler.class); 34 | 35 | private final EchoService echoService; 36 | 37 | public EchoWebSocketHandler(EchoService echoService) { 38 | this.echoService = echoService; 39 | } 40 | 41 | @Override 42 | public void afterConnectionEstablished(WebSocketSession session) { 43 | logger.debug("Opened new session in instance " + this); 44 | } 45 | 46 | @Override 47 | public void handleTextMessage(WebSocketSession session, TextMessage message) 48 | throws Exception { 49 | String echoMessage = this.echoService.getMessage(message.getPayload()); 50 | logger.debug(echoMessage); 51 | session.sendMessage(new TextMessage(echoMessage)); 52 | } 53 | 54 | @Override 55 | public void handleTransportError(WebSocketSession session, Throwable exception) 56 | throws Exception { 57 | session.close(CloseStatus.SERVER_ERROR); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/samples/websocket/tomcat/reverse/ReverseWebSocketEndpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package samples.websocket.tomcat.reverse; 18 | 19 | import java.io.IOException; 20 | 21 | import javax.websocket.OnMessage; 22 | import javax.websocket.Session; 23 | import javax.websocket.server.ServerEndpoint; 24 | 25 | @ServerEndpoint("/reverse") 26 | public class ReverseWebSocketEndpoint { 27 | 28 | @OnMessage 29 | public void handleMessage(Session session, String message) throws IOException { 30 | session.getBasicRemote() 31 | .sendText("Reversed: " + new StringBuilder(message).reverse()); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/samples/websocket/tomcat/snake/Direction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package samples.websocket.tomcat.snake; 18 | 19 | public enum Direction { 20 | 21 | NONE, NORTH, SOUTH, EAST, WEST 22 | 23 | } 24 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/samples/websocket/tomcat/snake/Location.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package samples.websocket.tomcat.snake; 18 | 19 | public class Location { 20 | 21 | /** 22 | * The X location. 23 | */ 24 | public int x; 25 | 26 | /** 27 | * The Y location. 28 | */ 29 | public int y; 30 | 31 | public Location(int x, int y) { 32 | this.x = x; 33 | this.y = y; 34 | } 35 | 36 | public Location getAdjacentLocation(Direction direction) { 37 | switch (direction) { 38 | case NORTH: 39 | return new Location(this.x, this.y - SnakeUtils.GRID_SIZE); 40 | case SOUTH: 41 | return new Location(this.x, this.y + SnakeUtils.GRID_SIZE); 42 | case EAST: 43 | return new Location(this.x + SnakeUtils.GRID_SIZE, this.y); 44 | case WEST: 45 | return new Location(this.x - SnakeUtils.GRID_SIZE, this.y); 46 | case NONE: 47 | // fall through 48 | default: 49 | return this; 50 | } 51 | } 52 | 53 | @Override 54 | public boolean equals(Object o) { 55 | if (this == o) { 56 | return true; 57 | } 58 | if (o == null || getClass() != o.getClass()) { 59 | return false; 60 | } 61 | Location location = (Location) o; 62 | if (this.x != location.x) { 63 | return false; 64 | } 65 | if (this.y != location.y) { 66 | return false; 67 | } 68 | return true; 69 | } 70 | 71 | @Override 72 | public int hashCode() { 73 | int result = this.x; 74 | result = 31 * result + this.y; 75 | return result; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/samples/websocket/tomcat/snake/Snake.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package samples.websocket.tomcat.snake; 18 | 19 | import java.util.ArrayDeque; 20 | import java.util.Collection; 21 | import java.util.Deque; 22 | 23 | import org.springframework.web.socket.TextMessage; 24 | import org.springframework.web.socket.WebSocketSession; 25 | 26 | public class Snake { 27 | 28 | private static final int DEFAULT_LENGTH = 5; 29 | 30 | private final Deque tail = new ArrayDeque<>(); 31 | 32 | private final Object monitor = new Object(); 33 | 34 | private final int id; 35 | 36 | private final WebSocketSession session; 37 | 38 | private final String hexColor; 39 | 40 | private Direction direction; 41 | 42 | private int length = DEFAULT_LENGTH; 43 | 44 | private Location head; 45 | 46 | public Snake(int id, WebSocketSession session) { 47 | this.id = id; 48 | this.session = session; 49 | this.hexColor = SnakeUtils.getRandomHexColor(); 50 | resetState(); 51 | } 52 | 53 | private void resetState() { 54 | this.direction = Direction.NONE; 55 | this.head = SnakeUtils.getRandomLocation(); 56 | this.tail.clear(); 57 | this.length = DEFAULT_LENGTH; 58 | } 59 | 60 | private void kill() throws Exception { 61 | synchronized (this.monitor) { 62 | resetState(); 63 | sendMessage("{'type': 'dead'}"); 64 | } 65 | } 66 | 67 | private void reward() throws Exception { 68 | synchronized (this.monitor) { 69 | this.length++; 70 | sendMessage("{'type': 'kill'}"); 71 | } 72 | } 73 | 74 | protected void sendMessage(String msg) throws Exception { 75 | this.session.sendMessage(new TextMessage(msg)); 76 | } 77 | 78 | public void update(Collection snakes) throws Exception { 79 | synchronized (this.monitor) { 80 | Location nextLocation = this.head.getAdjacentLocation(this.direction); 81 | if (nextLocation.x >= SnakeUtils.PLAYFIELD_WIDTH) { 82 | nextLocation.x = 0; 83 | } 84 | if (nextLocation.y >= SnakeUtils.PLAYFIELD_HEIGHT) { 85 | nextLocation.y = 0; 86 | } 87 | if (nextLocation.x < 0) { 88 | nextLocation.x = SnakeUtils.PLAYFIELD_WIDTH; 89 | } 90 | if (nextLocation.y < 0) { 91 | nextLocation.y = SnakeUtils.PLAYFIELD_HEIGHT; 92 | } 93 | if (this.direction != Direction.NONE) { 94 | this.tail.addFirst(this.head); 95 | if (this.tail.size() > this.length) { 96 | this.tail.removeLast(); 97 | } 98 | this.head = nextLocation; 99 | } 100 | 101 | handleCollisions(snakes); 102 | } 103 | } 104 | 105 | private void handleCollisions(Collection snakes) throws Exception { 106 | for (Snake snake : snakes) { 107 | boolean headCollision = this.id != snake.id 108 | && snake.getHead().equals(this.head); 109 | boolean tailCollision = snake.getTail().contains(this.head); 110 | if (headCollision || tailCollision) { 111 | kill(); 112 | if (this.id != snake.id) { 113 | snake.reward(); 114 | } 115 | } 116 | } 117 | } 118 | 119 | public Location getHead() { 120 | synchronized (this.monitor) { 121 | return this.head; 122 | } 123 | } 124 | 125 | public Collection getTail() { 126 | synchronized (this.monitor) { 127 | return this.tail; 128 | } 129 | } 130 | 131 | public void setDirection(Direction direction) { 132 | synchronized (this.monitor) { 133 | this.direction = direction; 134 | } 135 | } 136 | 137 | public String getLocationsJson() { 138 | synchronized (this.monitor) { 139 | StringBuilder sb = new StringBuilder(); 140 | sb.append(String.format("{x: %d, y: %d}", Integer.valueOf(this.head.x), 141 | Integer.valueOf(this.head.y))); 142 | for (Location location : this.tail) { 143 | sb.append(','); 144 | sb.append(String.format("{x: %d, y: %d}", Integer.valueOf(location.x), 145 | Integer.valueOf(location.y))); 146 | } 147 | return String.format("{'id':%d,'body':[%s]}", Integer.valueOf(this.id), 148 | sb.toString()); 149 | } 150 | } 151 | 152 | public int getId() { 153 | return this.id; 154 | } 155 | 156 | public String getHexColor() { 157 | return this.hexColor; 158 | } 159 | 160 | } 161 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/samples/websocket/tomcat/snake/SnakeTimer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package samples.websocket.tomcat.snake; 18 | 19 | import java.util.Collection; 20 | import java.util.Collections; 21 | import java.util.Iterator; 22 | import java.util.Timer; 23 | import java.util.TimerTask; 24 | import java.util.concurrent.ConcurrentHashMap; 25 | import java.util.concurrent.CopyOnWriteArrayList; 26 | 27 | import org.apache.commons.logging.Log; 28 | import org.apache.commons.logging.LogFactory; 29 | 30 | /** 31 | * Sets up the timer for the multi-player snake game WebSocket example. 32 | */ 33 | public final class SnakeTimer { 34 | 35 | private static final long TICK_DELAY = 100; 36 | 37 | private static final Object MONITOR = new Object(); 38 | 39 | private static final Log logger = LogFactory.getLog(SnakeTimer.class); 40 | 41 | private static final ConcurrentHashMap snakes = new ConcurrentHashMap<>(); 42 | 43 | private static Timer gameTimer = null; 44 | 45 | private SnakeTimer() { 46 | } 47 | 48 | public static void addSnake(Snake snake) { 49 | synchronized (MONITOR) { 50 | if (snakes.isEmpty()) { 51 | startTimer(); 52 | } 53 | snakes.put(Integer.valueOf(snake.getId()), snake); 54 | } 55 | } 56 | 57 | public static Collection getSnakes() { 58 | return Collections.unmodifiableCollection(snakes.values()); 59 | } 60 | 61 | public static void removeSnake(Snake snake) { 62 | synchronized (MONITOR) { 63 | snakes.remove(Integer.valueOf(snake.getId())); 64 | if (snakes.isEmpty()) { 65 | stopTimer(); 66 | } 67 | } 68 | } 69 | 70 | public static void tick() throws Exception { 71 | StringBuilder sb = new StringBuilder(); 72 | for (Iterator iterator = SnakeTimer.getSnakes().iterator(); iterator 73 | .hasNext();) { 74 | Snake snake = iterator.next(); 75 | snake.update(SnakeTimer.getSnakes()); 76 | sb.append(snake.getLocationsJson()); 77 | if (iterator.hasNext()) { 78 | sb.append(','); 79 | } 80 | } 81 | broadcast(String.format("{'type': 'update', 'data' : [%s]}", sb.toString())); 82 | } 83 | 84 | public static void broadcast(String message) throws Exception { 85 | Collection snakes = new CopyOnWriteArrayList<>(SnakeTimer.getSnakes()); 86 | for (Snake snake : snakes) { 87 | try { 88 | snake.sendMessage(message); 89 | } 90 | catch (Throwable ex) { 91 | // if Snake#sendMessage fails the client is removed 92 | removeSnake(snake); 93 | } 94 | } 95 | } 96 | 97 | public static void startTimer() { 98 | gameTimer = new Timer(SnakeTimer.class.getSimpleName() + " Timer"); 99 | gameTimer.scheduleAtFixedRate(new TimerTask() { 100 | @Override 101 | public void run() { 102 | try { 103 | tick(); 104 | } 105 | catch (Throwable ex) { 106 | logger.error("Caught to prevent timer from shutting down", ex); 107 | } 108 | } 109 | }, TICK_DELAY, TICK_DELAY); 110 | } 111 | 112 | public static void stopTimer() { 113 | if (gameTimer != null) { 114 | gameTimer.cancel(); 115 | } 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/samples/websocket/tomcat/snake/SnakeUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package samples.websocket.tomcat.snake; 18 | 19 | import java.awt.Color; 20 | import java.util.Random; 21 | 22 | public final class SnakeUtils { 23 | 24 | /** 25 | * The width of the playfield. 26 | */ 27 | public static final int PLAYFIELD_WIDTH = 640; 28 | 29 | /** 30 | * The height of the playfield. 31 | */ 32 | public static final int PLAYFIELD_HEIGHT = 480; 33 | 34 | /** 35 | * The grid size. 36 | */ 37 | public static final int GRID_SIZE = 10; 38 | 39 | private static final Random random = new Random(); 40 | 41 | private SnakeUtils() { 42 | } 43 | 44 | public static String getRandomHexColor() { 45 | float hue = random.nextFloat(); 46 | // sat between 0.1 and 0.3 47 | float saturation = (random.nextInt(2000) + 1000) / 10000f; 48 | float luminance = 0.9f; 49 | Color color = Color.getHSBColor(hue, saturation, luminance); 50 | return '#' + Integer.toHexString((color.getRGB() & 0xffffff) | 0x1000000) 51 | .substring(1); 52 | } 53 | 54 | public static Location getRandomLocation() { 55 | int x = roundByGridSize(random.nextInt(PLAYFIELD_WIDTH)); 56 | int y = roundByGridSize(random.nextInt(PLAYFIELD_HEIGHT)); 57 | return new Location(x, y); 58 | } 59 | 60 | private static int roundByGridSize(int value) { 61 | value = value + (GRID_SIZE / 2); 62 | value = value / GRID_SIZE; 63 | value = value * GRID_SIZE; 64 | return value; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/java/samples/websocket/tomcat/snake/SnakeWebSocketHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package samples.websocket.tomcat.snake; 18 | 19 | import java.awt.Color; 20 | import java.util.Iterator; 21 | import java.util.Random; 22 | import java.util.concurrent.atomic.AtomicInteger; 23 | 24 | import org.springframework.web.socket.CloseStatus; 25 | import org.springframework.web.socket.TextMessage; 26 | import org.springframework.web.socket.WebSocketSession; 27 | import org.springframework.web.socket.handler.TextWebSocketHandler; 28 | 29 | public class SnakeWebSocketHandler extends TextWebSocketHandler { 30 | 31 | private static final AtomicInteger snakeIds = new AtomicInteger(0); 32 | 33 | private static final Random random = new Random(); 34 | 35 | private final int id; 36 | 37 | private Snake snake; 38 | 39 | public static String getRandomHexColor() { 40 | float hue = random.nextFloat(); 41 | // sat between 0.1 and 0.3 42 | float saturation = (random.nextInt(2000) + 1000) / 10000f; 43 | float luminance = 0.9f; 44 | Color color = Color.getHSBColor(hue, saturation, luminance); 45 | return '#' + Integer.toHexString((color.getRGB() & 0xffffff) | 0x1000000) 46 | .substring(1); 47 | } 48 | 49 | public static Location getRandomLocation() { 50 | int x = roundByGridSize(random.nextInt(SnakeUtils.PLAYFIELD_WIDTH)); 51 | int y = roundByGridSize(random.nextInt(SnakeUtils.PLAYFIELD_HEIGHT)); 52 | return new Location(x, y); 53 | } 54 | 55 | private static int roundByGridSize(int value) { 56 | value = value + (SnakeUtils.GRID_SIZE / 2); 57 | value = value / SnakeUtils.GRID_SIZE; 58 | value = value * SnakeUtils.GRID_SIZE; 59 | return value; 60 | } 61 | 62 | public SnakeWebSocketHandler() { 63 | this.id = snakeIds.getAndIncrement(); 64 | } 65 | 66 | @Override 67 | public void afterConnectionEstablished(WebSocketSession session) throws Exception { 68 | this.snake = new Snake(this.id, session); 69 | SnakeTimer.addSnake(this.snake); 70 | StringBuilder sb = new StringBuilder(); 71 | for (Iterator iterator = SnakeTimer.getSnakes().iterator(); iterator 72 | .hasNext();) { 73 | Snake snake = iterator.next(); 74 | sb.append(String.format("{id: %d, color: '%s'}", 75 | Integer.valueOf(snake.getId()), snake.getHexColor())); 76 | if (iterator.hasNext()) { 77 | sb.append(','); 78 | } 79 | } 80 | SnakeTimer 81 | .broadcast(String.format("{'type': 'join','data':[%s]}", sb.toString())); 82 | } 83 | 84 | @Override 85 | protected void handleTextMessage(WebSocketSession session, TextMessage message) 86 | throws Exception { 87 | String payload = message.getPayload(); 88 | if ("west".equals(payload)) { 89 | this.snake.setDirection(Direction.WEST); 90 | } 91 | else if ("north".equals(payload)) { 92 | this.snake.setDirection(Direction.NORTH); 93 | } 94 | else if ("east".equals(payload)) { 95 | this.snake.setDirection(Direction.EAST); 96 | } 97 | else if ("south".equals(payload)) { 98 | this.snake.setDirection(Direction.SOUTH); 99 | } 100 | } 101 | 102 | @Override 103 | public void afterConnectionClosed(WebSocketSession session, CloseStatus status) 104 | throws Exception { 105 | SnakeTimer.removeSnake(this.snake); 106 | SnakeTimer.broadcast( 107 | String.format("{'type': 'leave', 'id': %d}", Integer.valueOf(this.id))); 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/resources/static/echo.html: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | Apache Tomcat WebSocket Examples: Echo 22 | 53 | 54 | 109 | 110 | 111 | 113 |
114 |
115 |
116 | 117 |
118 |
119 | 120 | 121 |
122 |
123 | 124 |
125 |
126 | 127 |
128 |
129 |
130 |
131 |
132 |
133 | 134 | 135 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | Apache Tomcat WebSocket Examples: Index 22 | 23 | 24 | 26 |

Please select the sample you would like to try.

27 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/resources/static/reverse.html: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | WebSocket Examples: Reverse 22 | 53 | 116 | 117 | 118 | 120 |
121 |
122 |
123 | 124 |
125 |
126 | 127 | 128 |
129 |
130 | 131 |
132 |
133 | 134 |
135 |
136 |
137 |
138 |
139 |
140 | 141 | 142 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/resources/static/snake.html: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | 23 | Apache Tomcat WebSocket Examples: Multiplayer Snake 24 | 53 | 54 | 55 | 56 | 58 | 59 |
60 | 61 |
62 |
63 |
64 |
65 | 249 | 250 | 251 | -------------------------------------------------------------------------------- /spring-boot-practice-websocket/src/main/resources/static/websocket.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | My WebSocket 5 | 6 | 7 | 8 | Welcome
9 | 10 |
11 |
12 | 13 | 14 | 66 | -------------------------------------------------------------------------------- /spring-boot-pratice-activemq/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | spring-boot-practice 7 | com.foo 8 | 1.0.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | spring-boot-pratice-activemq 13 | jar 14 | 15 | spring-boot-pratice-activemq 16 | 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-activemq 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-test 27 | test 28 | 29 | 30 | 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-maven-plugin 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /spring-boot-pratice-activemq/src/main/java/com/foo/SampleActiveMQApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.foo; 18 | 19 | import org.springframework.boot.SpringApplication; 20 | import org.springframework.boot.autoconfigure.SpringBootApplication; 21 | import org.springframework.jms.annotation.EnableJms; 22 | import org.springframework.scheduling.annotation.EnableScheduling; 23 | 24 | @SpringBootApplication 25 | //启用jms 26 | @EnableJms 27 | //启用定时调度 28 | @EnableScheduling 29 | public class SampleActiveMQApplication { 30 | 31 | public static void main(String[] args) { 32 | SpringApplication.run(SampleActiveMQApplication.class, args); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /spring-boot-pratice-activemq/src/main/java/com/foo/consumer/Consumer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.foo.consumer; 18 | 19 | import org.springframework.jms.annotation.JmsListener; 20 | import org.springframework.stereotype.Component; 21 | 22 | @Component 23 | public class Consumer { 24 | 25 | @JmsListener(destination = "${test.queue.name}", concurrency = "1-20") 26 | public void receiveQueue(String text) { 27 | try { 28 | Thread.sleep(3000); 29 | } catch (InterruptedException e) { 30 | e.printStackTrace(); 31 | } 32 | System.out.println(Thread.currentThread().getName() + " message:" + text); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /spring-boot-pratice-activemq/src/main/java/com/foo/producer/Producer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.foo.producer; 18 | 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.beans.factory.annotation.Qualifier; 21 | import org.springframework.jms.core.JmsMessagingTemplate; 22 | import org.springframework.scheduling.annotation.Scheduled; 23 | import org.springframework.stereotype.Component; 24 | 25 | import javax.jms.Queue; 26 | 27 | @Component 28 | public class Producer { 29 | 30 | @Autowired 31 | private JmsMessagingTemplate jmsMessagingTemplate; 32 | 33 | @Autowired 34 | private Queue sampleQueue; 35 | 36 | @Scheduled(cron = "0/1 * * * * ?") 37 | public void send() throws Exception { 38 | this.jmsMessagingTemplate.convertAndSend(sampleQueue, "定时消息" + System.currentTimeMillis()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /spring-boot-pratice-activemq/src/main/java/com/foo/queue/QueueConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.foo.queue; 2 | 3 | import org.apache.activemq.command.ActiveMQQueue; 4 | import org.springframework.beans.factory.annotation.Configurable; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | import javax.jms.Queue; 10 | 11 | /** 12 | * @author JasonLin 13 | * @version V1.0 14 | * @date 2019/7/24 15 | */ 16 | @Configuration 17 | public class QueueConfiguration { 18 | 19 | @Value("${test.queue.name}") 20 | private String queueName; 21 | 22 | @Bean 23 | public Queue sampleQueue() { 24 | return new ActiveMQQueue(queueName); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /spring-boot-pratice-activemq/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.activemq.in-memory=false 2 | spring.activemq.broker-url=failover:(tcp://localhost:61616)?jms.useAsyncSend=true 3 | spring.activemq.password=admin 4 | spring.activemq.user=admin 5 | spring.activemq.send-timeout=100ms 6 | #缓存消费者 7 | spring.jms.cache.consumers=true 8 | #设置缓存的大小 9 | spring.jms.cache.session-cache-size=20 10 | #设置消费者的并发数量 11 | #spring.jms.listener.concurrency=20 12 | #设置消费者的最大并发数量 13 | #spring.jms.listener.max-concurrency=40 14 | #设置要反序列化的可信包列表,用于对象消息的安全传递http://activemq.apache.org/objectmessage.html 15 | spring.activemq.packages.trusted="com.foo" 16 | 17 | test.queue.name=sample.queue -------------------------------------------------------------------------------- /spring-boot-reference.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Json-Lin/spring-boot-practice/0d9537406b26d96edd0ede942a240cbca5f69d3c/spring-boot-reference.pdf --------------------------------------------------------------------------------