Spring Boot
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
[Link]
[Link]
[Link]
rticles/[Link]
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 = [Link]()
name_label = [Link]() {text "What is Your Name?"}
name_label.pack
name = [Link](root).pack
[Link]("FocusOut") {process_name(name)}
quest_label = [Link]() {text "What is Your Quest?"}
quest_label.pack
quest = [Link](root).pack
[Link]("FocusOut") {process_quest(quest)}
[Link]()
Hollywood Principle
Don’t call us, we’ll call you.
Ex. HttpSessionListener
•sessionCreated()
•sessionDestroyed()
Ex. Template Method Pattern
Dependency Injection
One Form of IoC
Spring Stereotype
•@Component
•@Repository
•@Service
•@Controller
Spring @Autowired
Productivity of
Java Programmers
•50% Spring
•50% IDE
Boot
Boot Methods
1. Web [Link]
2. IDE
3. CLI (command line)
[Link]@claudiazhou:~/projects$ brew tap pivotal/tap
==> Tapping pivotal/tap
Cloning into '/usr/local/Homebrew/Library/Taps/pivotal/homebrew-tap'...
remote: Counting objects: 15, done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 15 (delta 0), reused 5 (delta 0), pack-reused 0
Unpacking objects: 100% (15/15), done.
Tapped 10 formulae (50 files, 36.6KB)
[Link]@claudiazhou:~/projects$ brew install springboot
Updating Homebrew...
==> Installing springboot from pivotal/tap
==> Downloading [Link]
######################################################################## 100.0%
==> Caveats
Bash completion has been installed to:
/usr/local/etc/bash_completion.d
zsh completions have been installed to:
/usr/local/share/zsh/site-functions
==> Summary
🍺 /usr/local/Cellar/springboot/[Link]: 7 files, 9.8MB, built in 5 seconds
[Link]@claudiazhou:~/projects$ spring init --dependencies=web,data-jpa my-
project
Using service at [Link]
Project extracted to '/Users/[Link]/projects/my-project'
First Project
package [Link];
import [Link];
import
[Link]
on;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
[Link]([Link], args);
}
}
DemoApplication
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
private static final Logger logger =
[Link]([Link]);
public static void main(String[] args) {
[Link]([Link], args);
}
@Override
public void run(String... args) throws Exception {
[Link]("Hello World!");
}
}
CommandLineRunner
SQL Database
dependencies {
compile('[Link]:spring-boot-starter')
testCompile('[Link]:spring-boot-
starter-test')
}
[Link]
dependencies {
compile('[Link]:spring-boot-starter-
jdbc')
runtime('mysql:mysql-connector-java')
testCompile('[Link]:spring-boot-
starter-test')
}
[Link]
[Link]=jdbc:mysql://localhost/test
[Link]=test
[Link]=test
[Link]=1
[Link]
package [Link];
@Repository
public class DemoRepository {
private static final Logger logger =
[Link]([Link]);
private final JdbcTemplate jdbcTemplate;
@Autowired
public DemoRepository(JdbcTemplate jdbcTemplate) {
[Link] = jdbcTemplate;
}
public void demo() {
List<Map<String, Object>> list =
[Link]("select
PARTITION_NAME, START, END from `partition`;");
[Link]("partitions: {}", list);
}
}
DemoRepository
@SpringBootApplication
public class DemoApplication implements CommandLineRunner
{
private final DemoRepository demoRepository;
@Autowired
public DemoApplication(DemoRepository demoRepository)
{
[Link] = demoRepository;
}
@Override
public void run(String... args) throws Exception {
[Link]("Hello World!");
[Link]();
}
} DemoApplication
BeanPropertyRowMapper
package [Link];
public class Partition {
private String partitionName;
private Long start;
private Long end;
public String getPartitionName() {
return partitionName;
}
public void setPartitionName(String partitionName) {
[Link] = partitionName;
}
public Long getStart() {
return start;
}
public void setStart(Long start) {
[Link] = start;
}
public Long getEnd() {
return end;
}
public void setEnd(Long end) {
[Link] = end;
}
}
Partition
@Repository
public class DemoRepository {
private RowMapper<Partition> rowMapper = new
BeanPropertyRowMapper<>([Link]);
public void demo2() {
List<Partition> list =
[Link]("select
PARTITION_NAME, START, END from `partition`;", rowMapper);
[Link]("partitions: {}", list);
}
}
DemoRepository
public class Partition {
@Override
public String toString() {
return "Partition{" +
"partitionName='" + partitionName + '\'' +
", start=" + start +
", end=" + end +
'}';
}
}
Partition
package [Link];
public class Partition {
private String name;
private Long start;
private Long end;
// 省略 getter, setter, toString
}
Partition
@Repository
public class DemoRepository {
public void demo2() {
List<Partition> list =
[Link]("select
PARTITION_NAME as name, START, END from `partition`;",
rowMapper);
[Link]("partitions: {}", list);
}
}
DemoRepository
Lombok
dependencies {
compile('[Link]:spring-boot-starter-
jdbc')
compile('[Link]:lombok')
runtime('mysql:mysql-connector-java')
testCompile('[Link]:spring-boot-
starter-test')
}
[Link]
package [Link];
import [Link];
@Data
public class Partition {
private String name;
private Long start;
private Long end;
}
Partition
YAML
spring:
datasource:
url: jdbc:mysql://localhost/test
username: test
password: test
hikari:
maximumPoolSize: 1
[Link]
Spring Profiles
spring:
profiles:
active: ${NODE_ENV:dev}
datasource:
url: jdbc:mysql://localhost/test
username: test
password: test
hikari:
maximumPoolSize: 1
[Link]
spring:
datasource:
hikari:
maximumPoolSize: 2
[Link]
RabbitMQ
dependencies {
compile('[Link]:spring-boot-starter-
amqp')
compile('[Link]:jackson-databind')
}
[Link]
package [Link];
@Component
public class DemoRabbitSender {
private static final String queueName = "demo";
private final AmqpTemplate amqpTemplate;
@Autowired
public DemoRabbitSender(AmqpTemplate amqpTemplate) {
[Link] = amqpTemplate;
}
public void send() {
Partition p = new Partition();
[Link]("demo");
[Link](11111L);
[Link](99999L);
[Link](queueName, p);
}
}
DemoRabbitSender
package [Link];
@Component
public class DemoRabbitListener {
private static final Logger logger =
[Link]([Link]);
@RabbitListener(queues = "demo")
public void processMessage(Partition partition) {
[Link]("received: {}", partition);
}
DemoRabbitListener
package [Link];
@Configuration
public class AppConfig {
/*
@Bean
public SimpleRabbitListenerContainerFactory
rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new
SimpleRabbitListenerContainerFactory();
[Link](connectionFactory);
[Link](new Jackson2JsonMessageConverter());
return factory;
}
*/
@Bean
public MessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}
AppConfig
@SpringBootApplication
public class DemoApplication implements CommandLineRunner
{
private final DemoRabbitSender demoRabbitSender;
@Autowired
public DemoApplication(DemoRepository demoRepository,
DemoRabbitSender demoRabbitSender) {
[Link] = demoRepository;
[Link] = demoRabbitSender;
}
@Override
public void run(String... args) throws Exception {
[Link]();
}
}
DemoApplication
Scheduling
import
[Link];
@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() {
[Link]();
}
}
DemoApplication
Async
@Configuration
@EnableAsync
@EnableScheduling
public class AppConfig {
@Bean
public ThreadPoolTaskExecutor asyncExecutor() {
ThreadPoolTaskExecutor executor = new
ThreadPoolTaskExecutor();
[Link](5);
[Link]("async-");
[Link](true);
return executor;
}
}
AppConfig
@Component
public class DemoRabbitSender {
@Async
public void asyncSend() {
[Link]("asyncSendToRabbit()");
send();
}
}
DemoRabbitSender
@SpringBootApplication
public class DemoApplication implements CommandLineRunner
{
@Override
public void run(String... args) throws Exception {
[Link]();
[Link]();
[Link]();
}
}
DemoApplication
Redis
dependencies {
compile('[Link]:spring-boot-starter-
data-redis')
}
[Link]
@Repository
public class DemoRedisRepository {
private static final Logger logger =
[Link]([Link]);
private StringRedisTemplate template;
@Autowired
public DemoRedisRepository(StringRedisTemplate template) {
[Link] = template;
}
public void demo() {
Long size = [Link]().size("demoList");
[Link]("demoList size: {}", size);
String value = [Link]().index("demoList",
0);
[Link]("demoList[0]: {}", value);
}
}
DemoRedisRepository
@SpringBootApplication
public class DemoApplication implements CommandLineRunner
{
@Override
public void run(String... args) throws Exception {
[Link]();
}
}
DemoApplication
MongoDB
dependencies {
compile('[Link]:spring-boot-starter-
data-mongodb')
}
[Link]
spring:
data:
mongodb:
uri: mongodb://localhost/test
[Link]
@Repository
public class DemoMongoRepository {
private static final Logger logger =
[Link]([Link]);
private static final String COLLECTION = "demo";
private final MongoTemplate mongoTemplate;
@Autowired
public DemoMongoRepository(MongoTemplate mongoTemplate) {
[Link] = mongoTemplate;
}
public void demo() {
List<HashMap> data = [Link](new Query(),
[Link], COLLECTION);
[Link]("mongo data: {}", data);
}
}
DemoMongoRepository
Multiple Datasources
demo2:
datasource:
url: jdbc:mysql://localhost/test
username: test
password: test
hikari:
maximumPoolSize: 1
[Link]
@Configuration
public class DbConfig {
@Bean
@Primary
@ConfigurationProperties(prefix = "[Link]")
public DataSource primaryDataSource() {
return [Link]().build();
}
@Bean(name = "demo2DataSource")
@ConfigurationProperties(prefix = "[Link]")
public DataSource demo2DataSource() {
return [Link]().build();
}
}
DbConfig
@Repository
public class Demo2Repository {
private JdbcTemplate jdbcTemplate;
private NamedParameterJdbcTemplate
namedParameterJdbcTemplate;
@Autowired
public void setDataSource(@Qualifier("demo2DataSource")
DataSource dataSource) {
[Link] = new JdbcTemplate(dataSource);
[Link] = 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
• [Link]
sample
• [Link]
boot/docs/current/reference/
• [Link]
pring-framework-reference/
Thanks