开发WebService接口
导入maven
注意:cxf-spring-boot-starter-jaxrs和cxf-rt-rs-extension-providers的版本要保持一致
<?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>cn.com.techfly</groupId>
<artifactId>lzpid</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>lzpid Maven Webapp</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<!-- Spring Boot 父工程 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.9</version>
</parent>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- web支持,SpringMVC, Servlet支持等 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
<version>2.7.9</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
<version>1.3.8.RELEASE</version>
</dependency>
<!-- jdbc数据库操作 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<scope>runtime</scope>
</dependency>
<!-- redis操作 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.influxdb</groupId>
<artifactId>influxdb-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.5</version>
</dependency>
<!--CXF的jax-rs -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxrs</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- 转换JSON插件 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-extension-providers</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
<version>1.3.7</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.23</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>central</id>
<url>https://maven.aliyun.com/repository/public/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>https://maven.aliyun.com/repository/public/</url>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.9</version>
<configuration>
<!-- <skipTests>true</skipTests>-->
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
<version>3.1.2</version>
</plugin>
</plugins>
</build>
</project>
创建PidReport实体类
package cn.com.techfly.lzsh.bean.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class PidReport {
private int count;
private int workid;
private String fullname;
}
创建BaseForm实体类
package cn.com.techfly.lzsh.bean.form;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class BaseForm {
private String apiKey;//密钥
}
创建PidReportForm实体类
package cn.com.techfly.lzsh.bean.form;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import javax.xml.bind.annotation.XmlRootElement;
@Data
@ToString
@NoArgsConstructor
@XmlRootElement(name = "requestDatas")
public class PidReportForm extends BaseForm{
}
创建PidReportData实体类
package cn.com.techfly.lzsh.bean.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@XmlRootElement
public class PidReportData {
private List<PidReport> data;//数据
private String lastTime;//更新时间
private int status;//状态码
private String msg;//调用接口的结果描述
}
创建接口
package cn.com.techfly.lzsh.service;
import cn.com.techfly.lzsh.bean.entity.*;
import cn.com.techfly.lzsh.bean.form.*;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
@ResponseBody
public interface IPidLoopService {
/**
*
* @param form 请求参数
* @return PidReportData
*/
@POST
@Produces(MediaType.APPLICATION_JSON)
@Path("/pidReport")
PidReportData getPidReportList(PidReportForm form);
实现接口
package cn.com.techfly.lzsh.util;
import cn.com.techfly.lzsh.bean.entity.*;
import cn.com.techfly.lzsh.bean.form.*;
import cn.com.techfly.lzsh.constant.StatusCode;
import cn.com.techfly.lzsh.dao.*;
import cn.com.techfly.lzsh.exception.WebServiceLzException;
import cn.com.techfly.lzsh.service.IPidLoopService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
@Slf4j
@Service
public class PidLoopServiceImpl implements IPidLoopService {
@Autowired
private IPidReportDao pidReportDao;
@Override
public PidReportData getPidReportList(PidReportForm form) {
try {
PidReportData result = new PidReportData();
boolean apiKey = checkApiKey(form.getApiKey());
if (!apiKey) {
result.setStatus(StatusCode.DENY.getValue());
result.setMsg(StatusCode.DENY.getName());
return result;
}
List<PidReport> pidReportList = pidReportDao.getPidReportList();
//最新时间
Timestamp lastTime = Timestamp.valueOf(LocalDateTime.now());
//定义日期时间格式化器
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
result.setData(pidReportList);
result.setLastTime(lastTime.toLocalDateTime().format(formatter));
result.setStatus(StatusCode.SUCCEED.getValue());
result.setMsg(StatusCode.SUCCEED.getName());
return result;
} catch (Exception e) {
PidReportData result = new PidReportData();
result.setStatus(StatusCode.ERROR.getValue());
result.setMsg(StatusCode.ERROR.getName());
String msg = "PID台账接口出错!";
log.error(msg, e);
throw new WebServiceLzException(msg, e);
}
}
//验证apiKey
private boolean checkApiKey(String apiKey) {
try {
String decrypt = RsaUtil.decrypt(apiKey);//获取apiKey
String[] split = decrypt.split(";");//拆分apiKey数据
String time = split[1];//获取apiKey中的时间
LocalDateTime parse = LocalDateTime.parse(time, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));//定义时间格式
LocalDateTime now = LocalDateTime.now();//获取最新时间
//判断大于当前时间
// if (parse.isAfter(now)) {
//判断小于当前时间10分钟不满足条件
if (parse.minusMinutes(10).isAfter(now)) {
log.error(time);
log.error(now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
return false;
}
//判断大于当前时间10分钟不满足条件
if (parse.plusMinutes(10).isBefore(now)) {
log.error(time);
log.error(now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
return false;
}
return StringUtils.equals(split[0], "PIDZD@LZSH.COM");
} catch (Exception e) {
log.error(e.getMessage());
}
return false;
}
}
创建Dao层接口
package cn.com.techfly.lzsh.dao;
import cn.com.techfly.lzsh.bean.entity.PidReport;
import java.util.List;
public interface IPidReportDao {
List<PidReport> getPidReportList();
}
创建Dao层实现类
package cn.com.techfly.lzsh.dao.impl;
import cn.com.techfly.lzsh.annotation.DBQuery;
import cn.com.techfly.lzsh.bean.entity.PidReport;
import cn.com.techfly.lzsh.dao.IPidReportDao;
import cn.com.techfly.lzsh.util.BeanRowMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public class PidReportDaoImpl implements IPidReportDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@DBQuery
@Override
public List<PidReport> getPidReportList() {
StringBuilder sql = new StringBuilder();
sql.append("SELECT * FROM T_LOOP_INPUT");
List<PidReport> list = jdbcTemplate.query(sql.toString(), new BeanRowMapper<PidReport>(PidReport.class));
return list;
}
}
BeanRowMapper工具类
package cn.com.techfly.lzsh.util;
import cn.com.techfly.lzsh.annotation.DoubleFormat;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.jdbc.core.RowMapper;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Types;
import java.text.DecimalFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class BeanRowMapper<T> implements RowMapper<T>{
private Class<T> clazz;
public BeanRowMapper(Class<T> clazz){
this.clazz = clazz;
}
@Override
public T mapRow(ResultSet rs, int rowNum) {
try {
T t = this.clazz.newInstance();
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
for(int i = 1; i <= columnCount; i++){
String column = metaData.getColumnName(i);
column = this.getColumnName(column);
int type = metaData.getColumnType(i);
Object value = this.parseTypeAndReturnData(rs, type, i);
Field field = null;
try{
field = this.clazz.getDeclaredField(column);
}catch(NoSuchFieldException e){}
if(field == null){//如果在java类中没有找到数据库表字段对应的属性,直接跳过去不设置值
continue ;
}
if(value != null) {
BeanUtils.setProperty(t, column, value);
}
Class<?> fieldClazz = field.getType();
//double类型的使用DoubleFormat自定义注解保留两位小数
if(field.isAnnotationPresent(DoubleFormat.class)) {
DoubleFormat df = field.getAnnotation(DoubleFormat.class);
DecimalFormat format = new DecimalFormat(df.pattern());
if(type == Types.NUMERIC) {
if(fieldClazz == double.class || fieldClazz == Double.class) {
if(value != null){
Double doubleValue = Double.parseDouble(format.format((BigDecimal)value));
BeanUtils.setProperty(t, column, doubleValue);
}
}
}
if(type == Types.DOUBLE) {
if(fieldClazz == double.class || fieldClazz == Double.class) {
if(value != null){
Double doubleValue = Double.parseDouble(format.format((double)value));
BeanUtils.setProperty(t, column, doubleValue);
}
}
}
}
}
return t;
} catch (Throwable e) {
throw new RuntimeException("ResultSet转换为Bean出错!", e);
}
}
/**
* user_name转成userName
* 数据库表字段转换成java变量
* @param column 数据库字段
* @return java类属性
*/
private String getColumnName(String column) {
String name = "";
if(!StringUtils.isBlank(column) && column.startsWith("F_")) {
String field = column.toLowerCase().substring(2);
Pattern pattern = Pattern.compile("[_+](.)");
Matcher matcher = pattern.matcher(field);
while(matcher.find()){
int index = matcher.start();
String value = matcher.group(1).toUpperCase();
field = field.substring(0, index) + value + field.substring(index + 2);
matcher = pattern.matcher(field);
}
name = field;
}else {
name = column;
}
return name;
}
private Object parseTypeAndReturnData(ResultSet rs, int type, int index) throws Exception{
switch(type){
case Types.NULL:
return null;
case Types.INTEGER:
return rs.getInt(index);
case Types.VARCHAR:
return rs.getString(index);
case Types.DOUBLE:
return rs.getDouble(index);
case Types.TIMESTAMP:
return rs.getTimestamp(index);
case Types.BOOLEAN:
return rs.getBoolean(index);
case Types.DATE:
try {
return rs.getDate(index);
}catch(Exception e){
return rs.getString(index);
}
case Types.NUMERIC:
return rs.getBigDecimal(index);
case Types.NVARCHAR:
return rs.getString(index);
default:
return rs.getString(index);
}
}
}
DBUtil工具类
package cn.com.techfly.lzsh.util;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 新增,修改对象
* @author sc
*
*/
public class DBUtil {
/**
* 新增对象并返回主键ID
* @param template
* @param table
* @param obj
* @return
*/
public static long insertReturn(JdbcTemplate template, String table, Object obj) {
try {
long newId = 0;
StringBuilder buffer = new StringBuilder();
String dbFields="";
String positions="";//占位符
Class clazz = obj.getClass();
//Field[] fields = clazz.getDeclaredFields();
Field[] fields = getPersistedField(clazz);//拿到可序列化的字段
Object[] values = new Object[fields.length];
for(int i = 0; i < fields.length; i++) {
Field field = fields[i];
field.setAccessible(true);
String dbField = getDBFieldName(field.getName());//java变量转数据库字段
values[i] = field.get(obj);
if(i > 0) {
positions += ",";
dbFields += ",";
}
positions += "?";
dbFields += dbField;
}
buffer.append("INSERT INTO "+table+" ("+dbFields+") VALUES ("+positions+")");
System.out.println(buffer.toString()+"["+Arrays.toString(values)+"]");
KeyHolder holder = new GeneratedKeyHolder();
template.update(new MyPreparedStatementCreator(buffer.toString(), values), holder);
newId = holder.getKey().intValue();
return newId;
}catch(Throwable e) {
throw new RuntimeException("新增对象并返回主键ID出错!", e);
}
}
/**
* 新增记录
* @param template
* @param table 表名
* @param obj 新增对象
*/
public static void insert(JdbcTemplate template, String table, Object obj) {
try {
StringBuilder buffer = new StringBuilder();
String dbFields="";
String positions="";//占位符
Class clazz = obj.getClass();
//Field[] fields = clazz.getDeclaredFields();
Field[] fields = getPersistedField(clazz);//获取可序列化的字段
Object[] values = new Object[fields.length];
for(int i = 0; i < fields.length; i++) {
Field field = fields[i];
field.setAccessible(true);
String dbField = getDBFieldName(field.getName());//java变量转数据库字段
values[i] = field.get(obj);
if(i > 0) {
positions += ",";
dbFields += ",";
}
positions += "?";
dbFields += dbField;
}
buffer.append("INSERT INTO "+table+" ("+dbFields+") VALUES ("+positions+")");
System.out.println(buffer.toString()+"["+Arrays.toString(values)+"]");
template.update(buffer.toString(), values);
}catch(Throwable e) {
throw new RuntimeException("新增对象出错!", e);
}
}
public static <T> void insertList(JdbcTemplate template, String table, List<T> list, Class<T> clazz) {
try {
StringBuilder buffer = new StringBuilder();
String dbFields="";
String positions="";//占位符
//Field[] fields = clazz.getDeclaredFields();
Field[] fields = getPersistedField(clazz);//获取可序列化的字段
List<Object[]> valueList = new ArrayList<>();
for(T t: list) {
Object[] values = new Object[fields.length];
for(int i = 0; i < fields.length; i++) {
Field field = fields[i];
field.setAccessible(true);
values[i] = field.get(t);
}
valueList.add(values);
}
for(int i = 0; i < fields.length; i++) {
Field field = fields[i];
field.setAccessible(true);
String dbField = getDBFieldName(field.getName());//java变量转数据库字段
if(i > 0) {
positions += ",";
dbFields += ",";
}
positions += "?";
dbFields += dbField;
}
buffer.append("INSERT INTO "+table+" ("+dbFields+") VALUES ("+positions+")");
System.out.println(buffer.toString());
template.batchUpdate(buffer.toString(), valueList);
}catch(Throwable e) {
throw new RuntimeException("批量新增对象出错!", e);
}
}
/**
* 修改记录
* @param template
* @param table 表名
* @param obj java对象
* @param conditions 条件字段(不被修改)
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
public static void update(JdbcTemplate template, String table, Object obj, String...conditions) {
try {
StringBuilder buffer = new StringBuilder();
String sql="UPDATE "+table+" SET ";
String where = "WHERE ";
Class clazz = obj.getClass();
//Field[] fields = clazz.getDeclaredFields();
Field[] fields = getPersistedField(clazz);//获取可序列化的字段
int index1 = 0;
Object[] values = new Object[fields.length ];
//拼接set
for(int i = 0; i < fields.length; i++) {
Field field = fields[i];
field.setAccessible(true);
String fieldName = field.getName();
String dbField = getDBFieldName(fieldName);//java变量转数据库字段
boolean update = true;//是否需要更新
for(int j = 0; j < conditions.length; j++) {
if(conditions[j].equals(fieldName)) {
update = false;
}
}
if(update) {
values[index1++] = field.get(obj);
sql = sql + dbField + "=?,";
}
}
sql = sql.substring(0, sql.length() - 1);
//拼接where
for(int i = 0; i < conditions.length; i++) {
for(int j = 0; j < fields.length; j++) {
Field field = fields[j];
field.setAccessible(true);
String fieldName = field.getName();
String dbField = getDBFieldName(fieldName);//java变量转数据库字段
if(conditions[i].equals(fieldName)) {
values[index1++] = field.get(obj);
where = where + dbField + "=? AND ";
continue ;
}
}
}
if(where.length() > 0) {
where = where.substring(0, where.length() - 4);
}
System.out.println(sql+" "+where+"["+Arrays.toString(values)+"]");
template.update(sql+" "+where, values);
}catch(Throwable e) {
throw new RuntimeException("更新对象出错!", e);
}
}
/**
* 获取可序列化的字段(没有使用org.springframework.data.annotation.Transient这个注解的字段)
* @param clazz
* @return
*/
private static Field[] getPersistedField(Class clazz){
Field[] fields = clazz.getDeclaredFields();
List<Field> list = Arrays.asList(fields);
list = list.stream()
.filter(field -> !field.isAnnotationPresent(org.springframework.data.annotation.Transient.class))
.collect(Collectors.toList());
return list.toArray(new Field[list.size()]);
}
/**
* userName转为F_USER_NAME
* java对象字段转数据库表字段
* @param field
* @return
*/
private static String getDBFieldName(String field) {
String dbField = "F_"+field.substring(0, 1);
String upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String lower = upper.toLowerCase();
for(int i = 1; i < field.length(); i++) {
String s = String.valueOf(field.charAt(i));
if(upper.contains(s)) {//大写字母
dbField = dbField + "_" + s;
}else if(lower.contains(s)) {//小写字母
dbField = dbField + s;
}else {//数字或下划线
dbField = dbField + s;
}
}
return dbField.toUpperCase();
}
/*public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
EditDepartmentForm add = new EditDepartmentForm();
add.setFullName("测试");
//add.setParentId(0);
add.setChangeTime(new Timestamp(new Date().getTime()));
add.setChangeUser(2);
add.setEngName("TEST");
add.setSort(1);
update(null, "T_DEPARTMENT", add, "id");
System.out.println(NumberUtils.isNumber("00.99"));
}*/
}
MyPreparedStatementCreator工具类
package cn.com.techfly.lzsh.util;
import org.springframework.jdbc.core.PreparedStatementCreator;
import java.sql.*;
public class MyPreparedStatementCreator implements PreparedStatementCreator{
private String sql;
private Object[] params;
public MyPreparedStatementCreator(String sql, Object...params){
this.sql = sql;
this.params = params;
}
@Override
public PreparedStatement createPreparedStatement(Connection conn)
throws SQLException {
PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
try{
this.parseParams(ps, params);
return ps;
}catch(Exception e){
throw new RuntimeException("解析SQL语句参数出错!", e);
}
}
private void parseParams(PreparedStatement statement, Object...obj) throws Exception{
for(int i = 0; i < obj.length; i++){
Object param = obj[i];
if(param == null){
statement.setNull(i + 1, Types.NULL);
}else if(param instanceof Integer){
statement.setInt(i + 1, (Integer)param);
}else if(param instanceof String){
statement.setString(i + 1, (String)param);
}else if(param instanceof Double){
statement.setDouble(i + 1, (Double)param);
}else if(param instanceof Long){
statement.setLong(i + 1, (Long)param);
}else if(param instanceof Timestamp){
statement.setTimestamp(i + 1, (Timestamp)param);
}else if(param instanceof Boolean){
statement.setBoolean(i + 1, (Boolean)param);
}else if(param instanceof Date){
statement.setDate(i + 1, new Date(((Date) param).getTime()));
}else{
statement.setString(i + 1, (String)param);
}
}
}
}
编写获取Redis数据工具类
package cn.com.techfly.lzsh.util;
import cn.com.techfly.lzsh.config.SpringBeanUtil;
import cn.com.techfly.lzsh.influxDB.HisData;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
public class Redis0Util {
private static final String LOOP_CALC_TIME = "LoopCalcTime";
private static final String STATIONARY_TIME = "StationaryTime";
private static final String F_TIME = "F_TIME";
private static final String redis = "redis";
/**
* 获取回路计算时间
*
* @return 字符串
*/
public static String getLoopCalcTime() {
Optional<StringRedisTemplate> optional = SpringBeanUtil.getBean(redis, StringRedisTemplate.class);
if (!optional.isPresent()) {
return "";
}
StringRedisTemplate redisTemplate = optional.get();
String loopCalcTime = redisTemplate.opsForValue().get(LOOP_CALC_TIME);
if (!StringUtils.isBlank(loopCalcTime)) {
loopCalcTime = loopCalcTime.replace("_", " ");
}
return loopCalcTime;
}
/**
* 获取StationaryTime
*
* @return 字符串
*/
public static String getStationaryTime() {
Optional<StringRedisTemplate> optional = SpringBeanUtil.getBean(redis, StringRedisTemplate.class);
if (!optional.isPresent()) {
return "";
}
StringRedisTemplate redisTemplate = optional.get();
String stationaryTime = redisTemplate.opsForValue().get(STATIONARY_TIME);
if (!StringUtils.isBlank(stationaryTime)) {
stationaryTime = stationaryTime.replace("_", " ");
}
return stationaryTime;
}
/**
* 获取F_TIME的值
*
* @return
*/
public static String getTime() {
Optional<StringRedisTemplate> optional = SpringBeanUtil.getBean(redis, StringRedisTemplate.class);
if (!optional.isPresent()) {
return "";
}
StringRedisTemplate redisTemplate = optional.get();
String time = redisTemplate.opsForValue().get(F_TIME);
if (!StringUtils.isBlank(time)) {
time = time.replace("_", " ");
}
return time;
}
public static List<HisData> getHisDataList(String dpids) {
List<String> dpIdList = new ArrayList<>();
if (!StringUtils.isBlank(dpids)) {
dpIdList = Arrays.asList(dpids.split(","));
}
List<HisData> list = new ArrayList<>();
Optional<StringRedisTemplate> optional = SpringBeanUtil.getBean(redis, StringRedisTemplate.class);
if (!optional.isPresent()) {
return list;
}
StringRedisTemplate redisTemplate = optional.get();
Set<String> sets = redisTemplate.keys("*");
if (sets != null && sets.size() > 0 && sets.contains(F_TIME)) {
String timeValue = redisTemplate.opsForValue().get(F_TIME);
for (String key : sets) {
String value = redisTemplate.opsForValue().get(key);
if (F_TIME.equals(key) || LOOP_CALC_TIME.equals(key)) {
continue;
}
if (value != null && value.contains(",")) {
HisData hisData = new HisData(key, timeValue, value, list.size());
if (dpIdList.size() > 0 && dpIdList.contains(String.valueOf(hisData.getDpId()))) {
list.add(hisData);
}
if (dpIdList.size() == 0) {
list.add(hisData);
}
}
}
}
return list;
}
public static List<String> getDpidList() {
List<String> list = new ArrayList<>();
Optional<StringRedisTemplate> optional = SpringBeanUtil.getBean(redis, StringRedisTemplate.class);
if (!optional.isPresent()) {
return list;
}
StringRedisTemplate redisTemplate = optional.get();
Set<String> sets = redisTemplate.keys("*[,]*");
if (sets != null && sets.size() > 0) {
List<String> tempList = sets.stream().collect(Collectors.toList());
for (String str : tempList) {
String dpid = str.substring(0, str.indexOf(","));
if (!list.contains(dpid)) {
list.add(dpid);
}
}
}
return list;
}
}
利用RSA编写apiKey解密类
package cn.com.techfly.lzsh.util;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
public class RsaUtil {
//私钥
private static final String privateKey = "私钥";
/**
* 解密方法
*/
public static String decrypt(String s1) {
RSA rsa2 = new RSA(privateKey, null);
String s2 = rsa2.decryptStr(s1, KeyType.PrivateKey);
return s2;
}
}
编写application-dev.properties.yml配置工具
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.url=jdbc:sqlserver://127.0.0.1:1433;DatabaseName=数据库名;encrypt=true;trustServerCertificate=true
spring.datasource.username=账号
spring.datasource.password=密码
###connection pool
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
##ms
spring.datasource.maxWait=60000
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
##spring.datasource.filters=stat,wall,log4j
spring.datasource.filters=stat,log4j
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=200
spring.datasource.logSlowSql=true
## redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.database=0
spring.redis.pool.max-active=100
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.timeout=60000
编写application.properties.yml配置文件
server.port=8088
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
spring.mvc.static-path-pattern=/static/**
spring.profiles.active=dev
spring.http.multipart.enabled=false
spring.servlet.multipart.enabled=false
application.version=20240129
配置Druid数据源
package cn.com.techfly.lzsh.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class DruidConfig {
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.driver-class-name}")
private String driverClassName;
@Value("${spring.datasource.initial-size}")
private int initialSize;//初始化时建立物理连接的个数
@Value("${spring.datasource.min-idle}")
private int minIdle;//最小连接数量
@Value("${spring.datasource.max-active}")
private int maxActive;//最大连接数量
@Value("${spring.datasource.max-wait}")
private int maxWait;//获取连接时最大等待时间,单位毫秒
@Value("${spring.datasource.time-between-eviction-runs-millis}")
private int timeBetweenEvictionRunsMillis;//配置隔多久进行一次检测(检测可以关闭的空闲连接)
@Value("${spring.datasource.min-evictable-idle-time-millis}")
private int minEvictableIdleTimeMillis;//配置连接在池中的最小生存时间
@Value("${spring.datasource.validation-query}")
private String validationQuery;//用来检测连接是否有效的sql,要求是一个查询语句
@Value("${spring.datasource.test-while-idle}")
private boolean testWhileIdle;//建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效
@Value("${spring.datasource.test-on-borrow}")
private boolean testOnBorrow;//申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
@Value("${spring.datasource.test-on-return}")
private boolean testOnReturn;//归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
@Value("${spring.datasource.pool-prepared-statements}")
private boolean poolPreparedStatements;//是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
@Value("${spring.datasource.max-pool-prepared-statement-per-connection-size}")
private int maxPoolPreparedStatementPerConnectionSize;//指定每个连接上PSCache的大小
/**
* 配置DataSouurce
* @return
*/
@Bean
public DataSource duridDataSource(){
try{
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(url);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
return datasource;
}catch(Exception e){
throw new RuntimeException("初始化Durid连接池出错!", e);
}
}
}
配置redis
package cn.com.techfly.lzsh.config;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import redis.clients.jedis.JedisPoolConfig;
@Configuration
public class RedisConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.database}")
private int database;
@Value("${spring.redis.pool.max-active}")
private int maxActive;
@Value("${spring.redis.pool.max-wait}")
private int maxWait;
@Value("${spring.redis.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.pool.min-idle}")
private int minIdle;
@Value("${spring.redis.timeout}")
private int timeout;
@Bean("redis")
public StringRedisTemplate stringRedisTemplate(){
RedisConnectionFactory cf = this.getRedisConnectionFactory(0);
return new StringRedisTemplate(cf);
}
@Bean("redis1")
public StringRedisTemplate stringRedisTemplate1(){
RedisConnectionFactory cf = this.getRedisConnectionFactory(1);
return new StringRedisTemplate(cf);
}
@Bean("redis2")
public StringRedisTemplate stringRedisTemplate2(){
RedisConnectionFactory cf = this.getRedisConnectionFactory(2);
return new StringRedisTemplate(cf);
}
@SuppressWarnings("deprecation")
private RedisConnectionFactory getRedisConnectionFactory(int dbNum) {
JedisConnectionFactory jedisFactory = new JedisConnectionFactory();
jedisFactory.setHostName(host);
jedisFactory.setPort(port);
if(!StringUtils.isBlank(password)) {
jedisFactory.setPassword(password);
}
jedisFactory.setDatabase(dbNum);
jedisFactory.setTimeout(timeout);
JedisPoolConfig poolConfig = new JedisPoolConfig(); // 进行连接池配置
poolConfig.setMaxTotal(maxActive);
poolConfig.setMaxIdle(maxIdle);
poolConfig.setMinIdle(minIdle);
poolConfig.setMaxWaitMillis(maxWait);
jedisFactory.setPoolConfig(poolConfig);
jedisFactory.afterPropertiesSet(); // 初始化连接池配置
return jedisFactory;
}
}
配置spring工具类
package cn.com.techfly.lzsh.config;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class SpringBeanUtil implements ApplicationContextAware{
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringBeanUtil.applicationContext == null) {
SpringBeanUtil.applicationContext = applicationContext;
}
System.out.println("========ApplicationContext配置成功,在普通类可以通过调用SpringUtils.getAppContext()获取applicationContext对象,applicationContext="+SpringBeanUtil.applicationContext+"========");
}
//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
public static Optional<Object> getBean(String name){
Optional<Object> optional = Optional.empty();
try{
Object bean = getApplicationContext().getBean(name);
optional = Optional.of(bean);
}catch (Exception e){}
return optional;
}
//检查bean是否已经存在
public static boolean existBean(String name){
return applicationContext.containsBean(name);
}
//通过class获取Bean.
public static <T> Optional<T> getBean(Class<T> clazz){
Optional optional = Optional.empty();
try {
T bean = getApplicationContext().getBean(clazz);
optional = Optional.of(bean);
}catch (Exception e){}
return optional;
}
//通过name,以及Clazz返回指定的Bean
public static <T> Optional<T> getBean(String name, Class<T> clazz){
Optional<T> optional = Optional.empty();
try{
T bean = getApplicationContext().getBean(name, clazz);
optional = Optional.of(bean);
}catch (Exception e){}
return optional;
}
//注入并返回Bean
public static <T> T registerBean(String name, Class<T> clazz, Object... args) {
ConfigurableApplicationContext cApplicationContext = (ConfigurableApplicationContext)getApplicationContext();
if(applicationContext.containsBean(name)) {
T bean = cApplicationContext.getBean(name, clazz);
if (bean.getClass().isAssignableFrom(clazz)) {
return bean;
} else {
throw new RuntimeException("BeanName 重复 " + name);
}
}
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
for (Object arg : args) {
beanDefinitionBuilder.addConstructorArgValue(arg);
}
BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry) cApplicationContext.getBeanFactory();
beanFactory.registerBeanDefinition(name, beanDefinition);
return cApplicationContext.getBean(name, clazz);
}
//删除bean
public static void removeBean(String name){
ConfigurableApplicationContext cApplicationContext = (ConfigurableApplicationContext)getApplicationContext();
if(applicationContext.containsBean(name)) {
BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry) cApplicationContext.getBeanFactory();
beanFactory.removeBeanDefinition(name);
}
}
}
配置WebServiceConfig类
package cn.com.techfly.lzsh.config;
import cn.com.techfly.lzsh.service.IPidLoopService;
import org.apache.cxf.Bus;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WebServiceConfig {
@Autowired
private Bus bus;
@Autowired
private IPidLoopService pidLoopService;
@Bean(name="rsServletRegistrationBean")
public ServletRegistrationBean getRegistrationBean(){
return new ServletRegistrationBean(new CXFServlet(), "/webapi/*");
}
@Bean
public Server createServer(){
JAXRSServerFactoryBean endpoint= new JAXRSServerFactoryBean();
//设置参数
//设置访问地址
endpoint.setAddress("/pidzd");
//设置bus
endpoint.setBus(bus);
//设置实体类对象
endpoint.setServiceBean(pidLoopService);
return endpoint.create();
}
}
创建SpringBoot启动类
package cn.com.techfly.lzsh;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LzPidWebServiceApplication {
public static void main(String[] args) {
SpringApplication.run(LzPidWebServiceApplication.class,args);
}
}
运行程序
成功运行服务端代码。
使用Eolink Apikit工具访问接口
在左侧选择快速测试