关于Spring Boot的入门基础
导言:
(1)搭建Spring Boot项目
(2)Spring Boot第一个项目:helloworld
(3)项目属性配置
(4)Controller
(5)Spring Boot的数据库操作
(6)事务管理
在有了一点Spring的知识基础之后,昨天去找了个Spring Boot的教学视频(https://www.imooc.com/learn/767),才发现Spring是如何的累赘,其中Spring中要引入jar包,配置IOC容器,导入依赖,尤其是web应用的开发中繁杂的操作,都在Spring Boot结合Maven得到了很大的提高。
一.搭建项目
我看过两个视频,两个视频搭建Spring Boot项目的方法不一样,一个是在Maven项目中导入Spring Boot的依赖,使得Maven自动导入jar包,在pom.xml中写入:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
如果编辑器自动导包,这时候该项目就与Spring Boot相关了。第二种是直接创建Spring Boot项目,创建完就是一个成型的Spring Boot项目了。
二.Helloworld
我是使用IntelliJ IDEA,所以创建完以后项目目录为:
我是删掉了一些暂时没用的文件(包括static和templates),其中:
- static:保存所有的静态资源,比如:js,css,images。
- templates:保存所有的模板页面,比如Spring Boot默认jar包使用的嵌入式的tomcat,默认不支持JSP页面;还有可以使用模板引擎(freemarker,thymeleaf之类的)
然后IDEA是自动帮忙创建了该项目相关的启动类,而使用Maven则需要自己打:
package com.xie.firstexample.helloworld;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HelloworldApplication {
public static void main(String[] args) {
SpringApplication.run(HelloworldApplication.class, args);
}
}
其中@SpringBootApplication标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot应该使用这个类的main方法来启动SpringBoot的应用,而main函数中SpringApplication类中的run函数,第一个参数是该类类名,而第二个参数是main函数中String声明的args。
这也是最基础的构造了。在这之后,我们试一下Spring Boot的helloworld,先创建一个新的类,在类中先声明该类是controller,在进行其他操作:
import org.springframework.web.bind.annotation.Mapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class helloworld {
@RequestMapping("/hello")
public String sayinghello(){
return "Hello world!";
}
}
现在运行项目,打开浏览器,输入localhost:8080/hello;就可以发现Hello world!的输出(localhost是自己主机地址,8080是默认端口号,/hello是我们在注解RequestMapping中声明的)。
三.项目属性配置
现在要说一下项目属性的配置,我们最熟悉的配置文件的作用就是导入数据库操作,而今天暂时不说数据库操作。项目配置文件有两个:一个是application.properties文件,另一个是application.yml文件。我们在配置文件(applications.propertie)中加入:
server.port=8081
server.servlet.context-path=/xie
原本是是”localhost:8080/hello”打开获得输出,而现时候我们要打开”localhost:8081/xie/hello”才可以获得输出。除此之外还有很多server,大家都可以查查。
在配置文件输入(application.yml):
language:
type: Chinese
content: helloworld
那我们如何获取配置文件中的这些内容,我们先新建一个类,输入:
package com.xie.firstexample.helloworld;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix="language")
public class languageofchinese {
private String type;
private String content;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
再修改controller内的类:
package com.xie.firstexample.helloworld;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
public class helloworld {
@Autowired
private languageofchinese loc;
@RequestMapping(value={"/hello"},method=RequestMethod.GET)
public String sayinghello(){
return "Type: "+loc.getType()+",Content: "+loc.getContent();
}
}
这时候运行就可以获得配置文件中language内容
四. Controller的使用
Controller的使用常用就@Controller和@RestController,第二个注解是结合了@Controller和@ResponseBody,目的是返回json数据。
而@RequestMapping()注解是与浏览器地址操作相关,除此之外还有几个Mapping注解也有关系:
大家可以自行查阅他们与网络应答间的关系,其中@RequestMapping注解中的参数常用的有两个:value和method,第一个value表示”localhost:8080/hello”中的/hello,也可以同时标志两个地址指向同一个内容,比如:value={"/hello","/hi"}这时候输入”localhost:8080/hello”和”localhost:8080/hi”都可以访问到同一输出。而method常用就是两个:RequestMethod.POST和RequestMethod.GET,分别表示post和get。另外,该注解也可以在该类外面使用。
注:RequestMethod.POST可以使用@PostMapping代替,RequestMethod.GET可以使用@GetMapping代替
另外@GetMapping和@PostMapping这两个注解作用很大,在很多API接口中会根据地址末尾的参数信息来查找数据库,所以该注解可以返回网络地址中我们要查找的参数值。是结合@RequestParam和@PathVariable使用,这两个注解都可以接受参数,第一个是从request中获得,第二个是从URI模板中填充。
五.结合数据库
使用了Spring Boot的数据库操作后,又发现一个比Spring好太多的优点,操作数据库简单(使用JPA),比起JDBC和MyBatis来说,不用记操作数据库的命令代码,而且继承了已实现增删改查的类JapRepository,可以不用编写内部方法,直接调用即可。
*先要说一下不同的功能会有不同的请求:
请求类型 | 请求路径 | 功能 |
GET | /mysql | 获取数据库列表 |
POST | /mysql | 创建一个对象 |
GET | /mysql/{id} | 通过id查询一个对象 |
PUT | /mysql/{id} | 通过id修改一个对象 |
DELETE | /mysql/{id} | 通过id删除一个对象 |
注:/mysql是注解@xxxMapping中所使用的
首先要添加组件:
<!--jpa导入-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--jdbc导入-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--mysql导入-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
进行文件配置(使用yaml):
spring:
datasource:
#用户名
username: root
#密码
password: 123456
#设置url,其中//后是连接的ip地址,3306是mysql的端口号,xxxx是建的数据库名
url: jdbc:mysql://192.168.88.*:3306/xxxx
driver-class-name: com.mysql.jdbc.Driver
#进行其他设置
jpa:
hibernate:
#create根据定义的类自动生成表格(每次重启便会删除前次的表)
#除了create,常用的是update,第一次也会生成,但之后操作不会删表
ddl-auto: create
#在控制台看到sql语句,方便调试
show-sql: true
编写一个实体类映射数据表:
//省略导入的包
//使用JPA注解配置映射关系
@Entity //该类是与数据表映射的类
@Table(name="person") //用来指定和哪个数据表(name决定)映射
public class personDao {
@Id //声明这是一个主键
@GeneratedValue(strategy = GenerationType.IDENTITY)
//自增主键(就是会自动+1)
private Integer id;
@Column(name="lastname") //给数据表中属性命名
private String name;
@Column //省略则用类中定义声明
private Integer age;
public Integer getId() {
return id;
}
//省略get和set方法
}
我们可以看一下它帮数据库建立的表:
JPA好用就在后面这些步骤,由于它已经设置了一个类JpaRepository完成了里面所有的数据库操作,我们就不用在编写数据库操作指令,也不用像jdbc或者MyBatis这么麻烦。
编写一个Dao接口来操作实体类对应的数据表:
//注意是接口
//继承JpaRepository,其中泛型中第一个是与数据库映射的实体类,第二个是id的类型
public interface personRepository extends JpaRepository<personDao,Integer> {
}
实现各种对数据库的操作即可:
先编写controller再编写各种方法:
@RestController //声明controller
public class personController {
@Autowired //导入继承好的repository接口
private personRepository personrepository;
}
获取数据库中的全部信息:
@GetMapping("/person")
public List<personDao> getAllPerson(){
return personrepository.findAll();
}
我使用postman查看(查看前一定一定要记得将配置文件中的ddl-auto改成update,create是会删表的)
创建一个对象:
@PostMapping("/person")
public personDao savePerson(@RequestParam("name") String name,
@RequestParam("age") Integer age){
personDao person=new personDao();
person.setName(name);
person.setAge(age);
return personrepository.save(person);
}
获得结果:
查看数据库:
查询一个对象:
@GetMapping("/person/{id}")
public personDao findPersonById(@PathVariable("id") Integer id){
return personrepository.findById(id).orElse(null);
//findbyid是springboot2.1版本后的,代替原本1.5.4的findOne;
// 原本应该是:
// return personrepository.findOne(id);
}
使用postman查找:
修改一个对象:
@PutMapping("/person/{id}")
public personDao updatePerson(@PathVariable("id") Integer id,
@RequestParam("name") String name,
@RequestParam("age") Integer age){
personDao person=new personDao();
person.setId(id);
person.setName(name);
person.setAge(age);
return personrepository.save(person);
}
使用postman查找:
删除一个对象:
@DeleteMapping("/person/{id}")
public void deletePerson(@PathVariable("id") Integer id){
personrepository.deleteById(id);
}
使用postman:
查找数据库:
另外,如果想要使用age查找,也可以编写:
先在repository中编写:
//继承JpaRepository,其中泛型中第一个是与数据库映射的实体类,第二个是id的类型
public interface personRepository extends JpaRepository<personDao,Integer> {
//注:findByAge是固定格式,一定要这么写
public List<personDao> findByAge(Integer age);
}
再在controller中编写:
//记得区分通过id查找
@GetMapping("/person/age/{age}")
public List<personDao> findpersonbyage (@PathVariable("age") Integer age){
return personrepository.findByAge(age);
}
我在数据库添加两条记录,再通过postman查找:
六.事务管理
事务管理我曾经在学习笔记——spring中说过,现在我们来说说事务管理发生的原因:我们在实际业务场景中,经常会遇到数据频繁修改读取的问题。在同一时刻,不同的业务逻辑对同一个表数据进行修改,这种冲突很可能造成数据不可挽回的错乱,所以我们需要用事务来对数据进行管理。
使用事务管理都是使用注解@transactional的,可以参考文章:事务管理
举个例子(接上面数据库中例子):我们设置一个service,里面准备创建两个对象,假设一个对象生成不了,正常情况下,另一个正常的对象可以生成,如果这时候加入事务管理注解@transactional即两个都生成不了。
设立一个service:
@Service
public class PersonService {
@Autowired
personRepository personrepository;
@Transactional
public void settwoperson(){
personDao person1=new personDao();
person1.setName("aa");
person1.setAge(20);
personrepository.save(person1);
personDao person2=new personDao();
person2.setName("bb");
person2.setAge(30);
personrepository.save(person2);
}
}
在controller中实现方法:
@Autowired
PersonService personservice;
@PostMapping("/person/two")
public void settwoperson(){
personservice.settwoperson();
}
假如一个无法插入,则两个都无法插入。