实战工具
1、Redis
- 依赖
<!--操作redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--ObjectMapper-->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
- 源码
@Configuration
public class RedisConfig {
// 企业中固定模板
// 编写我们自己的 redisTemplate
// <bean id=方法名:redisTemplate class=返回值:RedisTemplate
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> myRedisTemplate(RedisConnectionFactory factory)
throws UnknownHostException {
// 1、默认设置,为了开发方便使用String + Object
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 2、连接工厂
template.setConnectionFactory(factory);
// 3、json序列化的配置
// jackson解析任意对象
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 4、String的序列化
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;
}
}
- 调用
@Qualifier("myRedisTemplate")
@Autowired
private RedisTemplate redisTemplate;//Redis缓存
2、数据库实时更新
- pom.xml文件
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!--数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.23</version>
</dependency>
- 注入配置
//修改数据源时动态实时更新
@Configuration //用于定义配置类,等价于<Beans></Beans>
@Slf4j
public class DataSourceConfigure {
@Bean //<Bean></Bean>
@RefreshScope //配置文件自动刷新
@Primary //优先选择,自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者
@ConfigurationProperties(prefix = "spring.datasource")//获取配置在 application.properties 或 application.yml 文件中的参数值
public DataSource dataSource(DataSourceProperties properties){
log.info("执行了重新获取数据源");
return DataSourceBuilder.create(properties.getClassLoader())
//HikariDataSource默认数据源
.type(DruidDataSource.class)
.driverClassName(properties.determineDriverClassName())
.url(properties.determineUrl())
.username(properties.determineUsername())
.password(properties.determinePassword())
.build();
}
}
3、Spring Cloud Gateway网关跨域配置
//跨域问题
@Configuration
public class GatewayConfiguration {
@Bean
public CorsWebFilter corsWebFilter(){
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
//1、配置跨域
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.setAllowCredentials(true);
source.registerCorsConfiguration("/**",corsConfiguration);
return new CorsWebFilter(source);
}
}
- yaml配置
server:
port: 7000
spring:
application:
name: api-gateway #服务PID
cloud:
nacos:
discovery:
server-addr: localhost:8848 #nacos注册中心
gateway:
default-filters:
- PreserveHostHeader #重定向
discovery:
locator:
enabled: true #路由发现
routes:
- id: starter_route #router唯一标识
order: 1
uri: lb://starter-service/ #轮询微服务
predicates: #断言
- Path=/user/**
filters:
- StripPrefix=1 #去掉前缀
logging:
pattern:
console: "%d %p %msg%n"
file: "%d %p %msg%n"
path: D:\Environment\Logs
file: D:\Environment\Logs\gateway.log
4、EasyExcel导出
- pom依赖
<!--EasyExcel依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.6</version>
</dependency>
- 封装成的实体类
@Alias("excel")
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class ExcelProductInfo {
@ExcelProperty("商品编号")
private Integer id;
@ExcelProperty("商品名称")
private String name;
@ExcelProperty("商品价格")
private Double price;
@ExcelProperty("商品的销售量")
private Integer sales;
@ExcelProperty("下架:0 上架:1")
private Integer status;
@ExcelProperty("商品权限")
private String roleName;
}
- 导出业务实现
//导出Excel表格
@GetMapping("/excel")
public void OutExcel(HttpServletResponse response){
CARTER_USER_NAME = getCurrentUsername();//获取当前登录用户
if (StringUtils.isEmpty(CARTER_USER_NAME)){//空表示用户未登录
return;
}
log.info(CARTER_USER_NAME+"用户进行了Excel报表导出操作");
try {
response.setHeader("Content-Disposition","attachment;filename="+new String("商品信息.xlsx".getBytes(),"ISO-8859-1"));
//请求响应给前端
EasyExcel.write(response.getOutputStream(), ExcelProductInfo.class).sheet("商品信息表").doWrite(data());
} catch (Exception e) {
e.printStackTrace();
}
}
//得到所有商品数据
private List<ExcelProductInfo> data(){
return excelService.queryExcelData();
}
5、EasyExcel导入
- 监听器
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.ArrayList;
import java.util.List;
/**
* Excel文档导入配置类,使用泛型封装
*/
public class EasyExcelListener<T> extends AnalysisEventListener<T> {
//mapper层通用类,你也可以自己封装
private BaseMapper<T> baseMapper;
//由于存在poi冲突无法进行依赖注入,采取构造方法的方式注入其他类
public EasyExcelListener(BaseMapper<T> baseMapper){
this.baseMapper=baseMapper;
}
//设置最大读取行数
private static final int BAStudentCH_COUNStudent = 5;
//以List形式读取excel文档内容
private List<T> list=new ArrayList<>();
/**
* @param t 传入对应的实体类,就是你需要进行导入数据的类,我这里是student类
* @param analysisContext 用来解析excel文档的类,引入依赖的包已经帮我们封装了
*/
//重写导入代理类
@Override
public void invoke(T t, AnalysisContext analysisContext) {
list.add(t);
if (list.size()>=BAStudentCH_COUNStudent){
System.out.println("读取行数:"+list.size());
//执行逻辑操作,比如说插入数据到数据库 saveBath(list)
baseMapper.saveBath(list);
list.clear(); //清理list占用内存空间,重新读取下一次
}
}
/**
* @param analysisContext 用来解析excel文档的类,
*/
//必须重写这个类,否则最后一批数据不会被处理
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
//跟上面一样,比如说插入数据 saveBath(list)
System.out.println("最后读取行数:"+list.size());
baseMapper.saveBath(list);
}
}
- 接口
@PostMapping("/importExcel")
@ResponseBody
public String importExcel(MultipartFile file){//前端name必须是file
//从解析器中获取excel文件流,传入到服务层进行读取处理
try {
//DemoData分装的对象,BaseMapper数据层
EasyExcel.read(file.getInputStream(),DemoData.class,new EasyExcelListener(new BaseMapper())).sheet().doRead();
} catch (IOException e) {
e.printStackTrace();
return "导入失败";
}
return "导入成功";
}
- 前端
<form method="post" action="/importExcel" enctype="multipart/form-data">
<input type="file" name="file" value="选择文件">
<input type="submit" value="提交">
</form>
6、加载静态文件
- 依赖导入
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>static/**/*</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>static/**/*</include>
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
7、配置中心配置
public.yaml
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb?useUnicode=true&userSSL=true&characterEncoding=utf-8&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
thymeleaf:
cache: false
redis:
port: 6379
host: localhost
password:
cloud:
nacos:
discovery:
server-addr: localhost:8848
mybatis:
type-aliases-package: com.carter.pojo
mapper-locations: classpath*:mapper/**/*.xml
service.yaml
server:
port: 8074
spring:
application:
name: starter-service
cloud:
sentinel:
log:
dir: D:\Environment\logs\sentinel
switch-pid: false
logging:
pattern:
console: "%d %p %msg%n"
file: "%d %p %msg%n"
path: D:\Environment\Logs
file: D:\Environment\Logs\starter.log
feign:
client:
config:
default:
connectTimeout: 10000
readTimeout: 10000
bootstrap.yaml
spring:
application:
name: starter-service
cloud:
nacos:
config:
file-extension: yaml
server-addr: localhost:8848
shared-dataids: all-services.yaml #公共部分
refreshable-dataids: all-services.yaml #实现动态刷新
profiles:
active: dev
feign:
sentinel:
enabled: true #服务容错