- What is Spring Boot
- Radically faster getting started experience
- "Opinionated" approach to configuration / defaults
- Gets out of the way quickly
3. What does it involve?
- Easier dependency management
- Automatic configuration / reasonable defaults
- Different build / deployment options.
- What Spring Boot is NOT
- Plugins for IDEs
- Use Boot with any IDE(or none at all)
2. Code generation
___________________________________________________________________________
Demonstration - Spring Boot
Create a new, bare-bones Spring application
eclipse
Help -> eclipse marketplace -> spring ide search -> Spring Tools 4 (aka Spring Tool suite 4) 4.6.0. RELEASE -> install -> restart
Project Explorer right click -> new -> other -> Spring Boot -> Spring Starter Project
name: microserviceBoot, java Version 8 -> next -> next
"Tomcat version 8.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 and 6 WEb modules"
project foloer .settings>org.eclipse.wst.common.project.facet.core.xm
____________________________________________________________________________
- Spring Boot - What just Happened?
- Boilerplate project structure created
- "Application" class + test
- Maven POM (or Gradle if desired)
2. Dependency Management
- Running Spring Boot-What Just Happened?
- SpringApplication
2. @SpringBootApplication
- Combination of @Configuration
i) Marks a configuration file
ii) Java equivalent of file
- ...And @ComponentScan
i) Looks for @Componenrts (none at the moment)
- ...And @EnableAutoConfiguration
i) Master runtime switch for Spring Boot
ii) Examines ApplicationContext & classpath
iii) Creates missing beans based on intelligent defaults
____________________________________________________________________________________
Demonstration - Adding Web Capability
- Adding spring-boot-starter-web dependency
- Adding HelloController
pom.xml
spring-boot-starter => spring-boot-starter-web
com.example.demo package
create classes => WhateverIWant
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class WhateverIWant {
@RequestMapping("/hi")
public @ResponseBody String hiThere()
{
return "hello world!";
}
}
Run As -> Spring Boot App
____________________________________________________________________________________
- Adding Web - What Just Happened?
- spring-boot-starter-web Dependency
- Adds spring-web, spring-mvc jars
- Adds embedded Tomcat jars
2. When application starts...
- Your beans are created
- @EnableAutoConfiguration looks for 'missing' beans
i) Based on your beans + classpath
ii) Notices @Controller / Spring MVC jars
- Automatically creates MVC beans
i) DispatcherServlet, HandlerMappings, Adapters, ViewResolvers
- Launches embedded Tomcat instance.
- But wait, I want a WAR...
- To Convert from JAR to WAR:
- Extend SpringBootServletInitializer
2. Deploy to app server
- URL becomes http://localhost:8080//
_______________________________________________________________________________________
Demonstration - WAR Deployment
-WAR Packaging
-SpringBootServletInitializer
pom.xml
element
jar -> war
or addwar
MicroservicesBootApplication.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public class MicroservicesBootApplication extends SpringBootServletInitializer{
/**
* Used when run as a JAR
* @param args
*/
public static void main(String[] args) {
SpringApplication.run(MicroservicesBootApplication.class, args);
}
/**
* Used when run as a WAR
*/
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(MicroservicesBootApplication.class);
}
}
________________________________________________________________________________________
Demonstration - WAR Deployment
-WAR Packaging
-SpringBootServletInitializer
pom.xml
jar -> war
or add
MicroservicesBootApplication.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public class MicroservicesBootApplication extends SpringBootServletInitializer{
/**
* Used when run as a JAR
* @param args
*/
public static void main(String[] args) {
SpringApplication.run(MicroservicesBootApplication.class, args);
}
/**
* Used when run as a WAR
*/
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(MicroservicesBootApplication.class);
}
}
________________________________________________________________________________________
- What about Web Pages?
- Spring MVC supports a wide range of view options
- Easy to use JSP, Freemarker, Velocity, Thymeleaf
- Boot automatically establishes defaults
- ThymeleafViewResolver
i) If Thymeleaf is on the classpath
4. spring-boot-starter-thymeleaf
___________________________________________________________________________________________
Demonstration - Thymeleaf web pages
- spring-boot-starter-thymeleaf
- /templates folder
- Controller adjustments
- Web page
pom.xml
add
search google => spring boot reference
spring Boot Reference Guide
spring-boot-starter-thymeleaf
resource add Folder
name: templates
add hello.html
Hello name-goes-heae from a Thymeleaf page
WhateverIWant.java
@RequestMapping("/hi/{name}")
public String hiThere(Map model, @PathVariable String name)
{
model.put("name", name);
return "hello";
}
____________________________________________________________________________________________
- What Just Happended?
- spring-boot-starter-theymeleaf
- Automatically configured ThymeleafViewResolver
2. Controller returned a 'logical view name'
3. View Resolver found a matching template
4. Render
- But wait, I want JSPs...
- Thymeleaf and other templating approaches are way too advanced for my organization!
2. No Problem!
3. Just as easy to use JSPs!
- Place JSPs in desired web-relative location
- Set spring.mvc,view.prefix / spring.mvc.view.suffix as needed.
- (remove thymeleaf starter pom)
- (remove thymeleaf starter pom)
______________________________________________________________________________________________
Demonstration - JSP Web Pages
- Place JSP in desired folder
- Set spring.mvc.view.prefix / spring.mvc.view.suffix
- Exclude spring-boot-starter-tomcat
Project Explorer
src -> main -> webapp -> create folder -> WEB-INF -> views -> hello.jsp
Hello ${name} from a JSP page
Demonstration - JSP Web Pages
- Place JSP in desired folder
- Set spring.mvc.view.prefix / spring.mvc.view.suffix
- Exclude spring-boot-starter-tomcat
Project Explorer
src -> main -> webapp -> create folder -> WEB-INF -> views -> hello.jsp
Hello ${name} from a JSP page
src/main/resources/appcliaction.properties
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
_______________________________________________________________________________________________
- What Just Happened?
- No ThymeleafViewRresolver configured
- Controller returned a 'logical view name'
- InternalResourceViewResolver forwarded to JSP
- Render
- Spring & REST
- REST capability is built in to Spring MVC
- Mark with @RequestBody / @ResponseBody
- Spring MVC automatically handles XML/JSON conversion
*Based on converters available in classpath.
___________________________________________________________________________________________
DemonStration - REST Controllers in Spring MVC
- Additional domain objects
- Automatic HTTP Message Conversion
package com.example.demo.domain;
public class Player {
String name;
String position;
public Player() {
super();
}
public Player(String name, String position) {
this();
this.name = name;
this.position = position;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
}
package com.example.demo.domain;
import java.util.Set;
public class Team {
String name;
String location;
String mascotte;
Set players;
public Team() {
super();
}
public Team(String location, String name, Set players) {
this();
this.location = location;
this.name = name;
this.players = players;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getMascotte() {
return mascotte;
}
public void setMascotte(String mascotte) {
this.mascotte = mascotte;
}
public Set getPlayers() {
return players;
}
public void setPlayers(Set players) {
this.players = players;
}
}
package com.example.demo;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.example.demo.domain.Player;
import com.example.demo.domain.Team;
@Controller
public class WhateverIWant {
private Team team;
@PostConstruct
public void init()
{
Set players = new HashSet<>();
players.add(new Player("Charlien Brown", "pitcher"));
players.add(new Player("Snoopy", "shortstop"));
team = new Team("California", "Peanuts", players);
}
@RequestMapping("/hi")
public @ResponseBody Team hiThere()
{
return team;
}
}
What Just Happened?
1. Controller returned a domain object
- Not a logical view name (page)
2. Spring MVC noticed @ResponseBody
- Or @RestController
3. Invoked correct HttpMessageConverter
- Based on
* Requested format
* JARS on classpath
What if I want XML?
1. No Problem!
2. Annotate domain classes with JAXB annotations
- JAXB already part of java SE
3. When App Starts
- Spring creates HttpMessageConverter fo JAXB
* Based on classpath contents
4. XML or JSON returned
- based on requested format
@XmlRootElement => xml out
Accept: application/xml
Accept: application/json
Adding JPA Capability
1. Adding the spring-boot-starter-data-jps Dependency
- Adds Spring JDBC/ Transaction Management
- Adds Spring ORM
- Adds Hibernate / entity manager
- Adds Spring Data JPA subproject
* (explained later)
2. Does NOT add a Database Driver
- Add one manually (HSQL)
Spring Data JPA
1. Typical web application architecture
2. REST Controllers provide CRUD interface to clients
3. DAO provide CRUD interface to DB
Spring Data - Instant Repositories
1. Spring Data provides dynamic repositories
2. You provide the interface, Spring Data dynamically implements.
- JPA, MongoDB, GemFire, etc.
3. Service Layer / Controllers have almost no logic.
_____________________________________________________________________________________________
Demonstraion - Adding Spring Data JPA
- spring-boot-starter-data-jpa
- org.hsqldb / hsqldb
- Annotate domain objects with JPA
- Extend CrudRepository
pom.xml
org.springframework.boot
spring-boot-starter-data-jpa
Accept: application/json
Adding JPA Capability
1. Adding the spring-boot-starter-data-jps Dependency
- Adds Spring JDBC/ Transaction Management
- Adds Spring ORM
- Adds Hibernate / entity manager
- Adds Spring Data JPA subproject
* (explained later)
2. Does NOT add a Database Driver
- Add one manually (HSQL)
Spring Data JPA
1. Typical web application architecture
2. REST Controllers provide CRUD interface to clients
3. DAO provide CRUD interface to DB
Spring Data - Instant Repositories
1. Spring Data provides dynamic repositories
2. You provide the interface, Spring Data dynamically implements.
- JPA, MongoDB, GemFire, etc.
3. Service Layer / Controllers have almost no logic.
_____________________________________________________________________________________________
Demonstraion - Adding Spring Data JPA
- spring-boot-starter-data-jpa
- org.hsqldb / hsqldb
- Annotate domain objects with JPA
- Extend CrudRepository
pom.xml
package com.example.demo.domain;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Player {
@Id @GeneratedValue
Long id;
String name;
String position;
public Player() {
super();
}
public Player(String name, String position) {
this();
this.name = name;
this.position = position;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
}
package com.example.demo.domain;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
@Entity
public class Team {
@Id @GeneratedValue
Long id;
String name;
String location;
String mascotte;
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="teamId")
Set players;
public Team() {
super();
}
public Team(String location, String name, Set players) {
this();
this.location = location;
this.name = name;
this.players = players;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getMascotte() {
return mascotte;
}
public void setMascotte(String mascotte) {
this.mascotte = mascotte;
}
public Set getPlayers() {
return players;
}
public void setPlayers(Set players) {
this.players = players;
}
}
package com.example.demo.dao;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import com.example.demo.domain.Team;
public interface TeamDao extends CrudRepository {
List findAll();
Team findByName(String name);
}
package com.example.demo;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import com.example.demo.dao.TeamDao;
import com.example.demo.domain.Player;
import com.example.demo.domain.Team;
@SpringBootApplication
public class MicroservicesBootApplication extends SpringBootServletInitializer{
/**
* Used when run as a JAR
* @param args
*/
public static void main(String[] args) {
SpringApplication.run(MicroservicesBootApplication.class, args);
}
/**
* Used when run as a WAR
*/
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(MicroservicesBootApplication.class);
}
@PostConstruct
public void init()
{
Set players = new HashSet<>();
players.add(new Player("Charlien Brown", "pitcher"));
players.add(new Player("Snoopy", "shortstop"));
Team team = new Team("California", "Peanuts", players);
teamDao.save(team);
}
@Autowired TeamDao teamDao;
}
package com.example.demo;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.dao.TeamDao;
import com.example.demo.domain.Player;
import com.example.demo.domain.Team;
@RestController
public class WhateverIWant {
@Autowired TeamDao teamDao;
@RequestMapping("/teams/{name}")
public Team hiThere(@PathVariable String name)
{
return teamDao.findByName(name);
}
}
Adding Spring Data JPA - What Just Happened?
1. What I did:
- Added dependencies for spring-boot-starter-data-jpa and hsqldb
- Annotated Domain objects with plain JPA annotations
- Added an interface for Spring Data JPA
- Dependency injected info controller
2. When application starts...
- Spring Data dynamically implements repositories
* find*(), delete(), save() methods implemented.
- DataSource, Transaction Management, all handled.
Spring Data - REST
1. Often, applicatons simply expose DAO methods as REST resources
2. String Data REST handles this automatically...
Adding Spring Data REST
1. Plugs into dynamic repositories
2. Generates RRESTful interface
- GET, PUT, POST, DELETE
3. Code needed only to override defaults.
__________________________________________________________________________________________
__________________________________________________________________________________________
Adding Spring Data REST - What Just Happened?
1. when applicaton starts...
- @RestResource annotations interpreted
- @Controllers beans created
- @RequestMappings created
Adding HATEOAS
1. Spring Data Rest simply returns RESTful resources
- Conversion handled by Jackson, or JAXB
2. Underlying Data Relationships used to build Links
- If matching repositories exist
3. Consider the Team -> Player relationship
4. Player Repository needed to force link creation
__________________________________________________________________________________________
Demonstration - Adding HATEOAS Links
- Creating a Player DAO
package com.example.demo.domain;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Player {
@Id @GeneratedValue
Long id;
String name;
String position;
public Player() {
super();
}
public Player(String name, String position) {
this();
this.name = name;
this.position = position;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
}
HATEOAS - What Just Happened?
1. Spring Data REST noticed two repositories
- The relationship between entities is know via JPA annotations.
2. Spring automatically represents the children as links
- @RestResource determines names of links
Summary
1. Spring Boot makes it easy to start projects
- And easy to add featrure sets to projects
- Opinionated apporach
- Run as JAR or WAR
- Web Applications (JSP, Thymeleaf, others)
2. REST
- Automatic resource conversion
3. Spring Data JPA
- Automatic repository implementation
4. Spring Data REST
- Automatic REST controllers
댓글 없음:
댓글 쓰기