Commit 9cfe4c37 authored by hewenfeng's avatar hewenfeng

init

parent 4324df92
/target/
**/target/
!.mvn/wrapper/maven-wrapper.jar
*.orig
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
/logs/
**/logs/
**.log
**.class
\ No newline at end of file
img/img.png

20.3 KB

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>dmm_pll_darling</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>xxl_darling</module>
</modules>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
<id>central</id>
<url>https://maven.aliyun.com/repository/central/</url>
</repository>
<repository>
<id>public</id>
<url>https://maven.aliyun.com/repository/public</url>
</repository>
<repository>
<id>nexus</id>
<url>http://123.56.23.53:8081/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.3</version>
</parent>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>dmm_pll_darling</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>xxl_darling</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--MySQL驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<version>8.0.29</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.0.Final</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.7</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1.1-jre</version>
</dependency>
<!--jdbc连接数据库-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.32</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
<!--MyBaits-->
<!--Druid-->
<!-- Druid Spring Boot 组件-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- JasperReports 报表开发所需依赖 START -->
<!-- https://mvnrepository.com/artifact/net.sf.jasperreports/jasperreports -->
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.20.0</version>
<exclusions>
<!--
排除自带的itext依赖,因为自带的itext版本是 2.1.7.js10
这个版本在中央仓库里面没有,无法下载
-->
<exclusion>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入itext依赖,因为JasperReports中使用了itext操作PDF -->
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
<version>2.1.7</version>
</dependency>
<!-- JasperReports 报表开发所需依赖 END -->
<!--
引入 poi 依赖,因为 jasper 底层操作excel使用的是poi组件
-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.dmm.pll.Filter;
import com.dmm.pll.entity.User;
import com.dmm.pll.entity.UserLogin;
import com.dmm.pll.service.UserService;
import com.dmm.pll.service.impl.UserDetailServiceImpl;
import com.dmm.pll.util.JwtUtil;
import com.dmm.pll.util.RedisUtil;
import com.mysql.cj.util.StringUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;
public class JwtAuthenticationFilter extends BasicAuthenticationFilter {
@Autowired
UserDetailServiceImpl userDetailService;
@Autowired
UserService sysUserService;
@Autowired
RedisUtil redisUtil;
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String jwt = request.getHeader("Authorization");
// 这里如果没有jwt,继续往后走,因为后面还有鉴权管理器等去判断是否拥有身份凭证,所以是可以放行的
// 没有jwt相当于匿名访问,若有一些接口是需要权限的,则不能访问这些接口
if (StringUtils.isNullOrEmpty(jwt)) {
chain.doFilter(request, response);
return;
}
Claims claim = null;
try {
claim = JwtUtil.parseJWT(jwt);
} catch (Exception e) {
throw new RuntimeException(e);
}
if (claim == null) {
throw new JwtException("token 异常");
}
if (JwtUtil.isTokenExpired(claim)) {
throw new JwtException("token 已过期");
}
String id = claim.getSubject();
// 获取用户的权限等信息
// SysUser sysUser = sysUserService.getByUsername(username);
// User user = sysUserService.getById(Integer.valueOf(id));
UserLogin userLogin = redisUtil.getCacheObject("login" + id);
if(Objects.isNull(userLogin)){throw new JwtException("token 异常");}
// 构建UsernamePasswordAuthenticationToken,这里密码为null,是因为提供了正确的JWT,实现自动登录
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userLogin.getUsername(),null,null);
SecurityContextHolder.getContext().setAuthentication(token);
chain.doFilter(request, response);
}
}
package com.dmm.pll;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @Author:dongman
* @Date:2023/6/7 17:04
*/
@SpringBootApplication
@MapperScan("com.dmm.pll.dao")
public class XxlDarlingApplication {
public static void main(String[] args) {
SpringApplication.run(XxlDarlingApplication.class,args);
}
}
package com.dmm.pll.common;
/**
* @Author:dongman
* @Date:2023/6/12 14:38
*/
public enum ResponseCode {
SUCCESS(200, "请求成功"),
FAIL(500, "服务器内部错误");
private int code;
private String msg;
ResponseCode(int code, String message) {
this.code = code;
this.msg = message;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
package com.dmm.pll.common;
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
public class ResponseDataModel<T> {
private int code;
private String msg;
private T data;
@JsonFormat(
timezone = "GMT+8",
pattern = "yyyy-MM-dd HH:mm:ss"
)
private Date timestamp;
public static ResponseDataModel ok() {
return new ResponseDataModel(ResponseCode.SUCCESS.getCode(), ResponseCode.SUCCESS.getMsg());
}
public ResponseDataModel() {
this(ResponseCode.SUCCESS.getCode(), (String)null);
}
public static <T> ResponseDataModel<T> ok(T data) {
ResponseDataModel<T> model = new ResponseDataModel(ResponseCode.SUCCESS.getCode(), (String)null);
model.setData(data);
return model;
}
public static ResponseDataModel fail() {
return new ResponseDataModel(ResponseCode.FAIL.getCode(),ResponseCode.FAIL.getMsg());
}
public ResponseDataModel(ResponseCode responseCode, String msg) {
this.timestamp = new Date();
this.code = responseCode.getCode();
this.msg = msg;
}
public ResponseDataModel(int code, String msg) {
this.timestamp = new Date();
this.code = code;
this.msg = msg;
}
public ResponseDataModel(int code, String msg, T data) {
this.timestamp = new Date();
this.code = code;
this.msg = msg;
this.data = data;
}
public int getCode() {
return this.code;
}
public void setCode(int code) {
this.code = code;
}
public T getData() {
return this.data;
}
public void setData(T data) {
this.data = data;
}
public String getMsg() {
return this.msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Date getTimestamp() {
return this.timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
}
package com.dmm.pll.config;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import com.alibaba.fastjson.parser.ParserConfig;
import java.nio.charset.Charset;
/**
* Redis使用FastJson序列化
*
* @author sg
*/
public class FastJsonRedisSerializer<T> implements RedisSerializer<T>
{
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class<T> clazz;
static
{
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
}
public FastJsonRedisSerializer(Class<T> clazz)
{
super();
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException
{
if (t == null)
{
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException
{
if (bytes == null || bytes.length <= 0)
{
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return JSON.parseObject(str, clazz);
}
protected JavaType getJavaType(Class<?> clazz)
{
return TypeFactory.defaultInstance().constructType(clazz);
}
}
package com.dmm.pll.config;
import com.alibaba.fastjson2.JSON;
import com.dmm.pll.common.ResponseDataModel;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* @Author:dongman
* @Date:2023/6/13 13:36
*/
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws
IOException {
httpServletResponse.setContentType("application/json;charset=UTF-8");
httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
ServletOutputStream outputStream = httpServletResponse.getOutputStream();
ResponseDataModel dataModel = ResponseDataModel.fail();
outputStream.write(JSON.toJSONString(dataModel).getBytes(StandardCharsets.UTF_8));
outputStream.flush();
outputStream.close();
}
}
package com.dmm.pll.config;
import java.io.File;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.ReentrantLock;
/**
* @Author:dongman
* @Date:2023/7/12 14:09
*/
public class MyTest {
// public static void main(String[] args) {
// int n = 10;
// for (int i = 1; i <= n; i++) {
// System.out.print(fibonacci(i) + " ");
// }
// }
public static int fibonacci(int n) {
if (n <= 1) {
return n;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
public static void printNumbers(int[] numbers, int index) {
if (index != numbers.length) {
System.out.println(numbers[index]);
printNumbers(numbers, index + 1);
}
}
public static void traverseFileSystem(String path) {
File directory = new File(path);
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
System.out.println("Directory: " + file.getAbsolutePath());
traverseFileSystem(file.getAbsolutePath());
} else {
System.out.println("File: " + file.getAbsolutePath());
}
}
}
}
private static final Integer MAX = 100;
static class SubTask extends RecursiveTask<Integer> {
// 子任务开始计算的值
private Integer start;
// 子任务结束计算的值
private Integer end;
public SubTask(Integer start , Integer end) {
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
if(end - start < MAX) {
//小于边界,开始计算
System.out.println("start = " + start + ";end = " + end);
Integer totalValue = 0;
for(int index = this.start ; index <= this.end ; index++) {
totalValue += index;
}
return totalValue;
}else {
//否则,中间劈开继续拆分
SubTask subTask1 = new SubTask(start, (start + end) / 2);
subTask1.fork();
SubTask subTask2 = new SubTask((start + end) / 2 + 1 , end);
subTask2.fork();
return subTask1.join() + subTask2.join();
}
}
}
public static void main(String[] args) {
ForkJoinPool pool = new ForkJoinPool();
AtomicInteger atomicInteger = new AtomicInteger(0);
Future<Integer> taskFuture = pool.submit(new SubTask(1,1000));
try {
Integer result = taskFuture.get();
System.out.println("result = " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace(System.out);
}
}
}
package com.dmm.pll.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* @Author:dongman
* @Date:2023/6/12 14:02
*/
@Configuration
public class RedisConfig {
@Bean
@SuppressWarnings(value = {"unchecked", "rawtypes"})
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
FastJsonRedisSerializer serializer = new FastJsonRedisSerializer(Object.class);
// 使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
// Hash的key也采用StringRedisSerializer的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}
package com.dmm.pll.config;
import com.alibaba.druid.filter.logging.LogFilter;
import com.dmm.pll.Filter.JwtAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.*;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import java.util.ArrayList;
/**
* @Author:dongman
* @Date:2023/6/9 16:29
*/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager());
return jwtAuthenticationFilter;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
//关闭csrf
.csrf().disable()
//不通过Session获取SecurityContext
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.addFilter(jwtAuthenticationFilter())
.authorizeRequests()
// 对于登录接口 允许匿名访问
.antMatchers("/user/test").anonymous()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
package com.dmm.pll.controller;
import com.dmm.pll.common.ResponseCode;
import com.dmm.pll.common.ResponseDataModel;
import com.dmm.pll.entity.User;
import com.dmm.pll.refresh.boot.RefreshConfigExecutor;
import com.dmm.pll.service.UserService;
import com.dmm.pll.service.impl.JasperServiceImpl;
import com.dmm.pll.vo.GluReportHeader;
import com.dmm.pll.vo.GluReportTable;
import com.dmm.pll.vo.OutpatientPoctReportVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* @Author:dongman
* @Date:2023/6/7 18:16
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
UserService userService;
@Autowired
RefreshConfigExecutor executor;
@Autowired
JasperServiceImpl jasperService;
@RequestMapping("/test")
public void test(HttpServletRequest request, HttpServletResponse response){
OutpatientPoctReportVo vo = new OutpatientPoctReportVo();
vo.setBisPdf(true);
GluReportHeader gluReportHeader = new GluReportHeader();
gluReportHeader.setAge("18");
gluReportHeader.setSex("男");
gluReportHeader.setIdentityId("1xxxxx");
gluReportHeader.setPatientName("测试");
gluReportHeader.setIdentityId("123456789");
List<GluReportHeader> gluReportHeaders = Arrays.asList(gluReportHeader);
List<GluReportTable> gluReportTables = new ArrayList<>();
vo.setReportHeaders(gluReportHeaders);
for (int i = 1; i < 100; i++) {
GluReportTable gluReportTable = new GluReportTable();
gluReportTable.setDetectionTime("2023-12-19");
gluReportTable.setDetectionPeople("测试人员"+i);
gluReportTable.setOperatorId("5131224"+i);
gluReportTable.setSpecialRemark("注意饮食");
gluReportTable.setDetectionValue(String.valueOf(i));
gluReportTable.setInstrumentId("xhskjda1");
gluReportTable.setDetectionDoubleValue((double) i);
gluReportTables.add(gluReportTable);
}
vo.setReportTables(gluReportTables);
jasperService.getOutpatientGluRecordPdf(request,response,vo);
}
@PostMapping("/login")
public ResponseDataModel<Map<String,String>> login(@RequestBody User user){
Map<String, String> map = userService.login(user);
return new ResponseDataModel(ResponseCode.SUCCESS.getCode(),"登录成功",map);
}
}
package com.dmm.pll.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dmm.pll.entity.Role;
import org.springframework.stereotype.Repository;
/**
* @Author:dongman
* @Date:2023/6/9 15:21
*/
@Repository
public interface RoleMapper extends BaseMapper<Role> {
}
package com.dmm.pll.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dmm.pll.entity.User;
import org.springframework.stereotype.Repository;
/**
* @Author:dongman
* @Date:2023/6/9 15:20
*/
@Repository
public interface UserMapper extends BaseMapper<User> {
}
package com.dmm.pll.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dmm.pll.entity.UserRole;
import org.springframework.stereotype.Repository;
/**
* @Author:dongman
* @Date:2023/6/9 15:22
*/
@Repository
public interface UserRoleMapper extends BaseMapper<UserRole> {
}
package com.dmm.pll.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;
@Data
@Accessors(chain = true)
public class ParentReportBO {
/**
* 父报表存放路径
*/
@NotBlank(message = "父报表存放路径不能为空")
private String parentStorePath;
private List<SubReportBO> subReportBOs;
@NotNull(message = "是否打印pdf不能为空")
private boolean pdfFlag = true;
/**
* 文件下载名称
*/
@NotBlank(message = "文件下载名称不能为空")
private String downloadFileName;
private Map<String, Object> parameters;
@Data
@Accessors(chain = true)
public static class SubReportBO {
/**
*子报表在父报表(Parameters)下路径参数名
*/
private String subPathName;
/**
* 子报表存放路径
*/
private String subStorePath;
/**
* 子报表在父报表(Parameters)下数据参数名
*/
private String subDataName;
/**
* 子报表的数据
*/
private List subData;
}
}
package com.dmm.pll.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import java.util.Date;
/**
* @Author:dongman
* @Date:2023/6/9 15:10
*/
@TableName("s_role")
@Data
public class Role implements GrantedAuthority {
@TableId(type = IdType.AUTO)
private Integer id;
private String code;
private String roleName;
private Integer state;
private Integer createId;
private Integer updateId;
private Date createTime;
private Date updateTime;
@Override
public String getAuthority() {
return null;
}
}
package com.dmm.pll.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* @Author:dongman
* @Date:2023/6/9 15:10
*/
@TableName("s_user")
@Data
public class User {
@TableId(type = IdType.AUTO)
private Integer id;
private Integer createId;
private Integer updateId;
private Date createTime;
private Date updateTime;
private String userName;
private String password;
private Integer state;
}
package com.dmm.pll.entity;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
/**
* @Author:dongman
* @Date:2023/6/12 13:43
*/
@Data
public class UserLogin implements UserDetails {
private User user;
// private List<Role> roleList;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return this.user.getUserName();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
if (user.getState() == 1) {
return true;
}
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
package com.dmm.pll.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* @Author:dongman
* @Date:2023/6/9 15:10
*/
@TableName("s_user_role")
@Data
public class UserRole {
@TableId(type = IdType.AUTO)
private Integer id;
private Integer createId;
private Date createTime;
private Integer userId;
private Integer roleId;
}
package com.dmm.pll.refresh.boot;
import com.dmm.pll.refresh.factory.RemoteConfigProviderFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
@Component
public class RefreshConfigExecutor extends RemoteConfigSupport implements BeanFactoryAware, EnvironmentAware {
private ConfigurableEnvironment environment;
private ConfigurableBeanFactory beanFactory;
private SimpleTypeConverter typeConverter;
private RemoteConfigProviderFactory providerFactory;
public void execute() {
List<Properties> currentPropertiesList = providerFactory.getProperties();
if (Optional.ofNullable(currentPropertiesList).isPresent()) {
currentPropertiesList.forEach(current->{
// 更新Environment
addPropertySource(this.environment, current);
// 更新bean实例的成员变量属性值
updateField(beanFactory, environment, typeConverter, current);
});
}
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (ConfigurableBeanFactory) beanFactory;
this.typeConverter = new SimpleTypeConverter();
this.typeConverter.setConversionService(this.beanFactory.getConversionService());
}
@Override
public void setEnvironment(Environment environment) {
this.environment = (ConfigurableEnvironment) environment;
this.providerFactory = new RemoteConfigProviderFactory(this.environment);
}
}
package com.dmm.pll.refresh.boot;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RemoteConfigAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SpringValueAnnotationProcessor springValueAnnotationProcessor() {
return new SpringValueAnnotationProcessor();
}
@Bean
@ConditionalOnMissingBean
public RefreshConfigExecutor refreshConfigExecutor() {
return new RefreshConfigExecutor();
}
}
package com.dmm.pll.refresh.boot;
import com.dmm.pll.refresh.env.RemoteArgs;
import com.dmm.pll.refresh.env.RemotePropertySource;
import com.dmm.pll.refresh.property.SpringValueProperty;
import com.dmm.pll.refresh.property.SpringValuePropertyStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.Scope;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySourcesPropertyResolver;
import org.springframework.lang.NonNull;
import org.springframework.util.CollectionUtils;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
public abstract class RemoteConfigSupport {
private static final Logger log = LoggerFactory.getLogger(RemoteConfigSupport.class);
public static final String BOOTSTRAP_PROPERTY_SOURCE_NAME = "remoteConfiguration";
/**
* 向环境变量中增加PropertySource
* @param environment
* @param properties
*/
protected void addPropertySource(ConfigurableEnvironment environment, @NonNull Properties properties) {
RemoteArgs remoteArgs = new RemoteArgs(properties);
RemotePropertySource remotePropertySource = new RemotePropertySource(BOOTSTRAP_PROPERTY_SOURCE_NAME, remoteArgs);
environment.getPropertySources().addFirst(remotePropertySource);
}
/**
* 更新实例化Bean中的成员变量属性值
* @param beanFactory
* @param environment
* @param typeConverter 类型转换器,将配置值String转换为属性对应的类型值
* @param properties 配置中心读取的最新配置项
*/
protected void updateField(ConfigurableBeanFactory beanFactory, ConfigurableEnvironment environment, TypeConverter typeConverter, Properties properties) {
// 找到发生变化的配置项
Set<String> changed = findChanges(properties);
if (CollectionUtils.isEmpty(changed)) {
return ;
}
PropertySourcesPropertyResolver resolver = new PropertySourcesPropertyResolver(environment.getPropertySources());
Scope scope;
Object typeValue;
// 遍历所有发生改变的配置项
for (String key : changed) {
// 获取配置项对应的bean实例和field
for (SpringValueProperty springValueProperty : SpringValuePropertyStore.getInstance().get(key)) {
// 获取bean的scope
scope = beanFactory.getRegisteredScope(beanFactory.getMergedBeanDefinition(springValueProperty.getBeanName()).getScope());
// 解析@Value表达式,通过environment获取属性值,并根据SpEL表达式进行运算
typeValue = beanFactory.getBeanExpressionResolver().evaluate(resolver.resolvePlaceholders(springValueProperty.getExpress()), new BeanExpressionContext(beanFactory, scope));
springValueProperty.getField().setAccessible(Boolean.TRUE);
try {
// 根据Field类型进行转换
// 转换后赋值
springValueProperty.getField().set(springValueProperty.getBean(), typeConverter.convertIfNecessary(typeValue, springValueProperty.getField().getType(), new TypeDescriptor(springValueProperty.getField())));
} catch (IllegalAccessException e) {
log.error("更新变量属性值发生错误", e);
}
}
// 更新缓存
SpringValuePropertyStore.getInstance().update(key, properties.getProperty(key));
}
log.info("配置项已刷新");
}
private Set<String> findChanges(Properties properties) {
return properties.keySet().stream()
.map(String::valueOf)
.filter(key -> SpringValuePropertyStore.getInstance().isChange(key, properties.getProperty(key)))
.collect(Collectors.toSet());
}
}
package com.dmm.pll.refresh.boot;
import com.dmm.pll.refresh.factory.RemoteConfigProviderFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
public class RemoteConfigurationContextInitializer extends RemoteConfigSupport implements
ApplicationContextInitializer<ConfigurableApplicationContext>, EnvironmentPostProcessor, Ordered {
private static final Integer INIT_ORDER = 0;
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
initialize(environment);
}
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
initialize(applicationContext.getEnvironment());
}
protected void initialize(ConfigurableEnvironment environment) {
// 防止重复初始化
if (environment.getPropertySources().contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
return ;
}
List<Properties> propertiesList = new RemoteConfigProviderFactory(environment).getProperties();
if (Optional.ofNullable(propertiesList).isPresent()) {
propertiesList.forEach(properties->{
addPropertySource(environment, properties);
});
}
}
@Override
public int getOrder() {
return INIT_ORDER;
}
}
package com.dmm.pll.refresh.boot;
import com.dmm.pll.refresh.property.PlaceholderHelper;
import com.dmm.pll.refresh.property.SpringValueProperty;
import com.dmm.pll.refresh.property.SpringValuePropertyStore;
import org.springframework.beans.BeansException;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySourcesPropertyResolver;
import org.springframework.util.ReflectionUtils;
import java.util.Optional;
public class SpringValueAnnotationProcessor implements BeanPostProcessor, BeanFactoryAware, EnvironmentAware {
private ConfigurableEnvironment environment;
private ConfigurableBeanFactory beanFactory;
private PlaceholderHelper helper = new PlaceholderHelper();
private SimpleTypeConverter typeConverter;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
PropertySourcesPropertyResolver resolver = new PropertySourcesPropertyResolver(environment.getPropertySources());
ReflectionUtils.doWithFields(bean.getClass(), field -> {
Value value = field.getAnnotation(Value.class);
if (Optional.ofNullable(value).isPresent()) {
// 缓存@Value标记的Field
// 获取配置项Key
String key = helper.extractPlaceholderKeys(value.value()).stream().findFirst().get();
SpringValuePropertyStore.getInstance().add(new SpringValueProperty(
value.value(),
key,
environment.getProperty(key),
beanName,
bean,
field
));
}
});
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (ConfigurableBeanFactory) beanFactory;
this.typeConverter = new SimpleTypeConverter();
this.typeConverter.setConversionService(this.beanFactory.getConversionService());
}
@Override
public void setEnvironment(Environment environment) {
this.environment = (ConfigurableEnvironment) environment;
}
}
package com.dmm.pll.refresh.env;
import org.springframework.lang.Nullable;
import java.util.Collections;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
public class RemoteArgs {
private final Properties optionArgs;
public RemoteArgs(Properties optionArgs) {
this.optionArgs = optionArgs;
}
public Set<String> getOptionNames() {
return Collections.unmodifiableSet(
this.optionArgs.keySet().stream().map(String::valueOf).collect(Collectors.toSet())
);
}
public boolean containsOption(String optionName) {
return this.optionArgs.containsKey(optionName);
}
@Nullable
public Object getOptionValue(String optionName) {
return this.optionArgs.get(optionName);
}
}
package com.dmm.pll.refresh.env;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* @Author:dongman
* @Date:2023/8/30 15:41
*/
public class RemoteConfigTree {
private String id;
private String name;
private String type;
private String path;
private String mode;
public RemoteConfigTree() {
}
public RemoteConfigTree(@JsonProperty("id") String id,
@JsonProperty("name") String name,
@JsonProperty("type") String type,
@JsonProperty("path") String path,
@JsonProperty("mode") String mode) {
this.id = id;
this.name = name;
this.type = type;
this.path = path;
this.mode = mode;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getMode() {
return mode;
}
public void setMode(String mode) {
this.mode = mode;
}
}
package com.dmm.pll.refresh.env;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.util.StringUtils;
public class RemotePropertySource extends EnumerablePropertySource<RemoteArgs> {
public RemotePropertySource(String name, RemoteArgs source) {
super(name, source);
}
protected RemotePropertySource(String name) {
super(name);
}
@Override
public String[] getPropertyNames() {
return StringUtils.toStringArray(this.source.getOptionNames());
}
@Override
public Object getProperty(String name) {
return this.source.getOptionValue(name);
}
}
package com.dmm.pll.refresh.factory;
import com.dmm.pll.refresh.provider.FileConfigProvider;
import com.dmm.pll.refresh.provider.GiteeConfigProvider;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
public class RemoteConfigProviderFactory {
private ConfigurableEnvironment environment;
private static final String GITEE_URL = "refresh.gitUrl";
private static final String GIT_RESOURCE_DIR_PATH = "refresh.gitResourceDirPath";
private static final String GITEE_TOKEN = "refresh.access_token";
private static final String LOCAL_PATH = "refresh.localPath";
private static final String GIT_BRANCH = "refresh.gitBranch";
private static final String PROFILES = "spring.profiles.active";
public RemoteConfigProviderFactory(ConfigurableEnvironment environment) {
this.environment = environment;
}
public List<Properties> getProperties() {
String profile = environment.getProperty(PROFILES);
String localPath = environment.getProperty(LOCAL_PATH);
String giteeUrl = environment.getProperty(GITEE_URL);
String giteeToken = environment.getProperty(GITEE_TOKEN);
String gitResourceDirPath = environment.getProperty(GIT_RESOURCE_DIR_PATH);
String gitBranch = environment.getProperty(GIT_BRANCH);
if (StringUtils.hasLength(localPath)) {
return new FileConfigProvider(localPath).loadYmlAndProperties(profile);
} else if (StringUtils.hasLength(giteeUrl) && StringUtils.hasLength(giteeToken)) {
//读取git远程配置文件
OkHttpClient httpClient = new OkHttpClient.Builder()
.connectionPool(new ConnectionPool(1, 5L, TimeUnit.MINUTES)).build();
GiteeConfigProvider giteeConfigProvider = new GiteeConfigProvider(giteeUrl, giteeToken, gitResourceDirPath, httpClient, gitBranch);
return giteeConfigProvider.loadYmlAndProperties(profile);
}
return null;
}
}
/*
* Copyright 2022 Apollo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.dmm.pll.refresh.property;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.Scope;
import org.springframework.util.StringUtils;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;
/**
* Placeholder helper functions.
*/
public class PlaceholderHelper {
private static final String PLACEHOLDER_PREFIX = "${";
private static final String PLACEHOLDER_SUFFIX = "}";
private static final String VALUE_SEPARATOR = ":";
private static final String SIMPLE_PLACEHOLDER_PREFIX = "{";
private static final String EXPRESSION_PREFIX = "#{";
private static final String EXPRESSION_SUFFIX = "}";
/**
* Resolve placeholder property values, e.g.
* <br />
* <br />
* "${somePropertyValue}" -> "the actual property value"
*/
public Object resolvePropertyValue(ConfigurableBeanFactory beanFactory, String beanName, String placeholder) {
// resolve string value
String strVal = beanFactory.resolveEmbeddedValue(placeholder);
BeanDefinition bd = (beanFactory.containsBean(beanName) ? beanFactory
.getMergedBeanDefinition(beanName) : null);
// resolve expressions like "#{systemProperties.myProp}"
return evaluateBeanDefinitionString(beanFactory, strVal, bd);
}
private Object evaluateBeanDefinitionString(ConfigurableBeanFactory beanFactory, String value,
BeanDefinition beanDefinition) {
if (beanFactory.getBeanExpressionResolver() == null) {
return value;
}
Scope scope = (beanDefinition != null ? beanFactory
.getRegisteredScope(beanDefinition.getScope()) : null);
return beanFactory.getBeanExpressionResolver()
.evaluate(value, new BeanExpressionContext(beanFactory, scope));
}
/**
* Extract keys from placeholder, e.g.
* <ul>
* <li>${some.key} => "some.key"</li>
* <li>${some.key:${some.other.key:100}} => "some.key", "some.other.key"</li>
* <li>${${some.key}} => "some.key"</li>
* <li>${${some.key:other.key}} => "some.key"</li>
* <li>${${some.key}:${another.key}} => "some.key", "another.key"</li>
* <li>#{new java.text.SimpleDateFormat('${some.key}').parse('${another.key}')} => "some.key", "another.key"</li>
* </ul>
*/
public Set<String> extractPlaceholderKeys(String propertyString) {
Set<String> placeholderKeys = new HashSet<>();
if (!StringUtils.hasLength(propertyString) || (!isNormalizedPlaceholder(propertyString) && !isExpressionWithPlaceholder(propertyString))) {
return placeholderKeys;
}
Stack<String> stack = new Stack<>();
stack.push(propertyString);
while (!stack.isEmpty()) {
String strVal = stack.pop();
int startIndex = strVal.indexOf(PLACEHOLDER_PREFIX);
if (startIndex == -1) {
placeholderKeys.add(strVal);
continue;
}
int endIndex = findPlaceholderEndIndex(strVal, startIndex);
if (endIndex == -1) {
// invalid placeholder?
continue;
}
String placeholderCandidate = strVal.substring(startIndex + PLACEHOLDER_PREFIX.length(), endIndex);
// ${some.key:other.key}
if (placeholderCandidate.startsWith(PLACEHOLDER_PREFIX)) {
stack.push(placeholderCandidate);
} else {
// some.key:${some.other.key:100}
int separatorIndex = placeholderCandidate.indexOf(VALUE_SEPARATOR);
if (separatorIndex == -1) {
stack.push(placeholderCandidate);
} else {
stack.push(placeholderCandidate.substring(0, separatorIndex));
String defaultValuePart =
normalizeToPlaceholder(placeholderCandidate.substring(separatorIndex + VALUE_SEPARATOR.length()));
if (StringUtils.hasLength(defaultValuePart)) {
stack.push(defaultValuePart);
}
}
}
// has remaining part, e.g. ${a}.${b}
if (endIndex + PLACEHOLDER_SUFFIX.length() < strVal.length() - 1) {
String remainingPart = normalizeToPlaceholder(strVal.substring(endIndex + PLACEHOLDER_SUFFIX.length()));
if (StringUtils.hasLength(remainingPart)) {
stack.push(remainingPart);
}
}
}
return placeholderKeys;
}
private boolean isNormalizedPlaceholder(String propertyString) {
return propertyString.startsWith(PLACEHOLDER_PREFIX) && propertyString.contains(PLACEHOLDER_SUFFIX);
}
private boolean isExpressionWithPlaceholder(String propertyString) {
return propertyString.startsWith(EXPRESSION_PREFIX) && propertyString.contains(EXPRESSION_SUFFIX)
&& propertyString.contains(PLACEHOLDER_PREFIX) && propertyString.contains(PLACEHOLDER_SUFFIX);
}
private String normalizeToPlaceholder(String strVal) {
int startIndex = strVal.indexOf(PLACEHOLDER_PREFIX);
if (startIndex == -1) {
return null;
}
int endIndex = strVal.lastIndexOf(PLACEHOLDER_SUFFIX);
if (endIndex == -1) {
return null;
}
return strVal.substring(startIndex, endIndex + PLACEHOLDER_SUFFIX.length());
}
private int findPlaceholderEndIndex(CharSequence buf, int startIndex) {
int index = startIndex + PLACEHOLDER_PREFIX.length();
int withinNestedPlaceholder = 0;
while (index < buf.length()) {
if (StringUtils.substringMatch(buf, index, PLACEHOLDER_SUFFIX)) {
if (withinNestedPlaceholder > 0) {
withinNestedPlaceholder--;
index = index + PLACEHOLDER_SUFFIX.length();
} else {
return index;
}
} else if (StringUtils.substringMatch(buf, index, SIMPLE_PLACEHOLDER_PREFIX)) {
withinNestedPlaceholder++;
index = index + SIMPLE_PLACEHOLDER_PREFIX.length();
} else {
index++;
}
}
return -1;
}
}
package com.dmm.pll.refresh.property;
import java.io.Serializable;
import java.lang.reflect.Field;
public class SpringValueProperty implements Serializable {
private static final long serialVersionUID = -8956519848116609175L;
/**
* @Value注解中的表达式
*/
private String express;
private String key;
private String value;
private String beanName;
private Object bean;
private Field field;
public SpringValueProperty(String express, String key, String value, String beanName, Object bean, Field field) {
this.express = express;
this.key = key;
this.value = value;
this.beanName = beanName;
this.bean = bean;
this.field = field;
}
public String getExpress() {
return express;
}
public void setExpress(String express) {
this.express = express;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getBeanName() {
return beanName;
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
public Object getBean() {
return bean;
}
public void setBean(Object bean) {
this.bean = bean;
}
public Field getField() {
return field;
}
public void setField(Field field) {
this.field = field;
}
}
package com.dmm.pll.refresh.property;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class SpringValuePropertyStore {
private static SpringValuePropertyStore instance = null;
private static MultiValueMap<String, SpringValueProperty> store = null;
private final ReentrantReadWriteLock LOCK = new ReentrantReadWriteLock();
private final Lock READ_LOCK = LOCK.readLock();
private final Lock WRITE_LOCK = LOCK.writeLock();
public static synchronized SpringValuePropertyStore getInstance() {
if (null == instance) {
instance = new SpringValuePropertyStore();
store = new LinkedMultiValueMap<>();
}
return instance;
}
/**
* 缓存@Value注解的元素
* @param property
*/
public void add(SpringValueProperty property) {
WRITE_LOCK.lock();
try {
store.add(property.getKey(), property);
} finally {
WRITE_LOCK.unlock();
}
}
/**
* 判断配置是否发生变化
* @param key 配置项key
* @param currentValue 配置项当前value
* @return
*/
public Boolean isChange(String key, String currentValue) {
boolean b = StringUtils.hasLength(key)
&& StringUtils.hasLength(currentValue)
&& store.containsKey(key)
&& !Objects.equals(store.getFirst(key).getValue(), currentValue);
return b;
}
/**
* 更新所有Field当前属性值
* @param key 配置项key
* @param currentValue 配置项当前value
*/
public void update(String key, String currentValue) {
WRITE_LOCK.lock();
try {
store.get(key).stream().forEach(springValueProperty -> springValueProperty.setValue(currentValue));
} finally {
WRITE_LOCK.unlock();
}
}
/**
* 根据配置项读取所有元素
* @param key
* @return
*/
public List<SpringValueProperty> get(String key) {
READ_LOCK.lock();
try {
return store.get(key);
} finally {
READ_LOCK.unlock();
}
}
}
package com.dmm.pll.refresh.provider;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;
/**
* @Author:dongman
* @Date:2023/8/28 15:53
*/
public class FileConfigProvider implements RemoteConfigProvider{
private final String localPath;
public FileConfigProvider(String localPath) {
this.localPath = localPath;
}
@Override
public List<Properties> loadYmlAndProperties(String profile) {
ArrayList<Properties> propertiesList = new ArrayList<>();
List<File> fileList = this.collectFiles(localPath);
List<String> pathList = fileList.stream()
.filter(file -> file.getName().endsWith(".properties") || file.getName().endsWith(profile + ".yml"))
.map(File::getAbsolutePath).collect(Collectors.toList());
pathList.forEach(path -> {
Properties properties = this.load(path);
propertiesList.add(properties);
});
return propertiesList;
}
public Properties load(String absolutePath) {
Properties properties =null;
try {
Path path = Paths.get(absolutePath);
byte[] configBytes = Files.readAllBytes(path);
Resource resource = new ByteArrayResource(configBytes);
YamlPropertiesFactoryBean yamlBeanFactory = new YamlPropertiesFactoryBean();
yamlBeanFactory.setResources(resource);
properties = yamlBeanFactory.getObject();
} catch (IOException e) {
e.printStackTrace();
}
return properties;
}
public List<File> collectFiles(String directoryPath) {
List<File> fileList = new ArrayList<>();
File directory = new File(directoryPath);
if (directory.exists() && directory.isDirectory()) {
collectFilesRecursively(directory, fileList);
}
return fileList;
}
private void collectFilesRecursively(File directory, List<File> fileList) {
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
if (file.isFile()) {
fileList.add(file);
} else if (file.isDirectory()) {
collectFilesRecursively(file, fileList);
}
}
}
}
}
package com.dmm.pll.refresh.provider;
import com.dmm.pll.refresh.boot.RemoteConfigSupport;
import com.dmm.pll.refresh.env.RemoteConfigTree;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
public class GiteeConfigProvider implements RemoteConfigProvider {
private static final Logger log = LoggerFactory.getLogger(GiteeConfigProvider.class);
/**
* Gitee config repository remote URL
*
* @example https://gitee.com/api/v5/repos/codest-c/config-folder/contents/disk.properties
*/
private final String url;
/**
* Gitee Access Token
*/
private final String token;
private final String gitResourceDirPath;
private OkHttpClient httpClient;
private final String branch;
private static final String PROPERTIES_KEY = "content";
private static final String FILE_NAME_KEY = "file_name";
public GiteeConfigProvider(String url, String token, String gitResourceDirPath, OkHttpClient httpClient,String branch) {
this.url = url;
this.token = token;
this.gitResourceDirPath = gitResourceDirPath;
this.httpClient = httpClient;
this.branch = branch;
}
/**
* load all config(yml/properties)
*
* @return
*/
@Override
public List<Properties> loadYmlAndProperties(String profile) {
String configTreeUrl = this.url + "/tree?ref=" + branch + "&path=" + gitResourceDirPath;
Request request = this.buildRequest(configTreeUrl);
ArrayList<Properties> propertiesList = new ArrayList<>();
try (Response response = this.httpClient.newCall(request).execute()) {
//获取目录结构
if (response.isSuccessful() && response.body() != null) {
List<RemoteConfigTree> remoteConfigTrees = new ObjectMapper().readValue(response.body().string(), new TypeReference<List<RemoteConfigTree>>() {
});
List<String> configPathList = remoteConfigTrees.stream().filter(s ->
"blob".equals(s.getType())
&& (s.getPath().endsWith(".properties") || s.getPath().endsWith(profile + ".yml")))
.map(RemoteConfigTree::getPath).collect(Collectors.toList());
//拉取远程对应yml和properties文件具体内容
configPathList.forEach(path -> {
try {
path = URLEncoder.encode(path, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException("URL编码失败",e);
}
String configFileUrl = this.url + "/files/" + path + "?ref=" + branch;
Properties properties = this.load(configFileUrl);
propertiesList.add(properties);
});
}
} catch (IOException e) {
log.error("读取Gitee仓库配置发生错误");
e.printStackTrace();
}
return propertiesList;
}
public Properties load(String url) {
Request request = this.buildRequest(url);
try (Response response = this.httpClient.newCall(request).execute()) {
if (response.isSuccessful()) {
Map<String, Object> data = new ObjectMapper().readValue(response.body().string(), Map.class);
String config = data.get(PROPERTIES_KEY).toString();
config = new String(Base64.getDecoder().decode(config), StandardCharsets.UTF_8.name());
String fileName = data.get(FILE_NAME_KEY).toString();
Properties properties = new Properties();
if (fileName.endsWith(".yml")) {
//yml
byte[] configBytes = config.getBytes(StandardCharsets.UTF_8);
Resource resource = new ByteArrayResource(configBytes);
YamlPropertiesFactoryBean yamlBeanFactory = new YamlPropertiesFactoryBean();
yamlBeanFactory.setResources(resource);
properties = yamlBeanFactory.getObject();
} else if (fileName.endsWith(".properties")) {
//properties
properties.load(new StringReader(config));
}
return properties;
} else {
log.error(String.format("读取Gitee配置文件发生错误[%s]", response.body().string()));
}
} catch (IOException e) {
log.error("读取Gitee配置文件发生错误");
e.printStackTrace();
}
return null;
}
private Request buildRequest(String url) {
return new Request.Builder()
.url(url)
.addHeader("PRIVATE-TOKEN", this.token)
.get()
.build();
}
}
package com.dmm.pll.refresh.provider;
import java.util.List;
import java.util.Properties;
public interface RemoteConfigProvider {
List<Properties> loadYmlAndProperties(String profile);
}
package com.dmm.pll.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dmm.pll.entity.User;
import java.util.Map;
/**
* @Author:dongman
* @Date:2023/6/7 16:59
*/
public interface UserService extends IService<User>{
Map<String,String> login(User user);
}
package com.dmm.pll.service.impl;
import com.dmm.pll.dto.ParentReportBO;
import com.dmm.pll.util.JasperReportUtil;
import com.dmm.pll.vo.OutpatientPoctReportVo;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
/**
* @Author:dongman
* @Date:2023/12/19 13:43
*/
@Service
public class JasperServiceImpl {
public void getOutpatientGluRecordPdf(HttpServletRequest request, HttpServletResponse response, OutpatientPoctReportVo vo){
String outpatientGluRecordReport = "D:\\project\\dmm_pll_darling\\xxl_darling\\src\\main\\resources/jasper/outpatient_glu_record_report.jrxml";
String outpatientGluRecordSubHeader = "D:\\project\\dmm_pll_darling\\xxl_darling\\src\\main\\resources/jasper/outpatient_glu_record_sub_header.jrxml";
String outpatientGluRecordSubTable = "D:\\project\\dmm_pll_darling\\xxl_darling\\src\\main\\resources/jasper/outpatient_glu_record_sub_table.jrxml";
String outpatientPoctSubHeaderPath = "outpatientPoctSubHeaderPath";
String outpatientPoctSubTablePath = "outpatientPoctSubTablePath";
String outpatientPoctSubHeaderList = "outpatientPoctSubHeaderList";
String outpatientPoctSubTableList = "outpatientPoctSubTableList";
ParentReportBO.SubReportBO sub1 = new ParentReportBO.SubReportBO()
.setSubStorePath(outpatientGluRecordSubHeader).setSubPathName(outpatientPoctSubHeaderPath).setSubDataName(outpatientPoctSubHeaderList).setSubData( vo.getReportHeaders());
ParentReportBO.SubReportBO sub2 = new ParentReportBO.SubReportBO()
.setSubStorePath(outpatientGluRecordSubTable).setSubPathName(outpatientPoctSubTablePath).setSubDataName(outpatientPoctSubTableList).setSubData(vo.getReportTables());
List<ParentReportBO.SubReportBO> subReportBOs = Arrays.asList(sub1, sub2);
ParentReportBO parent = new ParentReportBO()
.setDownloadFileName("门诊血糖记录单")
.setParentStorePath(outpatientGluRecordReport).setSubReportBOs(subReportBOs).setPdfFlag(vo.getBisPdf());
JasperReportUtil.loadAndRespond(parent,response);
}
}
package com.dmm.pll.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dmm.pll.dao.RoleMapper;
import com.dmm.pll.dao.UserMapper;
import com.dmm.pll.dao.UserRoleMapper;
import com.dmm.pll.entity.Role;
import com.dmm.pll.entity.User;
import com.dmm.pll.entity.UserLogin;
import com.dmm.pll.entity.UserRole;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* @Author:dongman
* @Date:2023/6/12 13:50
*/
@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
private UserMapper userMapper;
@Autowired
private UserRoleMapper userRoleMapper;
@Autowired
private RoleMapper roleMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if(Strings.isBlank(username)) throw new UsernameNotFoundException("用户名为空");
User user = userMapper.selectOne(
new QueryWrapper<User>().lambda().eq(User::getUserName, username));
if(Objects.isNull(user)) throw new UsernameNotFoundException("用户不存在");
UserLogin userLogin = new UserLogin();
List<UserRole> userRoles = userRoleMapper.selectList(
new QueryWrapper<UserRole>().lambda().eq(UserRole::getUserId, user.getId()));
if(!CollectionUtils.isEmpty(userRoles)){
List<Integer> roleIds = userRoles.stream().map(UserRole::getRoleId).collect(Collectors.toList());
List<Role> roles = roleMapper.selectList(
new QueryWrapper<Role>().lambda().in(Role::getId, roleIds)
);
// userLogin.setRoleList(roles);
}
userLogin.setUser(user);
return userLogin;
}
}
package com.dmm.pll.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dmm.pll.dao.UserMapper;
import com.dmm.pll.entity.User;
import com.dmm.pll.entity.UserLogin;
import com.dmm.pll.service.UserService;
import com.dmm.pll.util.JwtUtil;
import com.dmm.pll.util.RedisUtil;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* @Author:dongman
* @Date:2023/6/7 18:35
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{
@Resource
private AuthenticationManager authenticationManager;
@Resource
private RedisUtil redisUtil;
@Override
public Map<String,String> login(User user) {
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword());
Authentication authenticate = authenticationManager.authenticate(authenticationToken);
//认证未通过,给出提示
if(Objects.isNull(authenticate)){
throw new RuntimeException("登陆失败!");
}
//通过了,生成jwt
UserLogin loginUser = (UserLogin) authenticate.getPrincipal();
String id = loginUser.getUser().getId().toString();
String jwt = JwtUtil.createJWT(id);
Map<String,String> map = new HashMap<>();
map.put("token",jwt);
//将用户信息存入redis
redisUtil.setCacheObject("login"+id,loginUser);
return map;
}
}
package com.dmm.pll.util;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.RandomUtil;
import com.dmm.pll.dto.ParentReportBO;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter;
import net.sf.jasperreports.export.SimpleExporterInput;
import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput;
import net.sf.jasperreports.export.SimpleXlsxReportConfiguration;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.File;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
@Slf4j
@Validated
public class JasperReportUtil {
private JasperReportUtil() {
}
public static void loadAndRespond(@Valid ParentReportBO reportBO, HttpServletResponse response){
InputStream fis = null;
try{
if (StringUtils.hasText(reportBO.getParentStorePath())) {
//读取父报表
String parentStorePath = compileJRXmlReportToJasperFile(reportBO.getParentStorePath());
fis = Files.newInputStream(Paths.get(parentStorePath));
List<ParentReportBO.SubReportBO> subReportBOs =
Optional.ofNullable(reportBO)
.map(ParentReportBO ::getSubReportBOs)
.orElseGet(ArrayList::new);
//告知父报表子表的路径与数据
Map<String, Object> parameters = Objects.isNull(reportBO.getParameters())? Maps.newHashMapWithExpectedSize(16) :reportBO.getParameters();
// parameters.put("reportImageUrl","/cloudjar/img/logo1.png");
for (ParentReportBO.SubReportBO subReport : subReportBOs) {
String subStorePath = compileJRXmlReportToJasperFile(subReport.getSubStorePath());
File subFile = new File(subStorePath);
parameters.put(subReport.getSubPathName(), subFile.getPath()); //设置子表表路径
parameters.put(subReport.getSubDataName(), subReport.getSubData()); //设置子报表的数据
}
//装载数据
JasperPrint print = JasperFillManager.fillReport(fis, parameters, new JREmptyDataSource());
ServletOutputStream outputStream = response.getOutputStream();
//是pdf就打印
if (reportBO.isPdfFlag()) {
JasperExportManager.exportReportToPdfStream(print, outputStream);
} else {
String filename = StringUtils.hasText(reportBO.getDownloadFileName()) ? reportBO.getDownloadFileName() : RandomUtil.randomString(12);
//设置响应头的编码格式为UTF-8
response.setContentType("application/vnd.ms-excel;charset=utf-8");
//设置响应头中文件的下载方式为附件方式,以及设置文件名称
response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(filename + DateUtil.today() + ".xls", StandardCharsets.UTF_8.name()));
createExcel(print,outputStream,reportBO.getDownloadFileName());
}
}
}catch (Exception e){
log.info("JasperReportUtil.loadAndRespond方法发生错误,信息如下:{}",e.getMessage());
e.printStackTrace();
}finally {
IoUtil.close(fis);
}
}
private static void createExcel(JasperPrint print, ServletOutputStream outputStream,String sheetName) throws JRException {
//创建Jasper Excel导出类
JRXlsxExporter exporter = new JRXlsxExporter();
exporter.setExporterInput(new SimpleExporterInput(print));
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(outputStream));
//设置导出配置
SimpleXlsxReportConfiguration conf = new SimpleXlsxReportConfiguration();
//去除两行之前的空白
conf.setRemoveEmptySpaceBetweenRows(Boolean.FALSE);
//设置excel的sheet名称
String[] sheetNames = new String[1];
sheetNames[0] = sheetName;
conf.setSheetNames(sheetNames);
//设置Excel表格的背景颜色为默认的白色
conf.setWhitePageBackground(Boolean.FALSE);
//设置所有页只打印到一个Sheet中,true则可设置多个sheet
conf.setOnePagePerSheet(Boolean.FALSE);
conf.setDetectCellType(Boolean.TRUE);
exporter.setConfiguration(conf);
//导出报表
exporter.exportReport();
}
private static String compileJRXmlReportToJasperFile(String storePath) throws JRException {
if (!StringUtils.hasText(storePath)){
// throw new BusinessException("报表路径为空");
log.error("报表路径为空");
}
if (storePath.endsWith(".jrxml")) {
String jasperPath = "";
File file = new File(storePath);
File parentFile = file.getParentFile();
File tempJasper = new File(parentFile,"tempFile");
if (!tempJasper.exists()){
tempJasper.mkdirs();
}
jasperPath = tempJasper.getPath() + File.separator + file.getName().replace("jrxml","jasper");
JasperCompileManager.compileReportToFile(storePath,jasperPath);
return jasperPath;
}
return storePath;
}
}
package com.dmm.pll.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;
/**
* JWT工具类
*/
public class JwtUtil {
//有效期为
public static final Long JWT_TTL = 60 * 60 *1000L;// 60 * 60 *1000 一个小时
//设置秘钥明文
public static final String JWT_KEY = "sangeng";
public static String getUUID(){
String token = UUID.randomUUID().toString().replaceAll("-", "");
return token;
}
/**
* 生成jtw
* @param subject token中要存放的数据(json格式)
* @return
*/
public static String createJWT(String subject) {
JwtBuilder builder = getJwtBuilder(subject, null, getUUID());// 设置过期时间
return builder.compact();
}
/**
* 生成jtw
* @param subject token中要存放的数据(json格式)
* @param ttlMillis token超时时间
* @return
*/
public static String createJWT(String subject, Long ttlMillis) {
JwtBuilder builder = getJwtBuilder(subject, ttlMillis, getUUID());// 设置过期时间
return builder.compact();
}
private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
SecretKey secretKey = generalKey();
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
if(ttlMillis==null){
ttlMillis=JwtUtil.JWT_TTL;
}
long expMillis = nowMillis + ttlMillis;
Date expDate = new Date(expMillis);
return Jwts.builder()
.setId(uuid) //唯一的ID
.setSubject(subject) // 主题 可以是JSON数据
.setIssuer("sg") // 签发者
.setIssuedAt(now) // 签发时间
.signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥
.setExpiration(expDate);
}
/**
* 创建token
* @param id
* @param subject
* @param ttlMillis
* @return
*/
public static String createJWT(String id, String subject, Long ttlMillis) {
JwtBuilder builder = getJwtBuilder(subject, ttlMillis, id);// 设置过期时间
return builder.compact();
}
public static void main(String[] args) throws Exception {
String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMDZkZDc4MDQyNWU0ZDAxOTkwNzYyOGVmMmNiZDFlYSIsInN1YiI6IjEiLCJpc3MiOiJzZyIsImlhdCI6MTY4NjYyMTU2MywiZXhwIjoxNjg2NjI1MTYzfQ.UUCucldp_eCmRlX7Ti_uMboXC3LU7c002pCuv8nuJdE";
Claims claims = parseJWT(token);
System.out.println(claims);
}
/**
* 生成加密后的秘钥 secretKey
* @return
*/
public static SecretKey generalKey() {
byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
}
/**
* 解析
*
* @param jwt
* @return
* @throws Exception
*/
public static Claims parseJWT(String jwt) throws Exception {
SecretKey secretKey = generalKey();
Claims body = Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(jwt)
.getBody();
return body;
}
// 判断JWT是否过期
public static boolean isTokenExpired(Claims claims) {
return claims.getExpiration().before(new Date());
}
}
package com.dmm.pll.util;
/**
* @Author:dongman
* @Date:2023/6/12 14:06
*/
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
@SuppressWarnings(value = {"unchecked", "rawtypes"})
@Component
public class RedisUtil {
@Autowired
public RedisTemplate redisTemplate;
/**
* 缓存基本的对象,Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
*/
public <T> void setCacheObject(final String key, final T value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* 缓存基本的对象,Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
* @param timeout 时间
* @param timeUnit 时间颗粒度
*/
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @return true=设置成功;false=设置失败
*/
public boolean expire(final String key, final long timeout) {
return expire(key, timeout, TimeUnit.SECONDS);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @param unit 时间单位
* @return true=设置成功;false=设置失败
*/
public boolean expire(final String key, final long timeout, final TimeUnit unit) {
return redisTemplate.expire(key, timeout, unit);
}
/**
* 获得缓存的基本对象。
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public <T> T getCacheObject(final String key) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
/**
* 删除单个对象
*
* @param key
*/
public boolean deleteObject(final String key) {
return redisTemplate.delete(key);
}
/**
* 删除集合对象
*
* @param collection 多个对象
* @return
*/
public long deleteObject(final Collection collection) {
return redisTemplate.delete(collection);
}
/**
* 缓存List数据
*
* @param key 缓存的键值
* @param dataList 待缓存的List数据
* @return 缓存的对象
*/
public <T> long setCacheList(final String key, final List<T> dataList) {
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
return count == null ? 0 : count;
}
/**
* 获得缓存的list对象
*
* @param key 缓存的键值
* @return 缓存键值对应的数据
*/
public <T> List<T> getCacheList(final String key) {
return redisTemplate.opsForList().range(key, 0, -1);
}
/**
* 缓存Set
*
* @param key 缓存键值
* @param dataSet 缓存的数据
* @return 缓存数据的对象
*/
public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet) {
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
Iterator<T> it = dataSet.iterator();
while (it.hasNext()) {
setOperation.add(it.next());
}
return setOperation;
}
/**
* 获得缓存的set
*
* @param key
* @return
*/
public <T> Set<T> getCacheSet(final String key) {
return redisTemplate.opsForSet().members(key);
}
/**
* 缓存Map
*
* @param key
* @param dataMap
*/
public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
if (dataMap != null) {
redisTemplate.opsForHash().putAll(key, dataMap);
}
}
/**
* 获得缓存的Map
*
* @param key
* @return
*/
public <T> Map<String, T> getCacheMap(final String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* 往Hash中存入数据
*
* @param key Redis键
* @param hKey Hash键
* @param value 值
*/
public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
redisTemplate.opsForHash().put(key, hKey, value);
}
/**
* 获取Hash中的数据
*
* @param key Redis键
* @param hKey Hash键
* @return Hash中的对象
*/
public <T> T getCacheMapValue(final String key, final String hKey) {
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
return opsForHash.get(key, hKey);
}
/**
* 删除Hash中的数据
*
* @param key
* @param hkey
*/
public void delCacheMapValue(final String key, final String hkey) {
HashOperations hashOperations = redisTemplate.opsForHash();
hashOperations.delete(key, hkey);
}
/**
* 获取多个Hash中的数据
*
* @param key Redis键
* @param hKeys Hash键集合
* @return Hash对象集合
*/
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) {
return redisTemplate.opsForHash().multiGet(key, hKeys);
}
/**
* 获得缓存的基本对象列表
*
* @param pattern 字符串前缀
* @return 对象列表
*/
public Collection<String> keys(final String pattern) {
return redisTemplate.keys(pattern);
}
}
package com.dmm.pll.vo;
import lombok.Data;
/**
* @Author:dongman
* @Date:2023/12/19 13:53
*/
@Data
public class GluReportHeader {
private String patientName;
private String sex;
private String age;
private String medicareCardNo;
private String identityId;
}
package com.dmm.pll.vo;
import lombok.Data;
/**
* @Author:dongman
* @Date:2023/12/19 13:53
*/
@Data
public class GluReportTable {
private String detectionTime;
private String detectionValue;
private String detectionPeople;
private String operatorId;
private String instrumentId;
private String specialRemark;
private Double detectionDoubleValue;
}
package com.dmm.pll.vo;
import lombok.Data;
import java.util.List;
/**
* @Author:dongman
* @Date:2023/12/19 13:48
*/
@Data
public class OutpatientPoctReportVo {
private Boolean bisPdf;
private List<GluReportHeader> reportHeaders;
private List<GluReportTable> reportTables;
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.dmm.pll.refresh.boot.RemoteConfigAutoConfiguration
org.springframework.boot.env.EnvironmentPostProcessor=\
com.dmm.pll.refresh.boot.RemoteConfigurationContextInitializer
\ No newline at end of file
spring:
profiles:
active: dev
application:
name: dmmXxl-api-web
servlet:
multipart:
max-file-size: 20MB
max-request-size: 64MB
#tmp目录
location: ${server.tomcat.basedir}
jackson:
dateFormat: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/sshr_test?autoReconnect=true&failOverReadOnly=false&useUnicode=true&useSSL=false&allowMultiQueries=true&rewriteBatchedStatements=true
username: root
password: 123456
hikari:
pool-name: sshr-hikaricp
max-lifetime: 120000
minimum-idle: 8
maximum-pool-size: 16
connection-test-query: SELECT 1
refresh:
localPath: ../ahm/ahm-web/src/main/resources
server:
port: 8282
tomcat:
basedir: c:/home/data/deploy/tomcat/temp/
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.20.6.final using JasperReports Library version 6.20.6-5c96b6aa8a39ac1dc6b6bea4b81168e16dd39231 -->
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="outpatient_poct_report" pageWidth="524" pageHeight="842" columnWidth="504" leftMargin="10" rightMargin="10" topMargin="10" bottomMargin="0" uuid="041ab73a-2918-407b-a2a7-4111728da3a3">
<parameter name="outpatientPoctSubHeaderPath" class="java.lang.String"/>
<parameter name="outpatientPoctSubHeaderList" class="java.util.List"/>
<parameter name="outpatientPoctSubTablePath" class="java.lang.String"/>
<parameter name="outpatientPoctSubTableList" class="java.util.List"/>
<queryString>
<![CDATA[]]>
</queryString>
<background>
<band splitType="Stretch"/>
</background>
<title>
<band height="70" splitType="Stretch">
<staticText>
<reportElement x="70" y="0" width="434" height="70" uuid="92e7a25f-7eed-4fed-bccd-67c22da4e8fd">
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</reportElement>
<textElement verticalAlignment="Middle">
<font fontName="华文宋体" size="22"/>
</textElement>
<text><![CDATA[ 门诊血糖记录单]]></text>
</staticText>
</band>
</title>
<detail>
<band height="143">
<property name="com.jaspersoft.studio.unit.height" value="px"/>
<subreport>
<reportElement x="0" y="60" width="504" height="83" uuid="5e52a1d0-39f0-431c-9ce4-69544b048cde">
<property name="com.jaspersoft.studio.unit.height" value="px"/>
<property name="com.jaspersoft.studio.unit.x" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{outpatientPoctSubTableList})]]></dataSourceExpression>
<subreportExpression><![CDATA[$P{outpatientPoctSubTablePath}]]></subreportExpression>
</subreport>
<subreport>
<reportElement x="0" y="0" width="504" height="60" uuid="8af27db2-d62e-4ee9-93a1-3d31de633ed2">
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</reportElement>
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{outpatientPoctSubHeaderList})]]></dataSourceExpression>
<subreportExpression><![CDATA[$P{outpatientPoctSubHeaderPath}]]></subreportExpression>
</subreport>
</band>
</detail>
<pageFooter>
<band height="26">
<textField>
<reportElement positionType="FixRelativeToBottom" x="0" y="0" width="504" height="26" uuid="252b6282-3fca-4aee-9421-55e84bffb3d4">
<property name="com.jaspersoft.studio.unit.height" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Right">
<font fontName="华文宋体"/>
</textElement>
<textFieldExpression><![CDATA["第 "+$V{PAGE_NUMBER}+" 页"]]></textFieldExpression>
</textField>
</band>
</pageFooter>
</jasperReport>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.11.0.final using JasperReports Library version 6.11.0-0c4056ccaa4d25a5a8c45672d2f764ea3498bebb -->
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="outpatient_poct_sub_header" pageWidth="504" pageHeight="842" columnWidth="504" leftMargin="0" rightMargin="0" topMargin="0" bottomMargin="0" uuid="35ba0760-bc4e-4a5f-87df-6aaea21e735c">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="outpatientPoctVo"/>
<queryString language="JSON">
<![CDATA[reportHeaders]]>
</queryString>
<field name="patientName" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="patientName"/>
<fieldDescription><![CDATA[patientName]]></fieldDescription>
</field>
<field name="sex" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="sex"/>
<fieldDescription><![CDATA[sex]]></fieldDescription>
</field>
<field name="age" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="age"/>
<fieldDescription><![CDATA[age]]></fieldDescription>
</field>
<field name="medicareCardNo" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="cardNo"/>
<fieldDescription><![CDATA[medicareCardNo]]></fieldDescription>
</field>
<field name="identityId" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="idNumber"/>
<fieldDescription><![CDATA[identityId]]></fieldDescription>
</field>
<title>
<band height="60" splitType="Stretch">
<staticText>
<reportElement x="0" y="0" width="70" height="30" uuid="cd6dacb1-29b2-4f3f-82ca-612685708d34">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<box>
<topPen lineWidth="2.0"/>
</box>
<textElement textAlignment="Right" verticalAlignment="Middle">
<font fontName="华文宋体" size="10"/>
</textElement>
<text><![CDATA[患者姓名:]]></text>
</staticText>
<staticText>
<reportElement x="168" y="0" width="72" height="30" uuid="e858b707-3eeb-4a03-b0e8-f8d8f573ce2b">
<property name="com.jaspersoft.studio.unit.x" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<box>
<topPen lineWidth="2.0"/>
</box>
<textElement textAlignment="Right" verticalAlignment="Middle">
<font fontName="华文宋体" size="10"/>
</textElement>
<text><![CDATA[患者性别:]]></text>
</staticText>
<staticText>
<reportElement x="312" y="0" width="96" height="30" uuid="322dd91a-c818-4c1a-a9d0-1202ea6133af">
<property name="com.jaspersoft.studio.unit.x" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<box>
<topPen lineWidth="2.0"/>
</box>
<textElement textAlignment="Right" verticalAlignment="Middle">
<font fontName="华文宋体" size="10"/>
</textElement>
<text><![CDATA[年 龄:]]></text>
</staticText>
<staticText>
<reportElement x="0" y="30" width="70" height="30" uuid="48ad70b2-dc72-492c-8cf4-dec3d6877535">
<property name="com.jaspersoft.studio.unit.x" value="px"/>
</reportElement>
<box>
<bottomPen lineWidth="2.0"/>
</box>
<textElement textAlignment="Right" verticalAlignment="Middle">
<font fontName="华文宋体" size="10"/>
</textElement>
<text><![CDATA[卡 号:]]></text>
</staticText>
<staticText>
<reportElement x="312" y="30" width="96" height="30" uuid="2d6a4fdb-b148-4a2d-9a2c-6cf77b68a795">
<property name="com.jaspersoft.studio.unit.x" value="px"/>
</reportElement>
<box>
<bottomPen lineWidth="2.0"/>
</box>
<textElement textAlignment="Right" verticalAlignment="Middle">
<font fontName="华文宋体" size="10"/>
</textElement>
<text><![CDATA[身份证号:]]></text>
</staticText>
<textField isBlankWhenNull="true">
<reportElement x="70" y="0" width="98" height="30" uuid="502249c9-e573-42e8-bff6-4dc53502fc94">
<property name="com.jaspersoft.studio.unit.x" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<box>
<topPen lineWidth="2.0"/>
</box>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="华文宋体" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{patientName}]]></textFieldExpression>
</textField>
<textField isBlankWhenNull="true">
<reportElement x="240" y="0" width="72" height="30" uuid="e084b9a1-cbd6-44e7-a036-633af9e5b610">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<box>
<topPen lineWidth="2.0"/>
</box>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="华文宋体" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{sex}]]></textFieldExpression>
</textField>
<textField isBlankWhenNull="true">
<reportElement x="408" y="0" width="96" height="30" uuid="838c751e-0df6-4ff2-963d-25e6af219387">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<box>
<topPen lineWidth="2.0"/>
</box>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="华文宋体" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{age}]]></textFieldExpression>
</textField>
<textField isBlankWhenNull="true">
<reportElement x="70" y="30" width="242" height="30" uuid="9a29342d-0008-4994-a633-d6ab78976805">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<box>
<bottomPen lineWidth="2.0"/>
</box>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="华文宋体" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{medicareCardNo}]]></textFieldExpression>
</textField>
<textField isBlankWhenNull="true">
<reportElement x="408" y="30" width="96" height="30" uuid="257a7069-db00-47fd-898b-528a5eafab7a">
<property name="com.jaspersoft.studio.unit.x" value="px"/>
</reportElement>
<box>
<bottomPen lineWidth="2.0"/>
</box>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="华文宋体" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{identityId}]]></textFieldExpression>
</textField>
</band>
</title>
</jasperReport>
net.sf.jasperreports.extension.registry.factory.simple.font.families=net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactory
net.sf.jasperreports.extension.simple.font.families.lobstertwo=stsong/fonts.xml
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<fontFamilies>
<!--<fontFamily name="Lobster Two">-->
<!--<normal>lobstertwo/LobsterTwo-Regular.otf</normal>-->
<!--<bold>lobstertwo/LobsterTwo-Bold.otf</bold>-->
<!--<italic>lobstertwo/LobsterTwo-Italic.otf</italic>-->
<!--<boldItalic>lobstertwo/LobsterTwo-BoldItalic.otf</boldItalic>-->
<!--<pdfEncoding>Identity-H</pdfEncoding>-->
<!--<pdfEmbedded>true</pdfEmbedded>-->
<!--<!–-->
<!--<exportFonts>-->
<!--<export key="net.sf.jasperreports.html">'Lobster Two', 'Times New Roman', Times, serif</export>-->
<!--</exportFonts>-->
<!--–>-->
<!--</fontFamily>-->
<fontFamily name="华文宋体">
<normal>stsong/stsong.TTF</normal>
<bold>stsong/stsong.TTF</bold>simkai.ttf
<italic>stsong/stsong.TTF</italic>
<boldItalic>stsong/stsong.TTF</boldItalic>
<pdfEncoding>Identity-H</pdfEncoding>
<pdfEmbedded>true</pdfEmbedded>
<exportFonts>
<export key="net.sf.jasperreports.html">'华文宋体', Arial, Helvetica, sans-serif</export>
<export key="net.sf.jasperreports.xhtml">'华文宋体', Arial, Helvetica, sans-serif</export>
</exportFonts>
<!--
<locales>
<locale>en_US</locale>
<locale>de_DE</locale>
</locales>
-->
</fontFamily>
<fontFamily name="楷体">
<normal>stsong/simkai.ttf</normal>
<bold>stsong/simkai.ttf</bold>
<italic>stsong/simkai.ttf</italic>
<boldItalic>stsong/simkai.ttf</boldItalic>
<pdfEncoding>Identity-H</pdfEncoding>
<pdfEmbedded>true</pdfEmbedded>
<exportFonts>
<export key="net.sf.jasperreports.html">'楷体', Arial, Helvetica, sans-serif</export>
<export key="net.sf.jasperreports.xhtml">'楷体', Arial, Helvetica, sans-serif</export>
</exportFonts>
<!--
<locales>
<locale>en_US</locale>
<locale>de_DE</locale>
</locales>
-->
</fontFamily>
</fontFamilies>
\ No newline at end of file
//package com.dmm.pll.loginTest;
//
//import com.dmm.pll.XxlDarlingApplication;
//import lombok.extern.slf4j.Slf4j;
//import org.junit.Test;
//import org.junit.runner.RunWith;
//import org.springframework.boot.test.context.SpringBootTest;
//import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
//import org.springframework.test.context.junit4.SpringRunner;
//import org.springframework.test.context.web.WebAppConfiguration;
//
///**
// * @Author:dongman
// * @Date:2023/6/9 16:37
// */
//@RunWith(SpringRunner.class)
//@SpringBootTest(classes = XxlDarlingApplication.class)
//@WebAppConfiguration
//@Slf4j
//public class LoginTest {
// @Test
// public void initData(){
// String encode = new BCryptPasswordEncoder().encode("123456");
// log.info(encode);
// }
//}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment