? ? ? ? 很多时候我们新建好项目框架好,都是直接开发功能代码,但是在此之前我们还可以先把项目通用的工具,响应数据类给封装好。
这里不写创建框架的过程,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
看看什么时候再对里面的每一块的工具使用,相关知识点做一个梳理吧 ==
|