springboot框架应该具备的工具和配置

        很多时候我们新建好项目框架好,都是直接开发功能代码,但是在此之前我们还可以先把项目通用的工具,响应数据类给封装好。

这里不写创建框架的过程,IDEA创建一个SpringBoot可以参考以下链接(其中一个)。

https://blog.csdn.net/weixin_42009068/article/details/104443191

https://blog.csdn.net/weixin_42009068/article/details/104465376


1. 项目配置信息

 在resources下新建application.yml、application-dev.yml、application-prod.yml,dev为开发环境的配置,prod为生产环境。

application.yml

spring:
  application:
    name: demo_name # 应用名
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    serialization:
      FAIL_ON_EMPTY_BEANS: false
  profiles:
    # 本地开发测试时配置为local或dev,打包时采用动态配置@profiles.active@
    #active: @profiles.active@
    active: dev

server:
  tomcat:
    max: 1000
    max-connections: 20000

在dev或者prod文件中,需要配置服务端口,数据库连接,数据源等吗,对应在不同的开发环境,管理不同的配置信息。

dev

server:
  port: 12141
  tomcat:
    uri-encoding: UTF-8
  servlet:
    context-path: /smart
    encoding:
      force-response: true

spring:
  # 配置文件上传下载
  mvc:
    static-path-pattern: /**
  web:
    resources:
      static-locations: file:D:\fileUpload\eshore\cpgh\smart_community\resources # 配置静态资源访问路径
  servlet:
    multipart:
      max-file-size: 10MB # 单个文件大小
      max-request-size: 50MB # 总上传文件大小
  # 数据配置
  datasource:
    # mysql
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
    username: root
    password: 123456
    #    driverClassName: dm.jdbc.driver.DmDriver
    #    url: jdbc:dm://127.0.0.1
    #    username: dc
    #    password: 123456
    # 使用druid数据源
    type: com.alibaba.druid.pool.DruidDataSource
    sql-script-encoding: UTF-8
    # 数据源高级配置
    # 初始化大小,最小,最大
    initialSize: 20
    minIdle: 30
    maxActive: 80
    # 配置获取连接等待超时的时间
    maxWait: 600000
    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    timeBetweenEvictionRunsMillis: 600000
    # 配置一个连接在池中最小生存的时间,单位是毫秒
    minEvictableIdleTimeMillis: 3600000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,log4j2
    maxPoolPreparedStatementPerConnectionSize: 80
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
  # Redis服务配置
  redis:
    # Redis数据库索引(默认为0)
    database: 0
    # Redis 服务器地址
    host: xx.xx.xx.xx
    # Redis服务器连接端口
    port: 6379
    # Redis 服务器连接密码(默认为空)
    password: 123456
    jedis:
      pool:
        max-active: 8 # 连接池最大连接数(使用负值表示没有限制
        max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制
        max-idle: 8 # 连接池中的最大空闲连接
        min-idle: 0 # 连接池中的最小空闲连接
    # 连接超时时间(毫秒)
    timeout: 20000

prod

server:
  port: 9090
  tomcat:
    uri-encoding: UTF-8
  servlet:
    context-path: /smart
    encoding:
      force-response: true

spring:
  # 配置文件上传下载
  mvc:
    static-path-pattern: /**
  web:
    resources:
      static-locations: /home/eshore/cpgh/smart_community/resources # 配置静态资源访问路径
  servlet:
    multipart:
      max-file-size: 10MB # 单个文件大小
      max-request-size: 50MB # 总上传文件大小
  # 数据配置
  datasource:
    # mysql
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
    username: root
    password: 123456
    #    driverClassName: dm.jdbc.driver.DmDriver
    #    url: jdbc:dm://127.0.0.1
    #    username: dc
    #    password: 123456
    # 使用druid数据源
    type: com.alibaba.druid.pool.DruidDataSource
    sql-script-encoding: UTF-8
    # 数据源高级配置
    # 初始化大小,最小,最大
    initialSize: 20
    minIdle: 30
    maxActive: 80
    # 配置获取连接等待超时的时间
    maxWait: 600000
    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    timeBetweenEvictionRunsMillis: 600000
    # 配置一个连接在池中最小生存的时间,单位是毫秒
    minEvictableIdleTimeMillis: 3600000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,log4j2
    maxPoolPreparedStatementPerConnectionSize: 80
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
  # Redis服务配置
  redis:
    # Redis数据库索引(默认为0)
    database: 0
    # Redis 服务器地址
    host: xxx.xx.xx.xx
    # Redis服务器连接端口
    port: 6379
    # Redis 服务器连接密码(默认为空)
    password: 123456
    jedis:
      pool:
        max-active: 8 # 连接池最大连接数(使用负值表示没有限制
        max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制
        max-idle: 8 # 连接池中的最大空闲连接
        min-idle: 0 # 连接池中的最小空闲连接
    # 连接超时时间(毫秒)
    timeout: 0

2. 项目通用类封装

2.1 封装统一数据响应类

public class ResponseMessage<T> implements Serializable {
    private static final int STATUS_SUCCESS = 0; //成功
    private static final int STATUS_FAIL = 1; //失败

    /**
     * 成功与否代码
     * 成功为0 失败为1
     */
    private int status;
    /**
     * 返回响应信息
     */
    private String msg;
    /**
     * 返回对象、数据信息 T => int long String array list map等等
     */
    private T data;

    /**
     * 返回成功与否代码
     * @param status 成功为0 失败为1
     */
    private ResponseMessage(int status){
        this.status=status;
    }

    /**
     * 返回数据跟判断代码
     * @param status
     * @param data
     */
    private ResponseMessage(int status,T data){
        this.status=status;
        this.data=data;
    }

    /**
     * 返回判断代码、数据、响应信息
     * @param status
     * @param msg
     * @param data
     */
    private ResponseMessage(int status, String msg, T data) {
        this.status = status;
        this.msg = msg;
        this.data = data;
    }

    /**
     * 返回判断代码、响应信息
     * @param status
     * @param msg
     */
    private ResponseMessage(int status, String msg) {
        this.status = status;
        this.msg = msg;
    }

    @JsonIgnore //返回时忽略掉这个属性
    public boolean isSuccess() {
        return this.status == STATUS_SUCCESS;
    }

    public int getStatus() {
        return this.status;
    }

    public T getData() {
        return this.data;
    }

    public String getMsg() {return this.msg;}


    public static <T> ResponseMessage<T> createBySuccess() {
        return new ResponseMessage<T>(STATUS_SUCCESS);
    }


    public static <T> ResponseMessage<T> createBySuccessMessage(String msg) {
        return new ResponseMessage<T>(STATUS_SUCCESS, msg);
    }

    public static <T> ResponseMessage<T> createBySuccess(T data) {
        return new ResponseMessage<T>(STATUS_SUCCESS, data);
    }

    public static <T> ResponseMessage<T> createBySuccess(String msg, T data) {
        return new ResponseMessage<T>(STATUS_SUCCESS, msg, data);
    }

    public static <T> ResponseMessage<T> createByError() {
        return new ResponseMessage<T>(STATUS_FAIL, "请与管理员联系");
    }

    public static <T> ResponseMessage<T> createByError(T data) {
        return new ResponseMessage<T>(STATUS_FAIL, data);
    }

    public static <T> ResponseMessage<T> createByErrorMessage(String msg) {
        return new ResponseMessage<T>(STATUS_FAIL, msg);
    }

    public static <T> ResponseMessage<T> createByErrorCodeMessage(int errorCode, String msg) {
        return new ResponseMessage<T>(errorCode, msg);
    }

    @Override
    public String toString() {
        return "ResponseMessage{" +
                "status=" + status +
                ", msg='" + msg + '\'' +
                ", data=" + data +
                '}';
    }
}

2.2 分页函数

@Data
@ToString
@ApiModel(value="Paper分页参数", description="分页参数")
public class Paper<T> {
    @ApiModelProperty(value = "当前页码",required = true)
    private long current; // 当前页码
    @ApiModelProperty(value = "总页数",required = true)
    private long pages; // 总页数
    @ApiModelProperty(value = "每条记录数",required = true)
    private long size; // 每条记录数
    @ApiModelProperty(value = "查询总记录数",required = true)
    private long total; // 查询总记录数
    @ApiModelProperty(value = "数据",required = true)
    private List<T> data;
}

2.3 用户session保存

public class LoginSessionMap {

    private static final Map<String, Map<String, String>> SESSION = new ConcurrentHashMap<>();

    /**
     * 添加登录session_key,openid
     * @param loginSession
     * @param map
     */
    public static void put(String loginSession, Object map) {
        SESSION.put(loginSession, (Map<String, String>) map);
    }

    /**
     * 判断是否存在key,也就是是否登录
     * @param loginSession
     * @return
     */
    public static boolean containsKey(String loginSession) {
        return SESSION.containsKey(loginSession);
    }

    /**
     * 获取
     * @param loginSession
     * @return
     */
    public static Map<String, String> get(String loginSession) {
        return SESSION.get(loginSession);
    }

    /**
     * 清除过期session
     * @param loginSession
     */
    public static void clear(String loginSession) {
        SESSION.remove(loginSession);
    }
}

3. 基础配置Config

在写好配置文件以及通用的数据响应类后,就可以配置项目的基础配置了,例如数据源的使用,线程池的配置,okHttp客户端的配置使用等等,下面只举例两个的配置.

3.1 druid数据源配置

pom依赖

<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.5</version>
</dependency>

配置类

@Configuration
public class DruidConfiguration {
    //定义日志信息对象
    private static final Logger logger= LoggerFactory.getLogger(DruidConfiguration.class);

    @Bean //声明为bean实例
    @Primary //在同样的Source中,首先使用被标注的DataSource
    @ConfigurationProperties(prefix = "spring.datasource") //加载配置文件的前缀application-dev.yml
    public DataSource dataSource(){
        logger.info("init Druid____正在初始化Druid......");
        return DataSourceBuilder.create().type(com.alibaba.druid.pool.DruidDataSource.class).build();
    }

    /**
     * 配置servlet管理后台
     * @return
     */
    @Bean
    public ServletRegistrationBean druidServlet() {
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        // IP白名单 加入白名单可以不用登录
//        servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
        // IP黑名单(共同存在时,deny优先于allow)
        // servletRegistrationBean.addInitParameter("deny", "192.168.0.000");
        //控制台管理用户
        servletRegistrationBean.addInitParameter("loginUsername", "druid");
        servletRegistrationBean.addInitParameter("loginPassword", "123456");
        //是否能够重置数据 禁用HTML页面上的“Reset All”功能
        servletRegistrationBean.addInitParameter("resetEnable", "false");
        return servletRegistrationBean;
    }

    /**
     * 配置web监控filter
     * @return
     */
    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
        return filterRegistrationBean;
    }
}

3.2 mybatis-plus配置

pom依赖

<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3</version>
</dependency>

配置文件

@Configuration
public class MybatisPlusPageConfig {
    /**
     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

其他的类似于redis、线程池、fastJson那些就不一一放出来了,文章末尾会放源码地址。

4. 项目常用工具类封装

针对项目的不同业务需求,我们应该对经常使用的功能做一个统一的封装,减少代码的冗余,下面简单介绍几个常用的工具类。

4.1 利用easypoi实现excle导出导入

pom依赖

<!-- 导出Excel -->
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-base</artifactId>
    <version>3.0.3</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-web</artifactId>
    <version>3.0.3</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-annotation</artifactId>
    <version>3.0.3</version>
</dependency>

ExcleUtils.java

* Workbooks 集合包含 Microsoft Excel 中当前打开的所有 Workbook 对象。
*
* workbook分别有HSSFWorkbook、XSSFWorkbook、SXSSFWorkbook
* HSSFWorkbook:针对EXCEL 2003版本,扩展名为.xls,此种的局限就是导出的行数最多为65535行。因为导出行数受限,不足7万行,所以一般不会发送内存溢出(OOM)的情况
*
* *** XSSFWorkbook:由于第一种HSSF的局限性产生的,因为其导出行数较少,XSSFWorkbook应运而生,其对应的是EXCEL2007+ ,
* 扩展名为.xlsx ,最多可以导出104万行,不过这样就伴随着一个问题–OOM内存溢出。
* 因为使用XSSFWorkbook创建的book sheet row cell 等是存在内存中的,并没有持久化到磁盘上,
* 那么随着数据量的增大,内存的需求量也就增大。
*
* SXSSFWorkbook:SXSSFWorkbook可以根据行数将内存中的数据持久化写到文件中。
* 此种的情况就是设置最大内存条数,比如设置最大内存量为5000行, new SXSSFWookbook(5000),
* 当行数达到 5000 时,把内存持久化写到文件中,以此逐步写入,避免OOM。这样就完美解决了大数据下导出的问题
public class ExcelUtils {

    /**
     * 导入excle数据
     * @param file 文件
     * @param headerRows 忽略头行数
     * @param pojoClass 转换的实体
     * @param <T> 返回的集合
     * @return
     */
    public static <T> List<T> importData(MultipartFile file, Integer headerRows,
                                         Class<T> pojoClass){
        if (file == null) {
            return null;
        }
        ImportParams params = new ImportParams();
        params.setHeadRows(headerRows);
        List<T> list = null;
        try {
            list = ExcelImportUtil.importExcel(file.getInputStream(), pojoClass, params);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 导出excel表格
     * @param list 导出的数据
     * @param title 文件标题
     * @param sheetName sheet名称
     * @param pojoClass 集合对应的pojo类
     * @param fileName 文件名
     * @param response 响应对象
     */
    public static void exportExcel(List<?> list, String title, String sheetName,
                                   Class<?> pojoClass, String fileName, HttpServletResponse response) {
        Workbook workbook = ExcelExportUtil.exportBigExcel(new ExportParams(title,sheetName),pojoClass,list);
//        System.out.println(workbook.toString());
        if (workbook != null) {
            try {
                // 设置响应编码
                response.setCharacterEncoding("UTF-8");
                // 设置响应头 导出文件类型 导出文件名 等
                response.setHeader("content-Type", "APPLICATION/OCTET-STREAM");
                response.setHeader("Content-Disposition", "attachment;filename=" +
                        new String(fileName.getBytes("UTF-8"), "ISO-8859-1"));
                // 写入文件流
                workbook.write(response.getOutputStream());
                workbook.close();
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

4.2 Redis工具类应用

redis使用前,先编写redis配置类,再写操作工具类

pom依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
public class RedisUtils {

    /*使用自己配置的redisConfig*/
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;


    /**
     * Redis Template 操作对象 操作不同的数据类型
     * opsForValue 操作字符串 类似于String ==> redisTemplate.opsForValue();
     * opsForSet 操作Set 类似于Set
     * opsForList 操作List 类似于List
     * opsForHash 操作hash 类似于hash
     * opsForHyperLogLog 操作HyperLogLog 类似于HyperLogLog
     * opsForZSet 操作ZSet 类似于ZSet
     * opsForGeo 操作Geo 类似于Geo
     */

    /**
     * 获取redis连接对象
     * connection.flushDb(); 用于清空当前redis数据库中下所有的key
     * connection.flushAll(); 用于清空整个Redis服务器的数据(删除所有数据库的所有 key )。
     * connection.info(); 用于获取redis服务器的信息
     *
     * @return
     */
    public RedisConnection getConnection() {
        RedisConnection redisConnection = redisTemplate.getConnectionFactory().getConnection();
        return redisConnection;
    }

    /**
     * 指定缓存失效时间
     *
     * @param key
     * @param time
     * @return
     */
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据key获取过期时间
     *
     * @param key 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     *
     * @param key
     * @return true 存在 false 不存在
     */
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     *
     * @param key 可以传一个值或者多个
     */
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
            }
        }
    }

    /**
     * 普通缓存获取
     *
     * @param key 键
     * @return 值
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通缓存放入
     *
     * @param key
     * @param value
     * @return
     */
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 普通缓存放入并且设置有效时间
     *
     * @param key
     * @param value
     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return
     */
    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * HashGet
     *
     * @param key  不能为null
     * @param item 不能为null
     * @return
     */
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }

    /**
     * 获取hashKey对应的所有键值
     *
     * @param key key 键
     * @return 对应的多个键值
     */
    public Map<Object, Object> hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * HashSet
     *
     * @param key
     * @param map 对应多个键值
     * @return
     */
    public boolean hmset(String key, Map<String, Object> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * HashSet 并设置时间
     *
     * @param key
     * @param map
     * @param time 时间(秒)
     * @return
     */
    public boolean hmset(String key, Map<String, Object> map, long time) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中存入数据,如果不存在则创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @return
     */
    public boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中存入数据,如果不存在则创建 并且设置时间
     *
     * @param key
     * @param item
     * @param value
     * @param time
     * @return
     */
    public boolean hset(String key, String item, Object value, long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除hash中的值
     *
     * @param key  不能为null
     * @param item 可以使多个 不能为null
     */
    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }

    /**
     * 判断hash表中是否有该项的值
     *
     * @param key
     * @param item
     * @return
     */
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }

    /**
     * 根据key获取Set中的所有值
     *
     * @param key 键
     * @return
     */

    public Set<Object> sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据value从一个set中查询,是否存在
     *
     * @param key   键
     * @param value 值
     * @return true 存在 false不存在
     */

    public boolean sHasKey(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将数据放入set缓存
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 成功个数
     */

    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /*** 将set数据放入缓存
     * @param key 键
     * @param time 时间(秒)
     * @param values 值 可以是多个
     * @return 成功个数
     */

    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0)
                expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取set缓存的长度
     *
     * @param key 键
     * @return
     */

    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 移除值为value的
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 移除的个数
     */

    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取list缓存的内容
     *
     * @param key   键
     * @param start 开始
     * @param end   结束 0 到 -1代表所有值
     * @return
     */

    public List<Object> lGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取list缓存的长度
     *
     * @param key 键
     * @return
     */

    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 通过索引 获取list中的值
     *
     * @param key   键
     * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
     * @return
     */

    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key
     * @param value 值
     * @return
     */

    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     * @return
     */

    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     * @return
     */

    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据索引修改list中的某条数据
     *
     * @param key   键
     * @param index 索引
     * @param value 值
     * @return
     */
    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 移除N个值为value
     *
     * @param key   键
     * @param count 移除多少个
     * @param value 值
     * @return 移除的个数
     */
    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
}

4.3 单/多文件上传下载

一般项目中都会用到单、多文件的上传和下载,所以做一个统一的封装。使用示例在文章末尾的资源下载里面。

pom依赖

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.10.0</version>
</dependency>
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
@Slf4j
public class MyFileUtils {

    @Value("${filePath}")
    private String filePath; // 上传文件的地址,这里写在yml配置文件中

    /**
     * 将文件保存到指定的路径下
     * 单文件上传
     *
     * @param file
     * @param filePath
     * @return
     * @throws IOException
     */
    public static ResponseMessage uploadFile(MultipartFile file, String filePath) throws IOException {
        // 检测文件是否存在
        if (file.isEmpty()) {
            return ResponseMessage.createByErrorMessage("文件不存在或为空");
        }
        //文件名 用作文件名称字段
        String fileName;
        // 新文件名 用作实际文件名称
        String newFileName;
        //文件拓展名
        String fileHzm;

        //获取文件拓展名
        fileHzm = FilenameUtils.getExtension(file.getOriginalFilename());
        //获取文件名 file.xx
        fileName = FilenameUtils.getName(file.getOriginalFilename());
        if (fileName.lastIndexOf(".") <= 0) {
            return ResponseMessage.createByErrorMessage("不支持该文件类型");
        }
        //新文件名 以pId命名
        newFileName = UUID.randomUUID().toString().replaceAll("-", "");


        // 文件资源存放路径
        System.out.println(filePath);
        // 创建文件对象
        File fileUrl = new File(filePath);

        File uploadFile = new File(filePath + File.separator + newFileName + "." + fileHzm);
        // 检测是否存在目录
        if (!uploadFile.getParentFile().exists()) {
            //创建文件路径
            fileUrl.mkdirs();
        }
        log.info("======文件上传路径======" + fileUrl);
        //以绝对路径保存重命名后的文件
        // linux中不识别\ ,使用File.separator
        file.transferTo(uploadFile);
        //设置数据库保存路径
        String url = "/" + newFileName + "." + fileHzm;
        return ResponseMessage.createBySuccess("文件上传数据库使用路径", url);
    }

    /**
     * 多文件上传
     *
     * @param request
     * @return
     */
    public static ResponseMessage handleFileUpload(HttpServletRequest request, String filePath) {
        // 获取请求得到的多个文件
        List<MultipartFile> files = ((MultipartHttpServletRequest) request)
                .getFiles("file");
        BufferedOutputStream stream = null;
        List<String> list = new ArrayList<>();
        for (int i = 0; i < files.size(); i++) {
            try {
                // 这里上传文件
                ResponseMessage responseMessage = MyFileUtils.uploadFile(files.get(i), filePath);
                list.add(String.valueOf(responseMessage.getData()));
            } catch (Exception e) {
                stream = null;
                e.printStackTrace();
                return ResponseMessage.createByErrorMessage("上传异常,异常信息为第" + i + "个文件产生 ==>" + e.getMessage());
            }
        }
        return ResponseMessage.createBySuccess("多文件上传成功", list);
    }

    /**
     * 下载文件
     *
     * @param filePath 上传文件路径+数据库存储的路径
     * @return
     */
    public static ResponseMessage downloadFile(HttpServletResponse response, String filePath, String fileName) {
        File file = new File(filePath);
        // 判断文件父目录是否存在
        if (file.exists()) {
            byte[] buffer = new byte[1024];
            FileInputStream fis = null; //文件输入流
            BufferedInputStream bis = null;
            OutputStream os = null; //输出流
            try {
                response.setContentType(MediaType.APPLICATION_OCTET_STREAM.toString());
                response.setCharacterEncoding("UTF-8");
                response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));
                os = response.getOutputStream();
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                int i = bis.read(buffer);
                while (i != -1) {
                    os.write(buffer);
                    i = bis.read(buffer);
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error("文件下载失败,请重试====" + e.getMessage());
                return ResponseMessage.createByErrorMessage("文件下载失败,请重试");
            }
            try {
                bis.close();
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
                log.error("===文件下载-流关闭异常====");
                e.printStackTrace();
            }
            log.info("----------成功下载文件==>---" + fileName);
            return ResponseMessage.createBySuccess("文件下载成功", fileName);
        } else {
            log.info("====文件不存在====");
            return ResponseMessage.createByErrorMessage("文件不存在,无法下载");
        }
    }

    /**
     * 删除文件
     *
     * @param filePath 上传文件路径+数据库存储的路径
     * @return
     */
    public static ResponseMessage delFile(String filePath) {
        File file = new File(filePath);
        // 判断文件或者目录是否存在
        if (!file.exists()) {
            return ResponseMessage.createByErrorMessage("删除失败,文件不存在");
        }
        // 判断是否是一个文件
        if (file.isFile() || file.list() == null) {
            boolean f = file.delete();
            if (f) {
                // 删除成功
                log.info("删除了===" + file.getName());
                // 删除数据库记录 返回根据状态来删除数据库记录
                return ResponseMessage.createBySuccessMessage("删除文件" + file.getName() + "成功");
            } else {
                return ResponseMessage.createByErrorMessage("删除文件" + file.getName() + "失败");
            }
        } else {
            return ResponseMessage.createByErrorMessage("该目录下不是一个文件对象");
        }
    }
}

更多的例如,okhttp的封装与使用,JWT(Java Web Token)的封装使用都在下面的资源中,源代码链接如下:

https://download.csdn.net/download/weixin_42009068/21740613


看看什么时候再对里面的每一块的工具使用,相关知识点做一个梳理吧 ==

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Sinder_小德

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

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

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

打赏作者

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

抵扣说明:

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

余额充值