利用spring boot建立java app

sld666666發表於2016-04-27

利用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!";
    }
}

其中:

  1. @RestController 表示使用spring mvc 來接收request請求
  2. @RequestMapping 對映到主頁
  3. 當請求返回的時候,是純文字,那是因為@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:");
    }

}

其中:

  1. @SpringBootApplication 代表了其有四個註解組成: @Configuration, @EnableAutoConfiguration, @EnableWebMvc, @ComponentScan
  2. 在SpringApplication.run中會去自動啟動tomcat
  3. 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));
    }

}

其中:

  1. @RequestParam 表明了引數要求,如果要必填則設定required=true
  2. 返回是一個物件,會被自動轉換為json

當我們訪問:

  1. http://localhost:8080/greeting 時候返回 {"id":1,"content":"Hello, World!"}
  2. http://localhost:8080/greeting?name=User 時候返回 {"id":2,"content":"Hello, User!"}

資料庫訪問

另一個非常常用的問題。在傳統開發中, 我們需要配置:

  1. 類路徑上新增資料訪問驅動
  2. 例項化DataSource物件, 指定url, username, password
  3. 注入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;
}
  1. @Entity,說明被這個註解修飾的類應該與一張資料庫表相對應,表的名稱可以由類名推斷,當然了,也可以明確配置,只要加上@Table(name = "books")即可。需要特別注意,每個Entity類都應該有一個protected訪問級別的無參建構函式,用於給Hibernate提供初始化的入口。
  2. @Id and @GeneratedValue:@Id註解修飾的屬性應該作為表中的主鍵處理、@GeneratedValue修飾的屬性應該由資料庫自動生成,而不需要明確指定。
  3. @ManyToOne, @ManyToMany表明具體的資料存放在其他表中,在這個例子裡,書和作者是多對一的關係,書和出版社是多對一的關係,因此book表中的author和publisher相當於資料表中的外來鍵;並且在Publisher中通過@OneToMany(mapped = "publisher")定義一個反向關聯(1——>n),表明book類中的publisher屬性與這裡的books形成對應關係。
  4. @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 就會一直報錯。

相關文章