springboot

本文详细介绍了SpringBoot的多环境配置,包括单文件和多文件配置方式。此外,讲解了Thymeleaf模板引擎的使用、Valid验证、全局异常处理和MyBatis-SpringBoot整合。还涉及Redis缓存的多种操作以及Guava工具类的使用,并展示了如何在项目中集成Swagger3进行API文档管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

springboot

一:多环境配置

//表示当前启用的环境
spring:
  profiles:
    active: dev

用两种方式进行多环境的配置

1、在单文件中进行多环境配置

使用 — 进行多环境进行区分

spring:
  profiles:
    active: dev

#第一个环境配置
---
server:
  port: 8081
spring:
  profiles: dev

#第二个环境配置
---

server:
  port: 8082
spring:
  profiles: test

#第三个环境配置
---
server:
  port: 8083
spring:
  profiles: prod

2、创建多个文件进行多环境的配置

命名格式为application-*.yaml

一般创建三个文件,分别为application-dec.yaml application-prod.yaml application-test.yaml

以application-dec.yaml为例

server:
  port: 8080
#  servlet:
#    context-path: /fy22

env:
  name: 开发环境
  
#  等等等

二:thymeleaf

导入maven依赖

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

用处不多,都是前后端分离开发,去百度查询怎么使用

三:valid验证

1、创建实体类,并在实体类中添加对应的属性限制

package com.example.fy22_springboot.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;

/**
 * @author : panghuhu-Li
 * @date : Created in 2022/5/31 15:52
 * @description: no
 * @modified By: lxz
 */

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Book {

    private int id;
    @NotEmpty(message = "书名不能为空")
    @Size(min = 2,max = 20,message = "书名长度必须在1~20之间")
    private String name;

    @Min(value = 1,message = "价格至少一元")
    @Max(value = 100,message = "价格不能查过100元")
    private int price;
    private String author;
    private String publish;

}

在controller层对注入的属性进行验证

    @RequestMapping("path")
    public String testValid(@Valid Book){
        return "";
    }

四:异常捕获

//专门用来处理异常的类,也叫全局异常监听类
//相当于切面
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = {Exception.class})//申明捕获哪个异常类
    public String exceptionDemo() {
        return "自定义异常返回";
    }

}

五:mybatis—springboot整合

1、依赖项导入

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.8</version>
        </dependency>

2、yaml文件配置

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/fy_ssm?serverTimezone=UTC&characterEncoding=UTF-8&useSSL=false
    username: root
    password: 123456
    type: com.alibaba.druid.pool.DruidDataSource
mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml
  type-aliases-package: 包所在位置

六:redis缓存数据库的使用

卸载服务:redis-server --service-uninstall

开启服务:redis-server --service-start

停止服务:redis-server --service-stop

1、String使用

设置值
set [key] [value]
set 1001 zhangsan
获取值
get [key]
get 1001
获取并重新赋值
getset [key] [newValue]
getset 1001 pangliu
变量+1
incr [key]
incr count
变量-1
decr [key]
decr count
追加内容
append [key] [valux]
批量插入
mset [k1] [v1] [k2] [v2]
批量读取
mget [k1] [k2]

2 、list使用

向list中添加一条数据 左加
lpush [key] [values]    //lpush每次都会将数据填加到数据的头部 是left push的缩写
lpush mylist zhangsan

查询指定范围内的数据
lrange [key] [fromIndex] [endIndex]

向list中插入一条数据  右插(保证list中的数据和插入的顺序一致,使用该命令)
rpush [key] [values]
rpush mylist sunwukong

根据下标获取list中的元素
lindex [key] [index]
lindex mylist 2 (取出下标是2的数据,下标是从0开始的)

获取截取的内容 其余删除
ltrim [key] [index1] [index2]
ltrim mylist 1 3 (只保留1-3这几个位置的数据,其他的都删掉)

从list头部拿出一个数据
lpop [key]
lpop mylist

从list尾部拿出一个数据
rpop [key]
rpop mylist

3、hash结构使用

hash结构   数据很多的话存放在hash结构里 数据量较少的话存放在string结构里
每个hash的key里是有多个键值对的
hset [key] [field] [value]
hset myhash 1001 sunwukong

根据key和field从hash中取值
hget [key] [field]
hget myhash 1001

判断hash中是否存在filed
hexists [key] [field]
hexists myhash 1001

删除一个field
格式:  hdel  [key]  [field]
例:   hdel   myhash  1001


获取hash里面的field的数量
格式: hlen  [key] 
例:   hlen   myhash 

获取hash里所有的field
格式:  hkeys  [key]
例:   hkeys  myhash


获取hash里所有的value
格式:   hvals  [key]
例:    hvals  myhash

获取hash里所有的键值对
格式:  hgetall  [key]
例:   hgetall  myhash

5、springboot中redis使用

在使用redis时我们要确保redis服务器一直处于开启状态

1)引入依赖
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>

2)yaml配置

spring:
  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    timeout: 1000
    jedis:
      pool:
        max-idle: 8
        min-idle: 4
        max-active: 8
3)配置序列化格式

由于将内容存入到redis编码格式不同,我们需要对存入和取出的编码进行配置。需要对字符串,对象等进行序列化和反序列化。

@Configuration
public class BeanConfig {

/*    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        //创建字符串类型的序列化对象
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        //在java中想要让redis存储对象,就需要把对象进行序列化,转换一定格式的字符串然后进行存储
        //创建一个支持任意类型序列化的对象
        Jackson2JsonRedisSerializer json=new Jackson2JsonRedisSerializer(Object.class);

        ObjectMapper om=new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        json.setObjectMapper(om);

        //解决key前面有一串乱码的问题
        template.setKeySerializer(stringRedisSerializer);
        //值的序列化方式选择json的形式
        template.setValueSerializer(json);
        return template;
    }*/
    

    @Bean
    @ConditionalOnClass(RedisOperations.class)
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        //序列化包括类型描述 否则反向序列化实体会报错,一律都为JsonObject
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(mapper);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用 String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的 key也采用 String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用 jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的 value序列化方式采用 jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        return template;
    }

}

4)基本操作

通过查询的缓存业务逻辑来演示其基本使用

基本流程

1、从缓存中查询图书列表
2、如果查到了,则直接返回给调用方
3、如果没有查到,则去数据库中查询
4、如果没有查到,则去数据库中查询
5、如果数据库查到了,则需要把数据添加到缓存中一份,方便下次从缓存中查

查询业务

	public List<Book> selectAll() {
        //查询里加缓存的业务逻辑
        /*
        1、从缓存中查询图书列表
        2、如果查到了,则直接返回给调用方
        3、如果没有查到,则去数据库中查询
        4、如果没有查到,则去数据库中查询
        5、如果数据库查到了,则需要把数据添加到缓存中一份,方便下次从缓存中查
         */
        String key = "book_list";
        Object book_list = redisTemplate.opsForValue().get(key);
        if (book_list != null) {
            System.out.println("缓存命中");
            return (List<Book>) book_list;
        }
        List<Book> books = bookDao.selectAll();
        if (books != null) {
            System.out.println("从数据库中查询并添加到缓存里");
            redisTemplate.opsForValue().set(key, books);
        }
        return books;
    }

	@Transactional
    public int add(Book book) {
        //添加数据库的时候需要删除缓存,否则数据库和缓存会发生不一致的问题
        redisTemplate.delete("book_list");
        book.setId(AI.incrementAndGet());
        System.out.println("添加了" + bookDao.insert(book));
        return 1;
    }

    public int delete(int id) {
        //删除数据库的时候需要删除缓存,否则数据库和缓存会发生不一致的问题
        redisTemplate.delete("book_list");
        return bookDao.deleteById(id);
    }

    public int update(Book book) {
        //修改数据库的时候需要删除缓存,否则数据库和缓存会发生不一致的问题
        redisTemplate.delete("book_list");
        return bookDao.update(book);
    }

    public Book getBookById(int id) {
        return bookDao.selectById(id);
    }

通过set方法也能对加入的key-value设置过期时间

redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);

七:工具类guava使用

导入以来项

		<dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>22.0</version>
        </dependency>

项目中整合swagger3

1、文档接口添加依赖

		<dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>

2、在springboot2.6版本以上的需要添加

spring.mvc.pathmatch.matching-strategy=ant_path_matcher

3、在配置类中配置swaggeer的类

	@Bean
    public Docket createRestApi() {
        Docket docket = new Docket(DocumentationType.OAS_30)
                .apiInfo(apiInfo())
                .select()
                //设置通过什么方式定位需要自动生成文档的接口,我们这里采用定位方法上的apiOperation注解的方式
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .build();
        return docket;
    }

    private ApiInfo apiInfo() {
        ApiInfo info = new ApiInfoBuilder().title("Swagger3接口文档")
                .description("自动生成的接口文档,有问题联系开发工程师")
                .contact(new Contact("李星泽", "https://www.baidu.com", "abc@anc.com"))
                .version("1.0.1")
                .build();
        return info;
    }

4、在启动类中添加注解

//开启swagger文档注解
@EnableOpenApi

5、在需要添加注释信息的类上添加

@Api(tags = "学生管理api接口")
@RestController
public class StudentController {

    @ApiOperation(value = "通过学号查询学生")
    //这个注解的作用是对请求参数的解释
    @ApiImplicitParam(name = "no", value = "学号", required = true, dataType = "String")
    @GetMapping("selectByNo")
    public BaseResult<Student> selectByNo(String no) {
        Student student = new Student();
        student.setNo(no);
        student.setName("张三");
        student.setAge(21);
        student.setEmail("123456789");
        student.setPhone("110");
        student.setAddress("哈尔滨");

        BaseResult<Student> result = new BaseResult<>();
        result.setCode(1);
        result.setMsg("success");
        result.setData(student);
        return BaseResult.success(ResultCode.SUCCESS, student);
    }

    @ApiOperation(value = "添加学生信息")
    @PostMapping("insert")
    public BaseResult<String> insert(@RequestBody Student student) {
        return BaseResult.success(ResultCode.SUCCESS, "ok");
    }

    @PutMapping("update")
    @ApiOperation(value = "修改学生信息")
    public BaseResult<String> update(Student student) {
        return BaseResult.success(ResultCode.SUCCESS, "ok");
    }

    @DeleteMapping("delete")
    @ApiOperation(value = "删除学生信息")
    @ApiImplicitParam(name = "no", value = "学号", required = true, dataType = "String")
    public BaseResult<String> delete(String no) {
        return BaseResult.success(ResultCode.SUCCESS, "ok");
    }
}

注:我们可以设置自己返回前端的基本数据格式,上面代码中的BaseResulet就是自己设置的格式

@Data
public class BaseResult<T> {

    @ApiModelProperty(value = "状态码"
            , allowableValues = "1001,1002,1003"
            , example = "1002"
            , required = true
            , allowEmptyValue = false)
    private int code;
    @ApiModelProperty(value = "描述信息",example = "success")
    private String msg;
    @ApiModelProperty("数据")
    private T data;


    public static <T> BaseResult<T> success(ResultCode code, T data) {
        BaseResult<T> result = new BaseResult<>();
        result.setCode(code.getCode());
        result.setMsg(code.getMsg());
        result.setData(data);
        return result;
    }

    public static BaseResult fail(ResultCode code) {
        BaseResult res = new BaseResult<>();
        res.setCode(code.getCode());
        res.setMsg(code.getMsg());
        return res;
    }
}

public enum ResultCode {
    SUCCESS(1001, "SUCCESS"),
    FAIL(2001, "FAIL");

    int code;
    String msg;

    ResultCode(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }
}

6、访问地址 http://127.0.0.1:8080/swagger-ui/index.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

panghuhu-Li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值