一、项目属性配置
注意:在上个项目的基础上进行操作
将application.propertites改为application.yml,yml文件格式更为简单
配置端口、项目前缀路径(注意格式,value前有空格)
新建GirlProperties java文件(属性配置文件,简化配置)
package com.mlj.girl;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component//必须写,否则无法识别
@ConfigurationProperties(prefix = "girl")//属性前缀
public class GirlProperties {
private String cupSize;
private Integer age;
public String getCupSize() {
return cupSize;
}
public void setCupSize(String cupSize) {
this.cupSize = cupSize;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
在application.yml中饮用配置
girl:
cupSize: B
age: 18
在controller中使用配置的属性
package com.mlj.girl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
//相当于@controller和@responseBody的组合
@RestController
public class HelloController {
@Autowired//注入依赖
private GirlProperties girlProperties;
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String say() {
return girlProperties.getCupSize();
}
}
二、多环境配置(如生产环境和开发环境)
新建application-dev.yml application-prod.yml
server:
port: 8080
servlet:
context-path: /girl
girl:
cupSize: B
age: 18
server:
port: 8081
servlet:
context-path: /girl
girl:
cupSize: F
age: 18
修改application.yml
这里指定了开发环境dev,直接运行就会引用application-dev.yml的配置
spring:
#开发环境配置
profiles:
active: dev
运行时指定环境(避免频繁改动配置)
编译项目
进入target目录
java -jar jar包 --配置文件的参数(指定运行环境)
mvn install
cd target
java -jar jar包名 --spring.profiles.active.dev
三、controller层常用注解
@PathVariable符合rest风格接口url
package com.mlj.girl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
//相当于@controller和@responseBody的组合
@RestController
public class HelloController {
@Autowired
private GirlProperties girlProperties;
@GetMapping(value = "/hello/{id}")
public String say(@PathVariable("id") Integer id,
@RequestParam(value = "myId",required = false,defaultValue = "0") Integer myId) {
return "id:" + id + "myId:" + myId;
}
}
@GetMappting相当于@RequestMapping(method = RequestMethod.GET),适用于查找操作。相对应的有
@PostMapping 适用于添加操作
@PutMapping 适用于修改操作
@DeleteMapping 适用于删除操作
@Controller与@RestController
@RestController是相当于@controller和@responseBody的组合,返回json对象
@Controller返回的是html模板,目前开发为了提高性能大多前后端分离,所以一般使用@RestController
四、jpa数据库操作
新建数据库dbgirl
配置数据源和jpa
在application.yml中
#数据库配置
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/dbgirl
username: root
password: root
#jpa配置
jpa:
hibernate:
ddl-auto: update
show-sql: true
新建实体类:(注意:必须有无参构造方法,否则表创建失败)
类似hibernate的注解开发,省去了复杂配置
package com.mlj.girl;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Girl {
@Id
@GeneratedValue//自动生成策略
private Integer id;
private String cupSize;
private Integer age;
public Girl() {
}
// 必须有无参构造
//get set方法省略
}
新建接口GirlRepository
继承JpaRepository类,相当于hibernate中的session,可以对数据库进行操作
package com.mlj.girl;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface GirlRepository extends JpaRepository<Girl,Integer> {
}
新建类GirlController
因为没有复杂逻辑,先省略service.
对数据库表进行增删改查操作。girlRepository内有封装好的一般操作,查找条件为id,如果想自定义条件,需要在girlRepository中增加相应操作
package com.mlj.girl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
public class GirlController {
@Autowired
private GirlRepository girlRepository;
@Autowired
private GirlService girlService;
/**
* 获取列表
*
* @return
*/
@GetMapping(value = "/girls")
public List<Girl> girlList() {
return girlRepository.findAll();
}
/**
* 添加
*
* @param cupSize
* @param age
* @return
*/
@PostMapping(value = "/girls")
public Girl girlAdd(@RequestParam("cupSize") String cupSize,
@RequestParam("age") Integer age) {
Girl girl = new Girl();
girl.setCupSize(cupSize);
girl.setAge(age);
return girlRepository.save(girl);
}
/**
* 查找一个女生
*
* @param id
* @return
*/
@GetMapping(value = "/girls/{id}")
public Girl girlFindOne(@PathVariable(value = "id") Integer id) {
return girlRepository.findById(id).get();
}
/**
* 更新
*
* @param id
* @param cupSize
* @param age
* @return
*/
@PutMapping(value = "/girls/{id}")
public Girl girlUpdate(@PathVariable(value = "id") Integer id,
@RequestParam(value = "cupSize") String cupSize,
@RequestParam(value = "age") Integer age) {
Girl girl = new Girl();
girl.setId(id);
girl.setCupSize(cupSize);
girl.setAge(age);
return girlRepository.save(girl);
}
/**
* 删除
*
* @param id
*/
@DeleteMapping(value = "/girls/{id}")
public void girlDelete(@PathVariable(value = "id") Integer id) {
girlRepository.deleteById(id);
}
}
自定义条件查询
根据女生的年龄查找
在girlRepository中增加方法findByAge:(注意:方法名不能随便起,遵守JPA约定,idea会自定提示)
package com.mlj.girl;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface GirlRepository extends JpaRepository<Girl,Integer> {
//根据年龄查找
public List<Girl> findByAge(Integer age);
}
五、事务处理
在service层需要事务处理的方法上添加注解@Transactional,一般除了查询操作都要求事务处理
当我们在一个方法内要对数据库进行两次操作,希望两次操作同时进行时,事务就起作用了。例如:我要同时在数据库添加两个girl,当一个girl不符合条件时会添加失败,另一个则会添加成功,这就需要事务处理了。
将数据库表cupSize位数修改为1,人为制造错误进行测试,观察数据库数据变化
package com.mlj.girl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class GirlService {
@Autowired
private GirlRepository girlRepository;
@Transactional
// 查询不需要加事务
public void insertTow() {
Girl girl1 = new Girl();
girl1.setCupSize("C");
girl1.setAge(17);
girlRepository.save(girl1);
Girl girl2 = new Girl();
girl1.setCupSize("DDDD");
girl1.setAge(19);
girlRepository.save(girl2);
}
}
@PostMapping(value = "/girls/tow")
public void girlTow() {
girlService.insertTow();
}
六、问题与解决
org.apache.catalina.LifecycleException: Failed to start component [Connector
我的是端口被占用了,两个环境用了一个端口号,修改端口号或者杀死进程。
Inferred type 'S' for type parameter 'S' is not within its bound;
girlRepository.findOne(id)报错。 .findOne(id)不适用2.0以上的版本。改为girlRepository.findById(id).get();
Ambiguous handler methods mapped for HTTP path
重复映射错误。在使用@PathVariable进行路径映射时,注意进行区分
@GetMapping(value = "/girls/{id}")
@GetMapping(value = "/girls/{age}")重复映射。改为@GetMapping(value = "/girls/age")
Transactional注解不回滚
数据库引擎要支持事务,如果是MySQL,注意表要使用支持事务的引擎,比如innodb,如果是myisam,事务是不起作用的。
修改数据库引擎
或者在
修改mysql安装目录下的my.ini文件,在[mysqld]下加上:
1 |
|