Spring Boot: Claudia Zhou 2018.05.23
Spring Boot: Claudia Zhou 2018.05.23
Claudia Zhou
2018.05.23
Spring
2002
2004
2005
Spring Modules
• Inversion of Control container
• Aspect-oriented programming
• Data access
• Transaction management
• Model-view-controller
• Remote Access framework
• Convention-over-configuration
• Batch processing
• Authentication and authorization
• Remote Management
• Messaging
• Testing
Inversion of Control
vs
Dependency Injection
IoC
Inversion of Control
IoC
Inversion of Control Flow
Martin Fowler
https://martinfowler.com/bliki/In
versionOfControl.html
https://www.martinfowler.com/a
rticles/injection.html
Command Line
#ruby
puts 'What is your name?'
name = gets
process_name(name)
puts 'What is your quest?'
quest = gets
process_quest(quest)
GUI
require 'tk'
root = TkRoot.new()
name_label = TkLabel.new() {text "What is Your Name?"}
name_label.pack
name = TkEntry.new(root).pack
name.bind("FocusOut") {process_name(name)}
quest_label = TkLabel.new() {text "What is Your Quest?"}
quest_label.pack
quest = TkEntry.new(root).pack
quest.bind("FocusOut") {process_quest(quest)}
Tk.mainloop()
Hollywood Principle
Don’t call us, we’ll call you.
Ex. HttpSessionListener
•sessionCreated()
•sessionDestroyed()
Ex. Template Method Pattern
Dependency Injection
import org.springframework.boot.SpringApplication;
import
org.springframework.boot.autoconfigure.SpringBootApplicati
on;
@SpringBootApplication
public class DemoApplication {
DemoApplication
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
logger.info("Hello World!");
}
}
CommandLineRunner
SQL Database
dependencies {
compile('org.springframework.boot:spring-boot-starter')
testCompile('org.springframework.boot:spring-boot-
starter-test')
}
build.gradle
dependencies {
compile('org.springframework.boot:spring-boot-starter-
jdbc')
runtime('mysql:mysql-connector-java')
testCompile('org.springframework.boot:spring-boot-
starter-test')
}
build.gradle
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=test
spring.datasource.password=test
spring.datasource.hikari.maximumPoolSize=1
application.properties
package com.example.demo.dao;
@Repository
public class DemoRepository {
@Autowired
public DemoRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
DemoRepository
@SpringBootApplication
public class DemoApplication implements CommandLineRunner
{
@Autowired
public DemoApplication(DemoRepository demoRepository)
{
this.demoRepository = demoRepository;
}
@Override
public void run(String... args) throws Exception {
logger.info("Hello World!");
this.demoRepository.demo();
}
} DemoApplication
BeanPropertyRowMapper
package com.example.demo.domain;
Partition
@Repository
public class DemoRepository {
DemoRepository
public class Partition {
@Override
public String toString() {
return "Partition{" +
"partitionName='" + partitionName + '\'' +
", start=" + start +
", end=" + end +
'}';
}
}
Partition
package com.example.demo.domain;
Partition
@Repository
public class DemoRepository {
DemoRepository
Lombok
dependencies {
compile('org.springframework.boot:spring-boot-starter-
jdbc')
compile('org.projectlombok:lombok')
runtime('mysql:mysql-connector-java')
testCompile('org.springframework.boot:spring-boot-
starter-test')
}
build.gradle
package com.example.demo.domain;
import lombok.Data;
@Data
public class Partition {
Partition
YAML
spring:
datasource:
url: jdbc:mysql://localhost/test
username: test
password: test
hikari:
maximumPoolSize: 1
application.yaml
Spring Profiles
spring:
profiles:
active: ${NODE_ENV:dev}
datasource:
url: jdbc:mysql://localhost/test
username: test
password: test
hikari:
maximumPoolSize: 1
application.yaml
spring:
datasource:
hikari:
maximumPoolSize: 2
application-staging.yaml
RabbitMQ
dependencies {
compile('org.springframework.boot:spring-boot-starter-
amqp')
compile('com.fasterxml.jackson.core:jackson-databind')
}
build.gradle
package com.example.demo.component;
@Component
public class DemoRabbitSender {
@Autowired
public DemoRabbitSender(AmqpTemplate amqpTemplate) {
this.amqpTemplate = amqpTemplate;
}
this.amqpTemplate.convertAndSend(queueName, p);
}
}
DemoRabbitSender
package com.example.demo.component;
@Component
public class DemoRabbitListener {
@RabbitListener(queues = "demo")
public void processMessage(Partition partition) {
logger.info("received: {}", partition);
}
DemoRabbitListener
package com.example.demo;
@Configuration
public class AppConfig {
/*
@Bean
public SimpleRabbitListenerContainerFactory
rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new
SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setMessageConverter(new Jackson2JsonMessageConverter());
return factory;
}
*/
@Bean
public MessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}
AppConfig
@SpringBootApplication
public class DemoApplication implements CommandLineRunner
{
@Autowired
public DemoApplication(DemoRepository demoRepository,
DemoRabbitSender demoRabbitSender) {
this.demoRepository = demoRepository;
this.demoRabbitSender = demoRabbitSender;
}
@Override
public void run(String... args) throws Exception {
demoRabbitSender.send();
}
}
DemoApplication
Scheduling
import
org.springframework.scheduling.annotation.EnableScheduling;
@Configuration
@EnableScheduling
public class AppConfig {
}
AppConfig
@SpringBootApplication
public class DemoApplication implements CommandLineRunner
{
@Override
public void run(String... args) throws Exception {
}
@Scheduled(fixedRate = 1000)
public void sendToRabbit() {
this.demoRabbitSender.send();
}
}
DemoApplication
Async
@Configuration
@EnableAsync
@EnableScheduling
public class AppConfig {
@Bean
public ThreadPoolTaskExecutor asyncExecutor() {
ThreadPoolTaskExecutor executor = new
ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setThreadNamePrefix("async-");
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
}
AppConfig
@Component
public class DemoRabbitSender {
@Async
public void asyncSend() {
logger.info("asyncSendToRabbit()");
send();
}
}
DemoRabbitSender
@SpringBootApplication
public class DemoApplication implements CommandLineRunner
{
@Override
public void run(String... args) throws Exception {
this.demoRabbitSender.asyncSend();
this.demoRabbitSender.asyncSend();
this.demoRabbitSender.asyncSend();
}
}
DemoApplication
Redis
dependencies {
compile('org.springframework.boot:spring-boot-starter-
data-redis')
}
build.gradle
@Repository
public class DemoRedisRepository {
@Autowired
public DemoRedisRepository(StringRedisTemplate template) {
this.template = template;
}
DemoRedisRepository
@SpringBootApplication
public class DemoApplication implements CommandLineRunner
{
@Override
public void run(String... args) throws Exception {
this.demoRedisRepository.demo();
}
}
DemoApplication
MongoDB
dependencies {
compile('org.springframework.boot:spring-boot-starter-
data-mongodb')
}
build.gradle
spring:
data:
mongodb:
uri: mongodb://localhost/test
application.yaml
@Repository
public class DemoMongoRepository {
@Autowired
public DemoMongoRepository(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
DemoMongoRepository
Multiple Datasources
demo2:
datasource:
url: jdbc:mysql://localhost/test
username: test
password: test
hikari:
maximumPoolSize: 1
application.yaml
@Configuration
public class DbConfig {
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "demo2DataSource")
@ConfigurationProperties(prefix = "demo2.datasource")
public DataSource demo2DataSource() {
return DataSourceBuilder.create().build();
}
}
DbConfig
@Repository
public class Demo2Repository {
private NamedParameterJdbcTemplate
namedParameterJdbcTemplate;
@Autowired
public void setDataSource(@Qualifier("demo2DataSource")
DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.namedParameterJdbcTemplate = new
NamedParameterJdbcTemplate(dataSource);
}
}
Demo2MongoRepository
ORM - Hibernate-JPA
• Generate entity from table
• Generate table from entity
• Auto-implemented CRUD
Unit Test
RESTful API &
Microservice
WebSocket
AWS
Actuator
Sample & References
• https://github.com/jiayun/spring-boot-
sample
• https://docs.spring.io/spring-
boot/docs/current/reference/
• https://docs.spring.io/spring/docs/current/s
pring-framework-reference/
Thanks