利用spring boot建立java app
背景
在使用spring框架開發的過程中,隨著功能以及業務邏輯的日益複雜,應用伴隨著大量的XML配置和複雜的bean依賴關係,特別是在使用mvc的時候各種配置檔案錯綜複雜。隨著spring3.0的釋出,spring IO團隊開始放棄使用XML配置檔案,而使用"約定優先配租"的思想來代替。
spring boot 就是在這樣的背景中抽象出來的開發框架。它和sping已經大量的常用第三方庫整合在一起,幾乎可以零配置使用,使開發流程更方便
Hello world
使用傳統的spring mvc,需要配置web.xml, applicationContext.xml,然後打包為war 在tomcat中執行, 而如果使用 spring boot, 一切都變得簡單起來了。
下面使用Maven來建立spring boot 的web app工程
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>gs-spring-boot</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
HelloController
package hello;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/")
public String index() {
return "Greetings from Spring Boot!";
}
}
其中:
- @RestController 表示使用spring mvc 來接收request請求
- @RequestMapping 對映到主頁
- 當請求返回的時候,是純文字,那是因為@RestController是由@Controller 和 @ResponseBody組成
Application
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
System.out.println("Let's inspect the beans provided by Spring Boot:");
}
}
其中:
- @SpringBootApplication 代表了其有四個註解組成: @Configuration, @EnableAutoConfiguration, @EnableWebMvc, @ComponentScan
- 在SpringApplication.run中會去自動啟動tomcat
- run 方法返回上下文, 在這個上下文中可以拿到所有的bean
沒有一行配置程式碼、也沒有web.xml。基於Spring Boot的應用在大多數情況下都不需要我們去顯式地宣告各類配置,而是將最常用的預設配置作為約定,在不宣告的情況下也能適應大多數的開發場景。
總體而言spring boot 是對 java web app 開發的簡化
單元測試
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MockServletContext.class)
@WebAppConfiguration
public class HelloControllerTest {
private MockMvc mvc;
@Before
public void before() throws Exception {
mvc = MockMvcBuilders.standaloneSetup(new HelloController()).build();
}
@After
public void after() throws Exception {
}
/**
*
* Method: index()
*
*/
@Test
public void testIndex() throws Exception {
//TODO: Test goes here...
mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("Greetings from Spring Boot!")));
}
}
建立restfullweb伺服器
接上, 使用srping boot建立web伺服器就非常簡單了, 首先建立一個pojo類
public class Greeting {
private final long id;
private final String content;
}
然後使用control來handle http請求
@RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@RequestMapping("/greeting")
public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) {
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
}
其中:
- @RequestParam 表明了引數要求,如果要必填則設定required=true
- 返回是一個物件,會被自動轉換為json
當我們訪問:
- http://localhost:8080/greeting 時候返回 {"id":1,"content":"Hello, World!"}
- http://localhost:8080/greeting?name=User 時候返回 {"id":2,"content":"Hello, User!"}
資料庫訪問
另一個非常常用的問題。在傳統開發中, 我們需要配置:
- 類路徑上新增資料訪問驅動
- 例項化DataSource物件, 指定url, username, password
- 注入JdbcTemplate物件,如果使用Mybatis,還要配置框架資訊
下面一個例子講述用用spring boot來代替。 資料訪問層我們將使用Spring Data JPA和Hibernate(JPA的實現之一)。
開始之前先介紹兩個概念
spring data
為了簡化程式與資料庫互動的程式碼,spring提供了一個現成的dao層框架,spring家族提供的spring-data適用於關係型資料庫和nosql資料庫 ;
例如 Spring Data JPA, Spring Data Hadoop, Spring Data MongoDB ,Spring Data Solr 等;
具體的可以參考官網:http://projects.spring.io/spring-data/;
他們的共同特點是給我們提供了框架程式碼,spring Data能自動建立實體dao的實現類和自定義查詢,不再需要我們自己去實現了
jpa
JPA全稱為Java永續性API(Java Persistence API),JPA是Java EE 5標準之一,是一個ORM規範,由廠商來實現該規範,目前有hibernate、OpenJPA、TopLink、EclipseJPA等實現
然後我們進入配置環節, 配置很簡單:
一: pom.xml映入 data-jpa 和mysql-connetor
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
二: 配置application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/testor
spring.datasource.username=root
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.password = xxx
# Specify the DBMS
spring.jpa.database = MYSQL
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto = update
# Naming strategy
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
# stripped before adding them to the entity manager)
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
其中, hibernate的ddl-auto=update配置表名,資料庫的表和列會自動建立
寫下實體類:
@Entity
@Table(name="student")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@NotNull
private String name;
private String age;
}
- @Entity,說明被這個註解修飾的類應該與一張資料庫表相對應,表的名稱可以由類名推斷,當然了,也可以明確配置,只要加上@Table(name = "books")即可。需要特別注意,每個Entity類都應該有一個protected訪問級別的無參建構函式,用於給Hibernate提供初始化的入口。
- @Id and @GeneratedValue:@Id註解修飾的屬性應該作為表中的主鍵處理、@GeneratedValue修飾的屬性應該由資料庫自動生成,而不需要明確指定。
- @ManyToOne, @ManyToMany表明具體的資料存放在其他表中,在這個例子裡,書和作者是多對一的關係,書和出版社是多對一的關係,因此book表中的author和publisher相當於資料表中的外來鍵;並且在Publisher中通過@OneToMany(mapped = "publisher")定義一個反向關聯(1——>n),表明book類中的publisher屬性與這裡的books形成對應關係。
- @Repository 用來表示訪問資料庫並運算元據的介面,同時它修飾的介面也可以被component scan機制探測到並註冊為bean,這樣就可以在其他模組中通過@Autowired織入。
dao:
@Repository
public interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
}
詳細的可以看 spring jpa的具體介紹。
最後使用:
@RestController
public class DbController {
@Autowired
private StudentDao dao;
@RequestMapping("/get-student-counts")
@ResponseBody
public String getAllStudents(){
List<Student> students = (List<Student>) dao.findAll();
return String.format("%d", students.size());
}
}
主要一點是: 我在CustomerRepository 實現中每天新增方法:findByLastName, @Autowired 就會一直報錯。