01.两小时学会springboot-入门

一、说明

本博客基于《慕课网-2小时快速上手SpringBoot》,本地工程对应:E:\01.study\04.springboot\imooc2hours\hello-springboot

springboot是啥这里不过多介绍,自行google,本篇文章作为springboot系列文章的开篇之作,意在短时间内完成一个最简单springboot的入门示例,让读者可以对其大致有个了解,每部分深入详细介绍将在后续文章中介绍。

二、新建一个springboot项目,简单运行helloworld

这里使用IDEA创建,也可以使用spring官网(http://start.spring.io)在线创建

1、新建一个springboot项目

2、输入groupID、artifactID,next

3、选择一个非SNAPSHOT版本,这里使用2.1.X而不是2.2.X

4、输入项目名称,选择路径(路径不要有中文、不要有空格),点击finish

5、创建项目后,添加一个Controller

package com.mzj.hellospringboot;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String say(){
        return "mazhongjia";
    }
}

6、启动项目:

方式1:运行自动创建的:HelloSpringbootApplication类

方式2:通过进入项目根目录,执行mvn spring-boot:run命令启动

方式3:①先将项目打包:mvn clean package -Dmaven.test.skip=true -U②运行生成的jar包:java -jar target/xxxx.jar

7、测试

1)通过浏览器访问:http://127.0.0.1:8080/hello

2)通过curl访问:curl http://127.0.0.1:8080/hello

三、配置简介

1、配置文件路径

springboot的配置文件有两种类型:①application.properties②application.yml(推荐)

maven项目位于:src\main\resources\application.properties

2、代码注解中引入配置项

1)在yml中自定义配置项:注意value值前面要有空格(yml格式)

2)使用配置项:

单个配置项使用@Vlaue注解引用

3、配置中引入配置

4、配置太多、太分散时使用【对象配置类】进行优化

1)给配置定义一个前缀:这里时myconfig(注意这里前缀不能大些字母)

注意:前缀下的配置项要前面空2格

2)建立【对象配置类】

使用@Component @ConfigurationProperties(prefix = "myconfig")注解,其中prefix值为前缀

package com.mzj.hellospringboot;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;

@Component
@ConfigurationProperties(prefix = "myconfig")
public class MyConfig {

    private BigDecimal minMoney;

    private String description;

    public BigDecimal getMinMoney() {
        return minMoney;
    }

    public void setMinMoney(BigDecimal minMoney) {
        this.minMoney = minMoney;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

3)使用类中,通过Autowired自动装载

@RestController
public class HelloController {

    @Autowired
    private MyConfig myConfig;

    @GetMapping("/hello")
    public String say(){
        return "mazhongjia : " + myConfig.getMinMoney()+"----"+myConfig.getDescription();
    }
}

4)测试结果:

这种简化写法的好处是:不用在每一个变量上使用@Value,一个个的注解、分散定义

什么时候单个定义、什么时候统一定义一个配置类中?看业务需要

5、多环境支持

application-dev.yml

server:
  port: 8081
  servlet:
    context-path: /mazhongjia

myconfig:
  minMoney: 0.001
  description: 我们的配置项是${myconfig.minMoney}吧

application-fac.yml

server:
  port: 8081
  servlet:
    context-path: /mazhongjia

myconfig:
  minMoney: 1
  description: 我们的配置项是${myconfig.minMoney}吧

application.yml

spring:
  profiles:
    active: dev

spring.profiles.active改成fac:

在发布生产时,可以不用修改application.yml,使用:指定-Dspring.profiles.active=dev去设置:

①通过mvn clean package打包后,允许jar包时执行如下命令:

java -jar -Dspring.profiles.active=fac target/hello-springboot-0.0.1-SNAPSHOT.jar

四、Controller

1、类相关注解

注解说明
@Controller处理http请求
@RestController

Spring4之后新加的注解,原来返回json(字符串)需要@ResponseBody+@Controller,ResponseBody可以修饰在类上,也可以修饰在方法上

现在,只需要@RestController这一个注解即可

也就是@RestController=@ResponseBody+@Controller

@RequestMapping配置url映射

什么情况下使用@ResponseBody+@Controller?

答:在同一个Controller中,有的方法想返回html网页时

比如:下面的Controller声明中返回的hh会被识别为字符串

而下面的Controller声明(去掉@ResponseBody)返回的hh会被识别为html文件名

2、能够返回网页

说明1:类似于spring mvc中InternalResourceViewResolver效果:controller返回字符串,对应到网页文件名

说明2:此种方式使用较少,因为现在都是前后端相分离的开发模式

说明3:通常以模板渲染的方式实现:

1)增加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

2)增加html网页

3)Controller注解为@Controller

4)Controller对应方法返回hh

HelloController4Html.java

package com.mzj.hellospringboot;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HelloController4Html {

    @Autowired
    private MyConfig myConfig;

    @GetMapping("/hello1")
    public String say(){
        return "hh";
    }
}

5)启动springboot,输入网址:http://localhost:8081/mazhongjia/hello1

结果:

3、不同的URL都请求到同一个controller的同一个方法

HelloController.java

@GetMapping({"hello2","hello3"})
    public String say2ForOne(){
        return "say2ForOne : " + myConfig.getMinMoney()+"----"+myConfig.getDescription();
    }

运行结果:启动服务器,访问:http://localhost:8081/mazhongjia/hello3http://localhost:8081/mazhongjia/hello2

结果相同:

4、Controller中一般在类上通过@RequestMapping注解定义这个Controller的不同method相同的URL部分

5、Controller中方法注解

5.1 Controller方法上使用@RequestMapping,而不是@GetMapping、@PostMapping,可以支持Get+Post两种类型请求访问

但是这种方式不好,最佳实践:使用@GetMapping、@PostMapping替代@RequestMapping,两种注解实现方式不一样

5.2 获取请求中参数

注解名说明
@PathVariable获取url中的数据
@RequestParam从请求中获取(获取请求参数的值),body或者?后面的数据

1)@PathVariable

此种方式URL比较简洁

HelloController.java

@GetMapping({"/say/{id}")
    public String say2PathVariable(@PathVariable("id") Integer id){
        return "id : " + id;
    }

2)@RequestParam

HelloController.java

@GetMapping("/say2")
    public String say2RequestParam(@RequestParam("id") Integer id){
        return "id:RequestParam : " + id;
    }

注意:使用@RequestParam方式时,方法参数注解中的"id"对应url中?后面的key

扩展:使用@RequestParam方式时,参数设置非必须,不传时设置默认值

HelloController.java

@GetMapping("/say3")
    public String say2RequestParam2(@RequestParam(value = "id",required = false,defaultValue = "-1") Integer id){
        return "id:RequestParam2 : " + id;
    }


注意:如果请求类型为Post,则传递的参数的方式可以多样化(通过URL param携带、通过body携带....等等)

 

以下两种POST请求设置参数id的位置,都可以在服务端通过@RequestParam接收(上图)

这是因为,springboot框架对post类型请求传递参数进行了兼容,只要使用@RequestParam注解,就可以实现对不同位置传递参数的接收。

这里推荐用参数在body的x-www-form-urlencoded的方式:因为多数人使用这种方式:)

五、数据库访问:Spring-Data-JPA

JPA(Java Persistence API):定义了一系列对象持久化的标准,目前实现这一规范的产品有Hibernate、TopLink等。

Spring-Data-JPA就是springboot对hibernate的整合,让开发者更加方便的使用:不用写一行sql语句,就可以完成对数据库的操作。

示例:通过实现如下四个URL请求(restful风格的API),来演示spring-data-jpa的使用

1、获取红包列表:GET、/luckymoneys

2、创建一个红包:POST、/luckymoneys

3、通过id查询红包:GET、/luckymoneys/id

4、通过id更新红包:PUT、/luckymoneys/id

1、引入依赖

  • springboot中spring data jpa依赖
  • 使用的数据库依赖,这里是mysql
<!--spring data jpa-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

2、增加数据库配置

application.yml中增加:

spring:
  datasource:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/luckymoney
      username: root
      password: 123456

注意:设置数据库驱动时有两个选项:

要选择新版本驱动,不要选择旧版本

3、增加jpa的配置

  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

其中ddl-auto:

ddl-auto:create----每次运行该程序,如果表已经存在,则先删除,再创建

ddl-auto:create-drop----每次程序结束的时候会清空表

ddl-auto:update----每次运行程序,如果表已经存在,则不会删除,表内有数据不会清空,只会更新

ddl-auto:validate----运行程序会校验数据与数据库的字段类型是否相同,不同会报错

show-sql:控制台上显示执行的sql语句,方便开发调试

4、新建数据库

报错处理

此时启动springboot会报错:

You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.

解决办法:

此时,可以正常启动.

5、创建实体类(不需要手工建表,通过实体类spring-data-jpa可以自动创建表)

package com.mzj.hellospringboot.luckymoney;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.math.BigDecimal;

@Entity
public class Luckymoney {

	@Id//声明该属性为主键
	@GeneratedValue//声明该列自动生成
	private Integer id;

	private BigDecimal money;

	/**
	 * 发送方
	 */
	private String producer;

	/**
	 * 接收方
	 */
	private String consumer;

	public Luckymoney() {
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public BigDecimal getMoney() {
		return money;
	}

	public void setMoney(BigDecimal money) {
		this.money = money;
	}

	public String getProducer() {
		return producer;
	}

	public void setProducer(String producer) {
		this.producer = producer;
	}

	public String getConsumer() {
		return consumer;
	}

	public void setConsumer(String consumer) {
		this.consumer = consumer;
	}
}

其中使用的注解,都是JPA中的标准注解(javax.persistence包下):

@Id注解:设置表的主键

@GeneratedValue注解:设置该列自增(自增会自动创建序列)

@Entity注解:

创建实体类后,启动springboot会自动创建对应表:

  • 如果表自增列对应的序列存在则先删除
  • 如果表存在则先删除
  • 创建序列
  • 创建表

6、示例开发

1)创建Controller:LuckymoneyController

用@RestController注解标记类

2)创建DAO接口:JPA中约定叫XXRepository:LuckmoneyRepository

继承extends JpaRepository<A,B>,其中泛型:A:对应的数据库实体类,B:数据库主键类型

继承该接口后,就自带了很多通用的方法,可以直接使用,如果需要特殊的再进行扩展

package com.mzj.hellospringboot.luckymoney;

import org.springframework.data.jpa.repository.JpaRepository;

/**
 *  泛型:A:对应的数据库实体类,B:数据库主键类型
 */
public interface LuckmoneyRepository extends JpaRepository<Luckymoney,Integer> {
}

3)在Controller中Autowired这个DAO接口

4)使用Dao接口实现业务逻辑

  • 获取红包列表:GET、/luckymoneys
  • 创建一个红包:POST、/luckymoneys
  • 通过id查询红包:GET、/luckymoneys/id
  • 通过id更新红包:PUT、/luckymoneys/id

完整的Controller如下:

package com.mzj.hellospringboot.luckymoney;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;

@RestController
public class LuckymoneyController {

    @Autowired
    private LuckmoneyRepository luckmoneyRepository;

    /**
     * 获取红包列表
     *
     * @return
     */
    @GetMapping("/luckymoneys")
    public List<Luckymoney> list() {
        return luckmoneyRepository.findAll();
    }

    /**
     * 创建红包
     */
    @PostMapping("/luckymoneys")
    public Luckymoney create(@RequestParam("producer") String producer,
                             @RequestParam("money") BigDecimal money) {
        Luckymoney luckymoney = new Luckymoney();
        luckymoney.setProducer(producer);
        luckymoney.setMoney(money);
        return luckmoneyRepository.save(luckymoney);
    }

    /**
     * 通过id查询红包
     *
     * @param id
     * @return
     */
    @GetMapping("/luckymoneys/{id}")//这里的id对应@PathVariable("id")的id
    public Luckymoney findById(@PathVariable("id") Integer id) {
        return luckmoneyRepository.findById(id).orElse(null);//如果查不到返回null
    }

    /**
     * 更新红包
     *
     * @param id
     * @param consumer
     * @return
     */
    @PutMapping("/luckymoneys/{id}")
    public Luckymoney update(@PathVariable("id") Integer id,
                             @RequestParam("consumer") String consumer) {
        //更新操作需要首先查询出需要更新的整条记录,然后设置修改的内容
        Optional<Luckymoney> optionalLuckymoney = luckmoneyRepository.findById(id);
        //在使用这个对象进行更新
        if (optionalLuckymoney.isPresent()) {//判断是否查询到这个id的记录
            Luckymoney luckymoney = optionalLuckymoney.get();
            luckymoney.setConsumer(consumer);
            return luckmoneyRepository.save(luckymoney);//更新与创建使用的都是save接口,区别是,是否传递主键
        }
        return null;
    }
}

使用postman测试

  • 获取红包列表:localhost:8081/mazhongjia/luckymoneys
  • 创建一个红包:localhost:8081/mazhongjia/luckymoneys  producer:mazhongjia123,,,,money:100
  • 通过id查询红包:localhost:8081/mazhongjia/luckymoneys/1
  • 通过id更新红包:localhost:8081/mazhongjia/luckymoneys/5  consumer:XIAOMAGE

7、事务

事务操作一般都放在Service层中

1)创建LuckymoneyService

2)用@Service注解修饰该类

3)在Service中Autowired这个DAO接口

4)在Service中编写业务代码(这里是发送两个红包),并用@Transactional

注解修饰这个方法

注:要使用spring包的Transactional注解

完整service代码:

package com.mzj.hellospringboot.luckymoney;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

@Service
public class LuckymoneyService {

    @Autowired
    private LuckmoneyRepository luckmoneyRepository;

    @Transactional
    public void createTwo(){
        Luckymoney luckymoney1 = new Luckymoney();
        luckymoney1.setProducer("mazhongjia");
        luckymoney1.setMoney(new BigDecimal("520"));

        luckmoneyRepository.save(luckymoney1);

        Luckymoney luckymoney2 = new Luckymoney();
        luckymoney2.setProducer("mazhongjia");
        luckymoney2.setMoney(new BigDecimal("1314"));

        luckmoneyRepository.save(luckymoney2);
    }
}

5)为Service编写Controller方法

 /**
     *  事务示例:一起发送两个红包,要么全成功,要么全失败
     */
    @PostMapping("/luckymoneys/two")
    public void createTwo(){
        luckymoneyService.createTwo();
    }

6)在Controller中Autowired这个Service

    @Autowired
    private LuckymoneyService luckymoneyService;

原理:这里所说的事务指的是数据库事务,比如mysql,所以事务的功能,是数据库提供的,而不是java程序的事务,这里的注解是程序帮助我们自动执行commit、回滚等操作,最终这些提交都是提交给数据库的,所以需要数据库首先支持事务,有些数据库不支持事务,即使这里加了注解也没有用;至于mysql比较特殊,默认建表是MyISAM引擎,这种引擎下是不支持事务的,需要修改表的引擎为InnoDB引擎才支持事务。

实际开发中,事务应用非常广泛,比如买东西时创建订单与扣库存,必须在一个事务中,要么全成功,要么全失败。

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值