1 修改記錄
時間 | 描述 |
---|---|
2017-09-26 | 建檔 |
2017-09-27 | 添加第3-6節 |
2017-09-29 | 添加第7節 |
2 簡單Web項目
- IDE:Eclipse Neon Release (4.6.0)
- Builder:Maven (3.3.9)
- Framwork:Spring Boot
2.1 安裝SpringBoot插件
在Help -> Eclipse Marketplace -> Popular 下搜索Spring Tools(aka Spring IDE and Spring Tool Suite)並安裝。
2.2 創建Maven項目
右擊Project Explorer的空白區域,new -> other -> Maven -> Maven Project,archetype選擇webapp。
2.3 添加依賴
- spring-boot-starter-parent:
- spring-boot-starter-web:
- kotlin-stdlib-jre8:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.7.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jre8</artifactId>
<version>1.1.3</version>
</dependency>
</dependencies>
2.4 設計Controller
這裏將啓動的入口和Controller類集合到了一個類裏面,後面的章節會把這兩個分開。
- @RestController:被註解的類會被Spring視作Controller,且該類下所有被@RequestMapping註解的方法還默認被@ResponseBody註解。即@RestController相當於@Controller和@ResponseBody的組合;
- @EnableAutoConfiguration:允許Spring Boot根據引用的JAR包推斷並自動配置Beans。
package chngzhen.example
import org.springframework.boot.SpringApplication
import org.springframework.web.bind.annotation.RestController
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.web.bind.annotation.RequestMapping
@RestController
@EnableAutoConfiguration
class WebApplication {
@RequestMapping("/hello")
fun Hello(): String {
return "Hello world!"
}
}
fun main(args: Array<String>) {
SpringApplication.run(WebApplication::class.java, *args)
}
2.5 運行
運行testController類,在瀏覽器中訪問127.0.0.1:8080/hello。
注意:地址中沒有項目名稱
3 拋棄POM繼承
利用Maven管理項目時,通常會出現一個父項目下有多個子模塊的情況,Web項目作爲其中一個子模塊,除了會依賴其他子模塊,還會繼承父項目。這時候,就不能使用第2節中繼承的方法來引入Spring Boot。
可以將spring-boot-starter-parent作爲依賴放在(父項目的)< dependencyManagement >中,但scope和Type都有明確的規定:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.6.RELEASE</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
然後在Web子模塊中,按需求聲明spring-boot-starter-parent中的依賴。例如,聲明引入spring-boot-starter-web:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
4 分離啓動類和控制器
將第2節的啓動類WebApplication分離出來,放在chngzhen.web.mvc.starter包下。
package chngzhen.web.mvc.starter
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@EnableAutoConfiguration
@ComponentScan(basePackages=arrayOf("chngzhen.web.mvc"))
class WebApllication
fun main(args: Array<String>) {
SpringApplication.run(WebApllication::class.java, *args)
}
將Controller放到chngzhen.web.mvc.controller包下:
package chngzhen.web.mvc.controller
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
class LoginingController {
@RequestMapping("/register")
fun register(): String {
return "register"
}
}
重新運行WebApplication,訪問127.0.0.1:8080/register。
5 返回視圖
上面的Controller返回的都是內容,而不是視圖。
首先,添加register視圖文件。Spring Boot和標準Spring框架對視圖文件的存放位置要求不盡相同。spring Boot默認要求視圖文件存放在classpath*:/templates/下,但可以重新指定。現在在src/main/resources下新建一個/templates/public文件夾,並在裏面添加了一個register.html文件;
然後,返回register.html。@RestController註解的Controller返回的都是內容,要想返回視圖,需要創建ModelAndView實例並返回:
package chngzhen.web.mvc.controller
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.servlet.ModelAndView
@RestController
class LoginingController {
@RequestMapping("/register")
fun register(): ModelAndView {
println("Enter the register Method")
return ModelAndView("/public/register")
}
}
運行WebApplication,然後訪問127.0.0.1:8080/register會報404的錯誤,但控制檯的確輸出了“Enter the register Method”。那是因爲沒有添加模板引擎。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
5.1 拋棄ModelAndView
像在標準Spring框架中那樣,直接返回字符串,視圖解析器自動添加前綴和後綴後將視圖返回給前端。
首先,取消@RestController註解,改用@Controller:
package chngzhen.web.mvc.controller
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.servlet.ModelAndView
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.ResponseBody
@Controller
class LoginingController {
@RequestMapping("/hello")
@ResponseBody
fun hello(): String {
return "hello"
}
@RequestMapping("/register")
fun register(): String {
return "register"
}
}
然後,在src/main/resources下新建一個application.properties文件,利用spring.thymeleaf.prefix指定視圖文件的路徑,spring.thymeleaf.suffix指定視圖文件的後綴名:
spring.thymeleaf.prefix=classpath:/templates/public/
spring.thymeleaf.suffix=.html
運行訪問。
6 訪問靜態文件
Spring Boot默認攔截/**格式的請求,並映射到”classpath:/META-INF/resources/”、 “classpath:/resources/”、”classpath:/static/”和 “classpath:/public/”四個路徑下。即攔截所有請求,然後去以上四個地址下按URL尋找靜態資源。
在src/main/resources下新建一個static文件夾,向裏面添加一個1.jpg圖片文件。然後在瀏覽器中輸入127.0.0.1:8080/1.jpg訪問。
6.1 自定義
靜態文件的請求URL格式和映射路徑是通過org.springframework.boot.autoconfigure.web.WebMvcProperties中的staticPathPattern與org.springframework.boot.autoconfigure.web.ResourceProperties中的staticLocations指定的。這兩個屬性均可以在application.properties中設置:
spring.mvc.static-path-pattern=/assets/**
spring.resources.static-locations=classpath:/templates/assets/
將圖片放在src/main/resources/templates/assets下,在瀏覽器中輸入127.0.0.1:8080/assets/1.jpg訪問。
6.2 HTML引用
在HTML中引用靜態文件時無須指定IP、端口和項目名稱:
<link rel="stylesheet" href="/assets/plugins/bootstrap/css/bootstrap.min.css"/>
<style type="text/css">
.icontainer{
background:url(/assets/images/bg002.jpg);
}
</style>
<script src="/assets/plugins/jquery/jquery-3.2.1.min.js"></script>
7 數據庫訪問
7.1 添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
錯誤 | 方案 |
---|---|
At least one JPA metamodel must be present! | 可能是缺少了spring-boot-devtools依賴 |
7.2 實體類
package chngzhen.web.mvc.model.domain
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
import javax.persistence.Table
import javax.persistence.Transient
@Entity
@Table(name="user_info")
class UserInfo() {
companion object{
// Alias Begin
val ALIAS_ID = "ID"
val ALIAS_USER_NAME = "用戶賬號"
val ALIAS_USER_PSWD = "登陸密碼"
val ALIAS_REGISTER_TIME = "註冊時間"
}
// Property Begin
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private var id: Int? = null
@Column(name="user_name")
private var userName: String? = null
@Column(name="user_pswd")
private var userPswd: String? = null
@Column(name="register_time")
private var registerTime: java.util.Date? = null
@Transient
private var registerTimeString: String? = null
// Getter/Setter Begin
fun getId() = id
fun setId(id: Int) {
this.id = id
}
fun getUserName() = userName
fun setUserName(userName: String) {
this.userName = userName
}
fun getUserPswd() = userPswd
fun setUserPswd(userPswd: String) {
this.userPswd = userPswd
}
fun getRegisterTime() = registerTime
fun setRegisterTime(registerTime: java.util.Date) {
this.registerTime = registerTime;
this.registerTimeString = getRegisterTimeString()
}
fun getRegisterTimeString(): String? =
if (null == registerTime) null
else java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(registerTime)
fun setRegisterTimeString(registerTimeString: String) {
setRegisterTime(java.text.SimpleDateFormat().parse(registerTimeString))
}
}
7.3 數據庫操作接口
package chngzhen.web.mvc.service
import org.springframework.data.repository.CrudRepository
import org.springframework.stereotype.Repository
import chngzhen.web.mvc.model.domain.UserInfo
import org.springframework.beans.factory.annotation.Qualifier
import javax.persistence.Table
@Repository
interface UserInfoService: CrudRepository<UserInfo, Int> {
fun getById(id: Int): UserInfo
}
7.4 調用
package chngzhen.web.mvc.controller
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.servlet.ModelAndView
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.ResponseBody
import org.springframework.beans.factory.annotation.Autowired
import chngzhen.web.mvc.service.UserInfoService
@Controller
class LoginingController {
@Autowired
lateinit var userInfoService: UserInfoService
@RequestMapping("/register")
fun register(): String {
println(userInfoService.getById(1).getUserName())
return "register"
}
}