原料
新鮮的IntelliJ IDEA、一雙手、以及電腦一台。
搭建架構
建立項目
打開IDE,點選File -> New Project。在左側的清單中的選擇Maven項目,點選Next。
填寫GroupId和ArtifactId
什麼是GroupId和ArtifactId?大家可以參考一下google出來的定義,可以參考一下。
GroupID是項目組織唯一的辨別符,實際對應JAVA的包的結構,是main目錄裡java的目錄結構。
ArtifactID就是項目的唯一的辨別符,實際對應項目的名稱,就是項目根目錄的名稱
簡單了解一下,可以了解為GroupId就是你的Github賬号,而ArtifactId就是你的具體某個項目,例如這個例子的源碼,SpringBootDemo,
detectiveHLH/springbootdemo detectiveHLH就是GroupId,而ArtifactId就是後面的項目名稱。
是以,這裡應該填寫如下(僅供參考)。
GroupId: com.detectivehlh.test
ArtifactId: parent
test為項目的名稱。ArtifactId代表父類,是以就寫parent了。點選Next。
設定Project Name和Project Location
ProjectName就寫項目的名稱就好。Project Location就是項目在你本地的真實路徑。填好之後,點選Next。
然後可以看到IDE已經建立好了項目。
.
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ └── resources
│ └── test
│ └── java
└── test.iml
然後右下角會彈出Maven projects need to be imported,選擇右邊的Enable Auto-Imported.然後删除src目錄。
建立子產品
本次項目的架構一共有四層結構,也可以說是有四個子產品。分别是api、core、data、domain.我們從底層開始,自底向上開始構模組化塊。
domain
存放實體類
點選File -> New -> Module,在左側的清單中選擇Maven,點選Next。在ArtifactId處填 domain,一路Next。
data子產品
主要是做一些對資料庫的操作
點選File -> New -> Module,在左側的清單中選擇Maven,點選Next。在ArtifactId處填 data,一路Next。在子產品中其實是存在互相依賴關系的。
data子產品依賴domain子產品的實體。是以要在data檔案的配置檔案中實作對domain的依賴。
打開data目錄中的pom.xml檔案。在
<dependencies>
<dependency>
<groupId>com.detectivehlh.test</groupId>
<artifactId>domain</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
core子產品
後端主要的業務邏輯都會在core子產品中。
點選File -> New -> Module,在左側的清單中選擇Maven,點選Next。在ArtifactId處填 core,一路Next。同上,此處也需要配置依賴關系。
core子產品的中的service會依賴data子產品中的資料。
打開core目錄下的pom.xml檔案。在
<dependencies>
<dependency>
<groupId>com.detectivehlh.test</groupId>
<artifactId>data</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
api子產品
主要是存放供前端調用的接口。
點選File -> New -> Module,在左側的清單中選擇Maven,點選Next。在ArtifactId處填 api,一路Next。此處的api子產品依賴core中的service服務。
打開api目錄下的pom.xml檔案。在
<dependencies>
<dependency>
<groupId>com.detectivehlh.test</groupId>
<artifactId>core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
讓項目"走兩步"
到此,架構算是搭建好了,下一步就是要讓項目"走兩步"來看看。此時的項目的目錄如下。
.
├── api
│ ├── api.iml
│ ├── pom.xml
│ └── src
│ ├── main
│ │ ├── java
│ │ └── resources
│ └── test
│ └── java
├── core
│ ├── pom.xml
│ └── src
│ ├── main
│ │ ├── java
│ │ └── resources
│ └── test
│ └── java
├── data
│ ├── pom.xml
│ └── src
│ ├── main
│ │ ├── java
│ │ └── resources
│ └── test
│ └── java
├── domain
│ ├── pom.xml
│ └── src
│ ├── main
│ │ ├── java
│ │ └── resources
│ └── test
│ └── java
├── pom.xml
└── test.iml
定位到/api/src/main/java,在java目錄下建立package,名字為你之前定義的groupid再加上子產品名,舉個例子。我這的名字就應該為com.detectivehlh.test.api,然後
在該包下建立名為Application的class。然後将代碼替換成如下代碼。
package com.detectivehlh.test.api;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
此時會報錯,是因為springboot的各項依賴,都還沒有引入項目的dependences。打開根目錄下的pom.xml檔案,添加如下依賴。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
然後打開api目錄下的pom.xml檔案。在dependencies标簽中添加如下依賴。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
此時Application中就不會報錯了。然後就可以啟動項目了。打開Application這個類,在SpringBootApplication注解下有個綠色的啟動鍵,點選即可啟動項目。之後可在右上方啟動。
啟動之後,打開http://localhost:8080,如果頁面顯示
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Tue Sep 18 19:01:11 CST 2018
There was an unexpected error (type=Not Found, status=404).
No message available
那麼一個簡單的springboot應用就可以啟動成功了。
實作controller層
在com.detectivehlh.test.api包下,建立一個名為controller的包。然後建立名為HelloController的class。
将其全部替換為如下代碼(包名根據你的項目命名自行修改)。
package com.detectivehlh.test.api.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, SpringBoot";
}
}
重新啟動項目,通路http://localhost:8080/hello,就可以看到頁面顯示如下資訊。
Hello, SpringBoot
@RestController注解比較适用于Restful風格的API,如果接口隻關心資料,不做server render,就可以使用@RestController注解。
如果接口需要傳回模版頁面,則需要使用@Controller注解。
@GetMapping注解,是将HTTP Get請求映射到我們自定義的hello方法上。
實作service層
建立CoreConfiguration
定位到/core/src/main/java,在java目錄下建立名為com.detectivehlh.test.core的包。然後在該包建立名為CoreConfiguration的Class。
package com.detectivehlh.test.core;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @author detectiveHLH
* @date 2018/09/13
*/
@ComponentScan
@Configuration
public class CoreConfiguration {
}
引入依賴
此時會報錯,同樣是因為依賴沒有引入。在core的pom.xml檔案中的dependencies标簽中添加如下依賴。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
稍等片刻,就不會有報錯提示了。
建立Interface
在com.detectivehlh.test.core包下建立一個名為service的包。在service包下建立一個Class,
名字為HelloService,類型選擇Interface。然後修改代碼如下(包名根據你的項目命名自行修改)。
package com.detectivehlh.test.core.service;
public interface HelloService {
String sayHello();
}
建立實作類
在service目錄下建立名為impl的包。然後在impl下建立名為HelloServiceImpl的類。修改代碼如下(包名根據你的項目命名自行修改)。
package com.detectivehlh.test.core.service.impl;
import com.detectivehlh.test.core.service.HelloService;
import org.springframework.stereotype.Service;
@Service
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello() {
return "Hello, SpringBoot";
}
}
調用實作類
修改HelloController中的 hello 方法的代碼如下(包名根據你的項目命名自行修改)。
package com.detectivehlh.test.api.controller;
import com.detectivehlh.test.core.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* RestController
* 定義為Restful風格的API控制器
*/
@RestController
public class HelloController {
@Autowired
private HelloService helloService;
@GetMapping("/hello")
public String hello() {
return helloService.sayHello();
}
}
此時helloService會報錯,這是因為我們沒有将HelloService這個添加到Bean容器中來。修改Application類代碼如下(包名根據你的項目命名自行修改)。
package com.detectivehlh.test.api;
import com.detectivehlh.test.core.CoreConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;
@SpringBootApplication
@Import(CoreConfiguration.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
此時再通路http://localhost:8080/hello,就可以看到如下正常的輸出了。
打通資料庫
實作了簡單的service,下一步就是要連接配接資料庫。假設現在在你本地已經有了mysql服務。有名為test的資料庫,該資料庫下有名為user_role的表。表結構如下。
資料庫表名和表資料
column_name | column_value |
---|---|
id | 使用者id |
name | 使用者名 |
并且有了資料
1 |
建立實體類
定位到/domain/src/main/java,在java目錄下建立名為com.detectivehlh.test.domain的包。在該包下建立entity包。
在entity下建立名為BaseEntity的抽象類。修改代碼如下。
package com.detectivehlh.test.domain.entity;
public abstract class BaseEntity {
private long createdAt;
private String createdBy;
private long updatedAt;
private String updatedBy;
public long getCreatedAt() {
return createdAt;
}
public void setCreatedAt(long createdAt) {
this.createdAt = createdAt;
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public long getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(long updatedAt) {
this.updatedAt = updatedAt;
}
public String getUpdatedBy() {
return updatedBy;
}
public void setUpdatedBy(String updatedBy) {
this.updatedBy = updatedBy;
}
}
在entity下建立名為UserRole的類。代碼如下。
package com.detectivehlh.test.domain.entity;
public class UserRole extends BaseEntity {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
建立dao層
實作與資料庫互動的mapper。
定位到/data/src/main/java,在java目錄下建立名為com.detectivehlh.test.data的包。在該包下建立名為dao的包和名為
DataConfiguration的類。然後在dao包下建立名為UserRoleMapper的類。DataConfiguration代碼如下。
package com.detectivehlh.test.data;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @author duzhengkang
* @date 2018/6/25
*/
@ComponentScan
@Configuration
@MapperScan("com.detectivehlh.test.data.dao")
public class DataConfiguration {
}
将UserRoleMapper的代碼修改為如下。
package com.detectivehlh.test.data.dao;
import com.detectivehlh.test.domain.entity.UserRole;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface UserRoleMapper {
/**
* 查詢所有的使用者角色
* @return
*/
List<UserRole> all();
}
此時代碼會報錯,同樣的依賴原因。打開根目錄下的pom.xml檔案。添加如下依賴。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
添加如上依賴,稍等片刻,就不會報錯了。但是此時運作項目依舊會報錯。是因為我們引入了mybatis但是卻沒有配置檔案。以及沒有将mapper注入到容器中去。
修改Application中的代碼如下。
package com.detectivehlh.test.api;
import com.detectivehlh.test.core.CoreConfiguration;
import com.detectivehlh.test.data.DataConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;
@SpringBootApplication
@Import({CoreConfiguration.class, DataConfiguration.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
mapper就被注入到容器中去了。下一步需要添加配置檔案。定位到/api/src/main/resources,建立application.yaml檔案。
修改代碼如下。
spring:
application:
name: test
# 資料庫配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 9687Luohongwei
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
# mapper檔案配置
mybatis:
mapper-locations: classpath:mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
修改完畢後,啟動項目,通路http://localhost:8080/hello,就可以看到正常輸出了。
實作mapper
定位到/data/src/main/resources,建立名為mapper的包。在mapper包下建立名為UserRoleMapper的xml檔案。修改代碼如下。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.detectivehlh.test.data.dao.UserRoleMapper">
<!--用于與資料庫字段作一一對應-->
<resultMap id="userRoleMap" type="com.detectivehlh.test.domain.entity.UserRole">
<result column="id" property="id"/>
<result column="name" property="name"/>
</resultMap>
<!--查詢下方列出的所有列-->
<sql id="allColumns">
id, name
</sql>
<!--定義表名-->
<sql id="tableName">
user_role
</sql>
<select id="all" resultMap="userRoleMap">
SELECT
<include refid="allColumns"/>
FROM
<include refid="tableName"/>
ORDER BY id DESC
</select>
</mapper>
一定注意namespace是否準确。
調用mapper
修改實作類HelloServiceImpl代碼如下。
package com.detectivehlh.springbootdemo.core.service.impl;
import com.detectivehlh.springbootdemo.core.service.HelloService;
import com.detectivehlh.springbootdemo.data.dao.UserRoleMapper;
import com.detectivehlh.springbootdemo.domain.entity.UserRole;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class HelloServiceImpl implements HelloService {
@Autowired
private UserRoleMapper userRoleMapper;
@Override
public List<UserRole> createToken(String key) {
List<UserRole> data = userRoleMapper.all();
return data;
}
}
此時會報錯,是因為實作類中的傳回類型已經變成了List
package com.detectivehlh.test.core.service;
import com.detectivehlh.test.domain.entity.UserRole;
import java.util.List;
public interface HelloService {
List<UserRole> sayHello();
}
讓我們回到controller中,我們發現在HelloController中也有報錯。這個錯誤同樣也是因為傳回類型不一緻的原因,修改代碼如下。
package com.detectivehlh.test.api.controller;
import com.detectivehlh.test.core.service.HelloService;
import com.detectivehlh.test.domain.entity.UserRole;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* RestController
* 定義為Restful風格的API控制器
*/
@RestController
public class HelloController {
@Autowired
private HelloService helloService;
@GetMapping("/hello")
public List<UserRole> hello() {
return helloService.sayHello();
}
}
然後啟動項目,通路http://localhost:8080/hello。就可以看到,接口傳回了user_role表中的所有資料。
[
{
"createdAt": 0,
"createdBy": null,
"updatedAt": 0,
"updatedBy": null,
"id": 1,
"name": "Tom"
}
]
此時雖然能夠正常通路,但是會在控制台報如下警告。
Tue Sep 18 20:40:22 CST 2018 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
在com.detectivehlh.test.api包下建立config包,在config包中建立DbConfig檔案。代碼如下。
package com.detectivehlh.test.api.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
/**
* DbConfig
*
* @author detectiveHLH
* @date 2018-07-27 10:35
**/
@Configuration
@ConfigurationProperties
@EnableTransactionManagement
public class DbConfig {
@Bean
@ConfigurationProperties("spring.datasource")
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate(){
return new JdbcTemplate(dataSource());
}
@Bean
public PlatformTransactionManager transactionManager(){
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(dataSource());
return dataSourceTransactionManager;
}
}
重新開機啟動項目,通路接口時就不會有警告了。
最後的代碼目錄結構如下。
.
├── api
│ ├── api.iml
│ ├── pom.xml
│ ├── src
│ │ ├── main
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ └── detectivehlh
│ │ │ │ └── test
│ │ │ │ └── api
│ │ │ │ ├── Application.java
│ │ │ │ ├── config
│ │ │ │ │ └── DbConfig.java
│ │ │ │ └── controller
│ │ │ │ └── HelloController.java
│ │ │ └── resources
│ │ │ └── application.yml
│ │ └── test
│ │ └── java
│ └── target
│ ├── classes
│ │ ├── application.yml
│ │ └── com
│ │ └── detectivehlh
│ │ └── test
│ │ └── api
│ │ ├── Application.class
│ │ ├── config
│ │ │ └── DbConfig.class
│ │ └── controller
│ │ └── HelloController.class
│ └── generated-sources
│ └── annotations
├── core
│ ├── pom.xml
│ ├── src
│ │ ├── main
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ └── detectivehlh
│ │ │ │ └── test
│ │ │ │ └── core
│ │ │ │ ├── CoreConfiguration.java
│ │ │ │ └── service
│ │ │ │ ├── HelloService.java
│ │ │ │ └── impl
│ │ │ │ └── HelloServiceImpl.java
│ │ │ └── resources
│ │ └── test
│ │ └── java
│ └── target
│ ├── classes
│ │ └── com
│ │ └── detectivehlh
│ │ └── test
│ │ └── core
│ │ ├── CoreConfiguration.class
│ │ └── service
│ │ ├── HelloService.class
│ │ └── impl
│ │ └── HelloServiceImpl.class
│ └── generated-sources
│ └── annotations
├── data
│ ├── pom.xml
│ ├── src
│ │ ├── main
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ └── detectivehlh
│ │ │ │ └── test
│ │ │ │ └── data
│ │ │ │ ├── DataConfiguration.java
│ │ │ │ └── dao
│ │ │ │ └── UserRoleMapper.java
│ │ │ └── resources
│ │ │ └── mapper
│ │ │ └── UserRoleMapper.xml
│ │ └── test
│ │ └── java
│ └── target
│ ├── classes
│ │ ├── com
│ │ │ └── detectivehlh
│ │ │ └── test
│ │ │ └── data
│ │ │ ├── DataConfiguration.class
│ │ │ └── dao
│ │ │ └── UserRoleMapper.class
│ │ └── mapper
│ │ └── UserRoleMapper.xml
│ └── generated-sources
│ └── annotations
├── domain
│ ├── pom.xml
│ ├── src
│ │ ├── main
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ └── detectivehlh
│ │ │ │ └── test
│ │ │ │ └── domain
│ │ │ │ └── entity
│ │ │ │ ├── BaseEntity.java
│ │ │ │ └── UserRole.java
│ │ │ └── resources
│ │ └── test
│ │ └── java
│ └── target
│ ├── classes
│ │ └── com
│ │ └── detectivehlh
│ │ └── test
│ │ └── domain
│ │ └── entity
│ │ ├── BaseEntity.class
│ │ └── UserRole.class
│ └── generated-sources
│ └── annotations
├── pom.xml
└── test.iml
寫在後面
寫的比較詳細,如果有不對的地方,大佬盡管怼。本項目的源碼在
這裡個人部落格在
Github在
,歡迎star或follow。