项目创建

idea点击New Project 创建一个新项目

左上角打开点击File打开设置

maven设置

这样 我们的项目就创建完毕了

点开左边的pom文档 将提供的依赖导入

我之前就存在一个冲突 是easy excel 和spring版本的冲突

经过一天的排查, 我使用的easy excel 3.0.5  和spring 2.7.1 冲突 使用spring缓存数据会报如下错误

在将spring切换到 2.6.9 后正常  再次将spring切换成 2.7.1 后又莫名正常了 完全不知道是怎么回事所以在依赖处理上请不要自己乱修改依赖 用提供给你的依赖

接下来是配置我们的项目配置 如数据库的连接 spring的配置等等

idea默认提供的是properties文档 我们将其修改成yml即可

配置文件的设置

spring:     #多环境切换profiles:default: test  #指定当前使用的是test测试环境
---
spring:config:activate:on-profile: pro  #这是pro生产环境 即将项目部署到linux服务器上所使用的环境redis:               #redis缓存的配置host: localhost     port: 6379password: 123456database: 0 #操作的是0号数据库jedis:#Redis连接池配置pool:max-active: 8 #最大连接数max-wait: 1ms #连接池最大阻塞等待时间max-idle: 4 #连接池中的最大空闲连接min-idle: 0 #连接池中的最小空闲连接mail:         #邮件系统的配置host: smtp.qq.comport: 587username: 填写你要发送邮件的邮箱password: 开启POP3/SMTP后获得的授权码default-encoding: UTF-8properties:mail:smtp:socketFactoryClass: javax.net.ssl.SSLSocketFactorydebug: trueapplication:#应用名称 , 可选name: umbrelladatasource:                 #数据库连接 使用druiddruid:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/umbrella?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: root
server:                       #服务器运行的端口号port: 80
umbrella:                       #图片资源的缓存路径path: /usr/local/app/img/
---
spring:config:activate:on-profile: testredis:host: localhostport: 6379#password: 123456database: 0 #操作的是0号数据库time-to-live: 1800000   #设置缓存过期时间,可选jedis:#Redis连接池配置pool:max-active: 8 #最大连接数max-wait: 1ms #连接池最大阻塞等待时间max-idle: 4 #连接池中的最大空闲连接min-idle: 0 #连接池中的最小空闲连接mail:host: smtp.qq.comport: 587username: password: default-encoding: UTF-8properties:mail:smtp:socketFactoryClass: javax.net.ssl.SSLSocketFactorydebug: trueapplication:#应用名称 , 可选name: umbrelladatasource:druid:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/umbrella?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: 1234
server:port: 8080
umbrella:path: C:/Users/remedios/Desktop/Test/img/
---
#底下这里是公共全局配置 所有配置共享的内容
mybatis-plus:configuration:#在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射 address_book ---> AddressBookmap-underscore-to-camel-case: true#日志输出
#   log-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:db-config:id-type: ASSIGN_ID   #设置类的id使用mybatis-plus的雪花算法生成logic-delete-field: isDeleted  #设置逻辑删除logic-not-delete-value: 0      logic-delete-value: 1

这样我们就简单配置了一个由test和pro两种环境组成的配置文件

接着将前端的资源导入到resources包底下

这样,基本的环境搭建就算是完成了  接下来就是设置各种配置类

创建一个config包 存放配置类 

创建配置类WebMvcConfig,设置静态资源映射

用于在Springboot项目中, 默认静态资源的存放目录为 : "classpath:/resources/", "classpath:/static/", "classpath:/public/" ; 而在我们的项目中静态资源存放在 backend, front 目录中, 那么这个时候要想访问到静态资源, 就需要设置静态资源映射。

package com.umbrella.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;@Slf4j
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {/*** 设置静态资源映射* @param registry*/@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {log.info("开始进行静态资源映射...");registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");}
}

设置返回给前端的json数据序列化及反序列化时, LocalDateTime、LocalDate、LocalTime的处理方式, 以及BigInteger及Long类型数据,将其直接转换为字符串  确保其精度不会损失

在config下添加JacksonObjectMapper类

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;/*** 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象* 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]* 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]*/
public class JacksonObjectMapper extends ObjectMapper {public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";public JacksonObjectMapper() {super();//收到未知属性时不报异常this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);//反序列化时,属性不存在的兼容处理this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);SimpleModule simpleModule = new SimpleModule().addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))).addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT))).addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT))).addSerializer(BigInteger.class, ToStringSerializer.instance).addSerializer(Long.class, ToStringSerializer.instance).addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))).addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT))).addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));//注册功能模块 例如,可以添加自定义序列化器和反序列化器this.registerModule(simpleModule);}
}

修改WebMvcConfig

/*** 扩展mvc框架的消息转换器* @param converters*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {log.info("扩展消息转换器...");//创建消息转换器对象MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();//设置对象转换器,底层使用Jackson将Java对象转为jsonmessageConverter.setObjectMapper(new JacksonObjectMapper());//将上面的消息转换器对象追加到mvc框架的转换器集合中converters.add(0,messageConverter);
}

这样 我们返回给前端的字段就不会出现精度损失问题了

公共字段自动填充

Mybatis Plus公共字段自动填充,也就是在插入或者更新的时候为指定字段赋予指定的值,使用它的好处就是可以统一对这些字段进行处理,避免了重复代码。在上述的问题分析中,我们提到有四个公共字段,需要在新增/更新中进行赋值操作, 具体情况如下:

字段名 赋值时机 说明
createTime 插入(INSERT) 当前时间
updateTime 插入(INSERT) , 更新(UPDATE) 当前时间
createUser 插入(INSERT) 当前登录用户ID
updateUser 插入(INSERT) , 更新(UPDATE) 当前登录用户ID

实现步骤:

1、在实体类的属性上加入@TableField注解,指定自动填充的策略。

2、按照框架要求编写元数据对象处理器,在此类中统一为公共字段赋值,此类需要实现MetaObjectHandler接口。

创建一个MyMetaObjecthandler类

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;/*** 自定义元数据对象处理器*/
@Component
@Slf4j
public class MyMetaObjecthandler implements MetaObjectHandler {/*** 插入操作,自动填充* @param metaObject*/@Overridepublic void insertFill(MetaObject metaObject) {log.info("公共字段自动填充[insert]...");log.info(metaObject.toString());metaObject.setValue("createTime", LocalDateTime.now());metaObject.setValue("updateTime",LocalDateTime.now());}/*** 更新操作,自动填充* @param metaObject*/@Overridepublic void updateFill(MetaObject metaObject) {log.info("公共字段自动填充[update]...");log.info(metaObject.toString());metaObject.setValue("updateTime",LocalDateTime.now());}
}

文件上传下载功能

创建一个CommonController

编写文件上传的方法, 通过MultipartFile类型的参数即可接收上传的文件, 方法形参的名称需要与页面的file域的name属性一致。

上传逻辑:

1). 获取文件的原始文件名, 通过原始文件名获取文件后缀

2). 通过UUID重新声明文件名, 文件名称重复造成文件覆盖

3). 创建文件存放目录

4). 将上传的临时文件转存到指定位置

import com.itheima.reggie.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.UUID;/*** 文件上传和下载*/
@RestController
@RequestMapping("/common")
@Slf4j
public class CommonController {@Value("${reggie.path}")private String basePath;/*** 文件上传* @param file* @return*/@PostMapping("/upload")public R<String> upload(MultipartFile file){//file是一个临时文件,需要转存到指定位置,否则本次请求完成后临时文件会删除log.info(file.toString());//原始文件名String originalFilename = file.getOriginalFilename();//abc.jpgString suffix = originalFilename.substring(originalFilename.lastIndexOf("."));//使用UUID重新生成文件名,防止文件名称重复造成文件覆盖String fileName = UUID.randomUUID().toString() + suffix;//dfsdfdfd.jpg//创建一个目录对象File dir = new File(basePath);//判断当前目录是否存在if(!dir.exists()){//目录不存在,需要创建dir.mkdirs();}try {//将临时文件转存到指定位置file.transferTo(new File(basePath + fileName));} catch (IOException e) {e.printStackTrace();}return R.success(fileName);}
}   

下载实现

在 CommonController 中定义方法download,并接收页面传递的参数name,然后读取图片文件的数据,然后以流的形式写回浏览器。

具体逻辑如下:

1). 定义输入流,通过输入流读取文件内容

2). 通过response对象,获取到输出流

3). 通过response对象设置响应数据格式(image/jpeg)

4). 通过输入流读取文件数据,然后通过上述的输出流写回浏览器

5). 关闭资源

/*** 文件下载* @param name* @param response*/
@GetMapping("/download")
public void download(String name, HttpServletResponse response){try {//输入流,通过输入流读取文件内容FileInputStream fileInputStream = new FileInputStream(new File(basePath + name));//输出流,通过输出流将文件写回浏览器ServletOutputStream outputStream = response.getOutputStream();response.setContentType("image/jpeg");int len = 0;byte[] bytes = new byte[1024];while ((len = fileInputStream.read(bytes)) != -1){outputStream.write(bytes,0,len);outputStream.flush();}//关闭资源outputStream.close();fileInputStream.close();} catch (Exception e) {e.printStackTrace();}
}

数据缓存 SpringCache

这里有个大坑,spring的cache在2.7.1版本似乎和easyexcel3.0.5出现了冲突 花费我整整一天都没能找到原因 只能将spring的版本降级到了2.6.9 这时候就兼容了 然后我再次将spring的版本切换到2.7.1 也兼容了 不知道什么原因

Spring Cache是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能,大大简化我们在业务中操作缓存的代码。

Spring Cache只是提供了一层抽象,底层可以切换不同的cache实现。具体就是通过CacheManager接口来统一不同的缓存技术。CacheManager是Spring提供的各种缓存技术抽象接口。

针对不同的缓存技术需要实现不同的CacheManager:

CacheManager 描述
EhCacheCacheManager 使用EhCache作为缓存技术
GuavaCacheManager 使用Google的GuavaCache作为缓存技术
RedisCacheManager 使用Redis作为缓存技术

4.2 注解

在SpringCache中提供了很多缓存操作的注解,常见的是以下的几个:

注解 说明
@EnableCaching 开启缓存注解功能
@Cacheable 在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中
@CachePut 将方法的返回值放到缓存中
@CacheEvict 将一条或多条数据从缓存中删除

在spring boot项目中,使用缓存技术只需在项目中导入相关缓存技术的依赖包,并在启动类上使用@EnableCaching开启缓存支持即可。

例如,使用Redis作为缓存技术,只需要导入Spring data Redis的maven坐标即可。

引导类上加@EnableCaching

@CachePut注解

@CachePut 说明:

作用: 将方法返回值,放入缓存

value: 缓存的名称, 每个缓存名称下面可以有很多key

key: 缓存的key ----------> 支持Spring的表达式语言SPEL语法

@CacheEvict注解

@CacheEvict 说明:

作用: 清理指定缓存

value: 缓存的名称,每个缓存名称下面可以有多个key

key: 缓存的key ----------> 支持Spring的表达式语言SPEL语法

@Cacheable注解

@Cacheable 说明:

作用: 在方法执行前,spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中

value: 缓存的名称,每个缓存名称下面可以有多个key

key: 缓存的key ----------> 支持Spring的表达式语言SPEL语法

缓存非null值

在@Cacheable注解中,提供了两个属性分别为: condition, unless 。

condition : 表示满足什么条件, 再进行缓存 ;

unless : 表示满足条件则不缓存 ; 与上述的condition是反向的

@Cacheable 会将方法的返回值缓存在Redis中,而在Redis中存储对象,该对象是需要被序列化的,而对象要想被成功的序列化,就必须得实现 Serializable 接口。

集成Redis

在使用上述默认的ConcurrentHashMap做缓存时,服务重启之后,之前缓存的数据就全部丢失了,操作起来并不友好。在项目中使用,我们会选择使用redis来做缓存,主要需要操作以下几步:

1). pom.xml

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2). application.yml

spring:redis:host: localhostport: 6379password: 123456database: 0cache:redis:time-to-live: 1800000   #设置缓存过期时间,可选

至此 我们基本的配置就整完了  接下来就是git的基本使用 和如何实现邮件发送以及数据导出excel

springboot新手项目从零开始搭建,涉及excel数据导出和邮箱发送(上)相关推荐

  1. SpringBoot后端项目框架搭建

    SpringBoot后端项目框架搭建 本节内容服务于SpringBoot + Vue 搭建 JavaWeb 增删改查项目. 工具安装 电脑已安装\配置如下工具: IDEA.jdk.MySQL及其可视化 ...

  2. 项目实战 Java读取Excel数据

    项目实战 Java读取Excel数据 前言 实现步骤 导入POI依赖 示例Excel表结构 编写读取Excel工具类 实现思路 读取Excel数据工具类实现代码 取出从excel中获取的数据,并插入到 ...

  3. SpringBoot 整合eazyPoi 4.3.0 Excel数据导入导出(持续更新功能)

    目录 依赖 注解用法说明 @ExcelTarget 绑定Id @Excel 用在字段上面 @ExcelCollection 实体代码 Excel导出 正常数量导出(1-2W条) 大数据量导出 多she ...

  4. Vue项目从零开始搭建

    一.准备环境 第一步 安装node.js根据实际操作系统选择安装包 下载地址:https://nodejs.org/en/download/ Cmd命令行输入 node –v检测安装是否成功 第二步 ...

  5. 分分钟搞定 Excel 数据导出

    1. 概览 数据导出是日常开发的常见功能,及将数据导出为Excel并提供下载.Java 生态存在大量的 Excel 操作类库,基于这些类库便可完成相关功能.这样,大量繁杂.无意义的代码耗费着宝贵的人力 ...

  6. Excel数据导出图片

    表格数据导出图片 pom.xml引入Spire配置 <!-- Excel转换工具 参考 https://www.e-iceblue.cn/licensing/install-spirepdf-f ...

  7. xlsxwriter进度条php,PHP导出Excel数据导出,前端进度条实现方式

    效果如上,结合layer组件以及ajax分页实现,具体代码如下 前端代码 用户数据导出 // 执行事件 function exportData() { var loading = layer.load ...

  8. Dcat-Admin自定义Excel数据导出

    dact-admin框架支持导出 csv. xlsx 和 ods 等格式文件,在控制器内grid−>export()−>titles(grid->export()->title ...

  9. matlab导入桌面excel数据库,matlab导入excel数据_excel怎么导入网络上的数据?_excel导入网络数据...

    网络上的数据怎么导到excel中.有方法是直接复制然后粘贴到excel中,但是网络上直接复制过来的,可能不能直接进去下一步编辑.因为复制过来的每个词后面都有空格,是不能进行直接计算,连最基本的求和都不 ...

最新文章

  1. PCL_common模块api代码解析
  2. VS遇到的各种bug
  3. python integer_【Python】string/list/integer常用函数总结
  4. OpenWrt——Could not lock /var/lock/opkg.lock: Resource temporarily unavailable.
  5. java容器类2:Map及HashMap深入解读
  6. rtp 实时传输协议
  7. SQL 2017——新功能
  8. web项目开发最佳做法
  9. python logging默认情况下打印_python logging日志打印过程解析
  10. 2019-02-25 SQL:cast(itemvalue as decimal(19,4))
  11. delete删除重复记录方法
  12. k8s mysql 查询_MySql | 为什么大家都在说 Select * 效率低
  13. stm32f072 necleo学习(一)
  14. 项目管理十大知识领域之项目相关方管理
  15. 关于单片机引脚的别名定义的正确语法
  16. MEMORY系列之“DRAM概述”
  17. rounded-{0 | top | right | bottom | left | circle } 边角半径设置 - bootStrap4常用CSS笔记(2019-05-16 09:38)...
  18. 三极管一键开关机电路详解 and二极管/MOS管防反接保护电路
  19. 如何提升企业网络曝光率?
  20. 上手Pandas,带你玩转数据(6)-- 摆脱对pandas可视化丑图的刻板印象吧

热门文章

  1. 搜索引擎优化与信息检索有什么关联
  2. HPC平台计算软件依赖, Singularity超级简单
  3. Silverlight开发历程—(绘制放射渐变图形)
  4. 信奥中的数学学习资料汇总(2022.10.31)
  5. 【Kubernetes快速实战】
  6. 逻辑学自然科学教育计算机,科学网—【逻辑学知识】自然推理系统 - 黄荣彬的博文...
  7. 计算机视觉 专业术语,计算机视觉中常用的术语.doc
  8. css两个冒号什么意思
  9. windows文本转语音调用
  10. 解析 通证经济的分类及用途