本博客分为以下几个章节:
1.项目属性配置
2.Controller的使用
3.数据库操作
4.事务管理
5.表单验证
6.使用AOP处理请求
1.项目属性配置
将各种配置项写在application.properties文件里,为了配置方便将后缀名改为.yml(这种格式可以将配置进行分组操作,便于取值),变成application.yml。在书写配置项时要注意
server:
port: 8080
context-path: /girl
这里port:和context-path:后面必须有一个空格,这是语言规范。
将变量配置好后,那我们怎么用这个变量呢? 假设有这么一个变量
score: 85
就可以用@Value来取值,代码如下
@Value("${score}")
public String score;
假如有很多个变量,难道我们要一个个取出来吗?当然不是,那样太麻烦了,可以用建立一个bean的方式解决
girl:
cupSize: B
age: 18
height: 165
weight: 55
一个女生,她有4个变量,我们可以在配置项里把4个变量写在一个girl下。然后建立一个girlProperties类,代码如下
@Component
@ConfigurationProperties(prefix ="girl")
public class girlProperties {
public String cupSize;
public int age;
public String getCupSize() {
return cupSize;
}
public void setCupSize(String cupSize) {
this.cupSize = cupSize;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
用@ConfigurationProperties(prefix ="girl")将这个类和配置项里的girl联系起来,然后因为是要建立一个bean,所以要加上@Component。
@Autowired
private girlProperties girlProperties;
这样以后就可以用girlProperties的get方法取出需要的值了。
2.Controller的使用
在SpringBoot标明一个类是controller时用@RestController注解。
然后用@RequestMapping(value = "/say",method = RequestMethod.GET)给方法添加相应的映射。
如果我们想要多个映射都能访问到同一个方法,该怎么办呢?
就可以这样写
@RequestMapping(value = {"/say","/hi"},method = RequestMethod.GET)
就可以通过/say和/hi访问到同一个方法
那想要在请求方法时加上参数怎么办呢?有两种加参数的方法
一是@RequestMapping(value = "/say/{id}")这种路径中就写好一个参数的方式
就可以用@PathVariable注解
public String say(@PathVariable("id") Integer myid){***}
二是在传统的url方法,在请求路径后面加上?id=***
就可以用@RequestParam注解
public String say(@RequestParam(value = "id",defaultValue = "0") int myid){***}
public String say(@RequestParam(value = "id",defaultValue = "0") int myid){***}
3.数据库操作
在pom文件中添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
在application.yml中写上jpa的配置
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/dgirl 这是数据库的地址
username: root
password: *****
jpa:
hibernate:
ddl-auto: update
show-sql: true
// 建表方式有四种 一般update方式
create:每次加载Hibernate时都会删除上一次生成的表,然后重新生成新表,即使两次没有任何修改也会这样执行,这就导致每次启动都是一个新的数据库,也是导致数据丢失的重要原因
create-drop:每次加载Hibernate时都会生成表,但当SessionFactory关闭时,所生成的表将自动删除
update:最常用的属性值,第一次加载Hibernate时创建数据表(前提是需要先有数据库),以后加载HIbernate时只会根据model更新,即使model已经删除了某些属性,数据表也不会随之删除字段。
validate:每次加载Hibernate时都会验证数据表结构,只会和已经存在的数据表进行比较,根据model修改表结构,但不会创建新表。
springb-hibernate是自动在数据库中建表的,建立一个实体类,就会在数据库中自动新建一个Girl表
@Entity //声明一个实体,用的是Java规范下的注解(必须要加)
public class Girl {
@Id //声明主键
@GeneratedValue //声明主键的生成策略
private Integer id;
private String cupSize;
@Min(value = 18,message = "未成年少女禁止入内")
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
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;
}
}
然后新建一个借口,继承JpaRepository类
public interface GirlRepository extends JpaRepository<Girl,Integer> {
//JpaRepository<Girl,Integer>中Girl是类名,Integer是主键的类型
}
然后就可以再Controller中进行各种操作
@RestController
public class GirlController {
@Autowired
private GirlRepository girlRepository;
private static final Logger logger= LoggerFactory.getLogger(GirlController.class);
// 查询所有女生列表
@GetMapping(value = "/girls")
public List<Girl> girlList() {
logger.info("查询所有女生列表");
System.out.println("查询所有女生列表");
return girlRepository.findAll();
}
// 添加一个女生
@PostMapping(value = "/girls")
public Girl girlAdd(@Valid Girl girl,BindingResult bindingResult) {
if (bindingResult.hasErrors()){
System.out.println(bindingResult.getFieldError().getDefaultMessage());
return null;
}
return girlRepository.save(girl);
}
// 查询一个女生
@GetMapping(value = "girls/{id}")
public Girl girlFindOne(@PathVariable("id") Integer id){
return girlRepository.findById(id).orElse(null);
}
// 更新接口
@PutMapping(value = "girls/{id}")
public Girl girlUpdate(@PathVariable("id") Integer id,
@RequestParam("cupSize") String cupSize,
@RequestParam("age") Integer age){
Girl girl=new Girl();
girl.setCupSize(cupSize);
girl.setAge(age);
girl.setId(id);
return girlRepository.save(girl);
}
// 删除一个女生
@DeleteMapping(value = "girls/{id}")
public void girlDelete(@PathVariable("id") Integer id){
girlRepository.deleteById(id);
}
// 根据年龄查找女生
@GetMapping("girls/age/{age}")
public List<Girl> girlListByAge(@PathVariable("age") Integer age ){
return girlRepository.findByAge(age);
}
}
如果想根据某个字段去查询数据,可以再Repository类中添加自定义有方法,如下
public interface GirlRepository extends JpaRepository<Girl,Integer> {
public List<Girl> findByAge(Integer age); //这里的类名是有规定的,必须是findBy+字段名(第一个字母大写),如findByAge
}
4.事务管理
假如要添加多个数据,其中一个A数据不符合数据库里的格式规范,那就会导致只有A前面的那些数据存进去,其他都没有存,显然这不是我们想要的结局。
那可以在方法上加一个@Transactional注解,如果其中一个数据插入失败,则所有数据都不会被插入
@Service
public class GirlService {
@Autowired
public GirlRepository girlRepository;
@Transactional
public void insertTwo(){
Girl girl1=new Girl();
girl1.setAge(20);
girl1.setCupSize("D");
girlRepository.save(girl1);
Girl girl2=new Girl();
girl2.setAge(21);
girl2.setCupSize("Cccccc");
girlRepository.save(girl2);
}
}
5.表单验证
如果想要拦截某些数据,比如只能添加18岁以上的女生,这就要在age字段上加上条件了
@Min(value = 18,message = "未成年少女禁止入内")
private Integer age;
age的最小值为18,如果低于18则会返回信息"未成年少女禁止入内"
然后在添加女生方法中加上注解@Valid
@PostMapping(value = "/girls")
public Girl girlAdd(@Valid Girl girl,BindingResult bindingResult) {
if (bindingResult.hasErrors()){
System.out.println(bindingResult.getFieldError().getDefaultMessage());
return null;
}
return girlRepository.save(girl);
}
bindingResult.getFieldError().getDefaultMessage()就是"未成年少女禁止入内",bindingResult是用来判断是否添加成功的
6.使用AOP处理请求
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程
先添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
@Aspect //添加Aspect注解
@Component
public class HttpAspect {
private final static Logger logger= LoggerFactory.getLogger(HttpAspect.class); //日志
/* 如果切点是具体的某个方法,如girlAdd方法,则切点就是execution(public * com.example.demo.contorller.GirlController.girlAdd(..)),(..)代表任意参数。
如果切点是一个类中所有的方法,那就加个*就可以
*/
@Pointcut("execution(public * com.example.demo.contorller.GirlController.*(..))")
public void log(){} //切点
@Before("log()") //切点之前执行的方法
public void doBefore(JoinPoint joinPoint){
ServletRequestAttributes attributes= (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request=attributes.getRequest();
//获取url
logger.info("url={}",request.getRequestURI());
//获取method
logger.info("method={}",request.getMethod());
//获取ip
logger.info("ip={}",request.getRemoteAddr());
//获取类方法
logger.info("clas_method={}",joinPoint.getSignature().getDeclaringTypeName()+"."+joinPoint.getSignature().getName());
//获取参数
logger.info("args={}",joinPoint.getArgs());
System.out.println("doBefore");
logger.info("doBefore");
}
@After("log()") //切点之后执行的方法
public void doAfter(){
System.out.println("doAfter");
logger.info("doAfter");
}
@AfterReturning(returning = "object",pointcut = "log()") //切点里的return之后执行的方法,就是打印return的内容
public void doAfterReturning(Object object){
logger.info("response={}",object);
}
}