first commit

This commit is contained in:
cys841515238
2023-03-02 16:13:28 +08:00
commit 2733a60b97
741 changed files with 76931 additions and 0 deletions

View File

@@ -0,0 +1,342 @@
package com.peanut.common.Interface;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.peanut.common.utils.HttpClientUtils;
import com.peanut.common.utils.KdUtils;
import com.peanut.modules.book.entity.FMSCommodity;
import com.peanut.modules.book.entity.FMSOrderEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
*
* @技术QQ群: 可登录官网https://www.kdniao.com/右侧查看技术群号
* @see: https://kdniao.com/api-eorder
* @copyright: 深圳市快金数据技术服务有限公司
* ID和Key请到官网申请https://kdniao.com/reg
* 电子面单接口
* 此接口用于向快递/快运公司下发订单并获取快递单号返回电子面单html模板通知快递员上门取件。该功能支持情况需查看技术文档。
*正式地址https://api.kdniao.com/api/EOrderService
*
*
* 系统级参数
* RequestData String R 请求内容为JSON格式 详情可参考接口技术文档https://www.kdniao.com/documents
* EBusinessID String R 用户ID
* RequestType String R 请求接口指令
* DataSign String R 数据内容签名,加密方法为:把(请求内容(未编码)+ApiKey)进行MD5加密--32位小写然后Base64编码最后进行URL(utf-8)编码
* DataType String R DataType=2请求、返回数据类型均为JSON格式
* 应用级参数
* R-必填RequiredO-可选OptionalC-报文中该参数在一定条件下可选Conditional
* Callback String(50) O 用户自定义回传字段
* CustomerName String(50) C 电子面单客户号,需要下载《快递鸟电子面单客户号参数对照表.xlsx》参考对应字段传值 https://www.kdniao.com/documents
* CustomerPwd String(50) C 同上
* SendSite String(50) C 同上
* SendStaff String(50) C 同上
* MonthCode String(20) C 同上
* CustomArea String(500) O 商家自定义区域,需查看技术文档说明
* WareHouseID String(30) C 发货仓编码(ShipperCode为JD或JDKY时必填)
* TransType Int(2) O 京东(ShipperCode为JD或JDKY)的产品类型,需查看技术文档说明
* ShipperCode String(10) R 快递公司编码详细编码参考《快递鸟接口支持快递公司编码.xlsx》 https://www.kdniao.com/documents
* LogisticCode String(30) O 快递单号(仅宅急送可用)
* OrderCode String(30) R 订单编号(自定义,不可重复)
* ThrOrderCode String(50) C 京东商城的订单号(ShipperCode为JD且ExpType为1时必填)
* PayType Int(1) R 运费支付方式1-现付2-到付3-月结
* ExpType String(2) R 详细快递类型参考《快递公司快递业务类型.xlsx》 https://www.kdniao.com/documents
* IsReturnSignBill Int(1) O 是否要求签回单 0-不要求1-要求
* Receiver.Company String(30) O 收件人公司
* Receiver.Name String(30) R 收件人
* Receiver.Tel String(20) R 电话(电话与手机,必填一个)
* Receiver.Mobile String(20) R 手机(电话与手机,必填一个)
* Receiver.PostCode String(10) C 收件地邮编(ShipperCode为EMS、YZPY、YZBK时必填)
* Receiver.ProvinceName String(20) R 收件省(如广东省,不要缺少“省”;如是直辖市,请直接传北京、上海等;如是自治区,请直接传广西壮族自治区等)
* Receiver.CityName String(20) R 收件市(如深圳市,不要缺少“市;如是市辖区,请直接传北京市、上海市等”)
* Receiver.ExpAreaName String(20) R 收件区/县(如福田区,不要缺少“区”或“县”)
* Receiver.Address String(100) R 收件人详细地址(不用传省市区)
* Sender.Company String(30) O 发件人公司
* Sender.Name String(30) R 发件人
* Sender.Tel String(20) R 电话(电话与手机,必填一个)
* Sender.Mobile String(20) R 手机(电话与手机,必填一个)
* Sender.PostCode String(10) C 发件地邮编(ShipperCode为EMS、YZPY、YZBK时必填)
* Sender.ProvinceName String(20) R 发件省(如广东省,不要缺少“省”;如是直辖市,请直接传北京、上海等;如是自治区,请直接传广西壮族自治区等)
* Sender.CityName String(20) R 发件市(如深圳市,不要缺少“市;如是市辖区,请直接传北京市、上海市等”)
* Sender.ExpAreaName String(20) R 发件区/县(如福田区,不要缺少“区”或“县”)
* Sender.Address String(100) R 发件人详细地址(不用传省市区)
* IsNotice Int(1) O 是否通知快递员上门揽件 0-通知1-不通知不填则默认为1
* StartDate String(32) O 上门揽件时间段格式YYYY-MM-DD HH24:MM:SS
* EndDate String(32) O 上门揽件时间段格式YYYY-MM-DD HH24:MM:SS
* Weight Double(10,3) C 包裹总重量kg 1、当为快运的订单时必填2、ShipperCode为JD时必填
* Quantity Int(2) R 包裹数(最多支持300件)一个包裹对应一个运单号如果是大于1个包裹返回则按照子母件的方式返回母运单号和子运单号
* Volume Double(20,3) C 包裹总体积m3 1、当为快运的订单时必填2、ShipperCode为JD时必填
* Remark String(60) O 备注
* AddService.Name String(20) C 增值服务名称(数组形式,可以有多个增值服务)
* AddService.Value String(30) C 增值服务值
* AddService.CustomerID String(30) O 客户标识
* Commodity.GoodsName String(100) R 商品名称(数组形式)
* IsReturnPrintTemplate String(1) O 是否返回电子面单模板0-不需要1-需要
* IsSendMessage Int(1) O 是否订阅短信0-不需要1-需要
* IsSubscribe String(1) O 是否订阅轨迹推送 0-不订阅1-订阅不填默认为1
* TemplateSize String(10) O 模板规格,需查看技术文档说明
* PackingType Int(2) C 包装类型(快运字段),需查看技术文档说明
* DeliveryMethod Int(1) C 送货方式/派送类型/配送方式(快运字段),需查看技术文档说明
* CurrencyCode String(10) C 货物单价的币种CNY: 人民币 HKD: 港币 NTD: 新台币 MOP: 澳门元 (ShipperCode为SF且收件地址为港澳台地区必填)
* Dutiable.DeclaredValue Number(15,3) C 申报价值订单货物总声明价值包含子母件精确到小数点后3位 (ShipperCode为SF且收件地址为港澳台地区必填)
*/
public class KdApiEOrder {
//用户ID快递鸟提供注意保管不要泄漏
private static String EBusinessID="1788532";//即用户ID
// private static String EBusinessID="test1788532";//即用户ID
//API key快递鸟提供注意保管不要泄漏
private static String ApiKey="f4342e6c-5cfa-458f-997b-f973eb29eb1d";//即API key
// private static String ApiKey="34f033ae-9c73-4b9a-899e-943a65fd86bf";//即API key
// 电子面单请求url
private static String OnlineReqURL="https://api.kdniao.com/api/EOrderService";
// private static String OnlineReqURL="http://sandboxapi.kdniao.com:8080/kdniaosandbox/gateway/exterfaceInvoke.json";
// 物流信息跟踪
private String TrackReqURL="https://api.kdniao.com/api/dist";
// private static String TrackReqURL="http://sandboxapi.kdniao.com:8080/kdniaosandbox/gateway/exterfaceInvoke.json";
// 即时查询物流信息
private static String QueryReqURL="https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx";
// private static String QueryReqURL="http://sandboxapi.kdniao.com:8080/kdniaosandbox/gateway/exterfaceInvoke.json";
// public static void main(String[] args) {
// try {
// KdApiEOrder api = new KdApiEOrder();
// System.out.println(api.orderOnlineByJson());
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
/**
* 电子面单接口
* 此接口用于向快递/快运公司下发订单并获取快递单号返回电子面单html模板通知快递员上门取件。
* @return
* @throws Exception
*/
public static JSONArray orderOnlineByJson(List<FMSOrderEntity> fmsOrderList) throws Exception{
String RequestData= "";
JSONArray jsonArray = new JSONArray();
String cust = "";
for(FMSOrderEntity fms : fmsOrderList){
// 组装应用级参数
RequestData= "{"+
"'OrderCode': '" + fms.getOrderCode() + "',"+
"'ShipperCode': '" + fms.getShipperCode() + "',";
if("JD".equals(fms.getShipperCode())){
cust = "'CustomerName': '010K1598220',"+
"'CustomerPwd': '',";
}
if ("YD".equals(fms.getShipperCode())){
// cust = "'CustomerName': '114198226272',"+
// "'CustomerPwd': 'gcs5XavNGRVqbhUmHpnkDd7Fi3T9Ef',";
cust = "'CustomerName': 'testyd',"+
"'CustomerPwd': 'testydpwd',";
}
cust += "'MonthCode': '',"+
"'SendSite': '',"+
"'PayType': 1,"+
"'MonthCode': '',"+
"'ExpType': 1,"+
"'Cost': 1.0,"+
"'OtherCost': 1.0,"+
// "'TemplateSize':'130'"+
"'Sender': {"+
"'Company': '众妙之门',"+
"'Name': 'Taylor',"+
"'Mobile': '12345678901',"+
"'ProvinceName': '天津',"+
"'CityName': '天津市',"+
"'ExpAreaName': '南开区',"+
"'Address': '天津市南开区融创中心中南广场东区2号楼605'"+
"},"+
"'Receiver': {"+
"'Company': '',"+
"'Name': '" + fms.getReceiverName() + "',"+
"'Mobile': '" + fms.getReceiverMobile() + "',"+
"'ProvinceName': '" + fms.getReceiverProvinceName() + "',"+
"'CityName': '" + fms.getReceiverCityName() + "',"+
"'ExpAreaName': '" + fms.getReceiverExpAreaName() + "',"+
"'Address': '" + fms.getReceiverAddress() + "'"+
"},"+
"'Commodity': [" ;
String s = "";
for(FMSCommodity fmsCommodity : fms.getCommodityList() ){
s += "{'GoodsName': '"+fmsCommodity.getGoodsName()+ "'},";
}
s = s.substring(0,s.lastIndexOf(','));
String a = s + "],"+
"'AddService': [],"+
"'IsReturnPrintTemplate':1,"+
"'Remark': "+ fms.getRemark()+""+
"}";
// 组装系统级参数
Map<String, String> params = new HashMap<String, String>();
params.put("RequestData", KdUtils.urlEncoder(RequestData + cust + a, "UTF-8"));
params.put("EBusinessID", EBusinessID);
params.put("RequestType", "1007");
String dataSign=KdUtils.encrypt(RequestData + cust + a, ApiKey, "UTF-8");
System.out.println(RequestData + a);
params.put("DataSign", KdUtils.urlEncoder(dataSign, "UTF-8"));
params.put("DataType", "2");
// 以form表单形式提交post请求post请求体中包含了应用级参数和系统级参数
String result= HttpClientUtils.kdSendPost(OnlineReqURL, params);
jsonArray.add(result);
}
return jsonArray;
}
/**
* 电子面单取消接口
* 此接口用于取消“电子面单接口”下单成功的订单,回收快递单号。
*
* 应用级参数
* R-必填RequiredO-可选OptionalC-报文中该参数在一定条件下可选Conditional
* ShipperCode String(10) R 快递公司编码
* OrderCode String(30) R 订单编号
* ExpNo String(30) R 快递单号
* CustomerName String(50) R 电子面单客户号
* CustomerPwd String(30) R 电子面单密码(顺丰不需要)
*
*/
@RequestMapping("/cancel")
public static String cancelOrderByJson(@RequestParam Map<String,Object> param) throws Exception{
// 组装应用级参数
String RequestData= "{"+
"'ShipperCode':" +param.get("ShipperCode")+","+
"'OrderCode': "+param.get("orderSn")+","+
"'ExpNo': '"+param.get("ExpNo")+"',"+
"}";
// 组装系统级参数
Map<String, String> params = new HashMap<String, String>();
params.put("RequestData", KdUtils.urlEncoder(RequestData, "UTF-8"));
params.put("EBusinessID", EBusinessID);
params.put("RequestType", "1147");
String dataSign=KdUtils.encrypt(RequestData, ApiKey, "UTF-8");
params.put("DataSign", KdUtils.urlEncoder(dataSign, "UTF-8"));
params.put("DataType", "2");
// 以form表单形式提交post请求post请求体中包含了应用级参数和系统级参数
String result=HttpClientUtils.kdSendPost(OnlineReqURL, params);
// JSONObject json = JSONObject.parseObject(result);
// if(json.get("Success").equals("true")){
// // TODO 返回值为Success时 存入到系统中的 sys_interface_log 表
//
// }else{
// // TODO 存入到系统中的 sys_interface_fail 表中
// // TODO 存入interfaceType 值为 2 用作以后人工干预重推 区分是什么接口
//
// }
//根据公司业务处理返回的信息......
return result;
}
/**
*
* 即时查询接口(增值版)
* 此接口用于向快递公司实时查询物流轨迹信息。
*
* 应用级参数
* R-必填RequiredO-可选OptionalC-报文中该参数在一定条件下可选Conditional
* OrderCode String(30) O 订单编号
* CustomerName String(50) C ShipperCode为SF时必填对应寄件人/收件人手机号后四位ShipperCode为其他快递时可不填或保留字段不可传值
* ShipperCode String(10) R 快递公司编码 详细编码参考《快递鸟接口支持快递公司编码.xlsx》
* LogisticCode String(30) R 快递单号
*/
@RequestMapping("/queryOrder")
public static String queryOrderOnlineByJson(@RequestParam Map<String,Object> param) throws Exception{
// 组装应用级参数
String RequestData= "{"+
"'ShipperCode': '"+ param.get("ShipperCode") +"',"+
"'LogisticCode': '"+ param.get("LogisticCode") +"',"+
"}";
// 组装系统级参数
Map<String,String> params = new HashMap<String,String>();
params.put("RequestData", KdUtils.urlEncoder(RequestData, "UTF-8"));
params.put("EBusinessID", EBusinessID);
params.put("RequestType", "8001");//在途监控即时查询接口指令8001/地图版即时查询接口指令8003
String dataSign=KdUtils.encrypt(RequestData, ApiKey, "UTF-8");
params.put("DataSign", KdUtils.urlEncoder(dataSign, "UTF-8"));
params.put("DataType", "2");
// 以form表单形式提交post请求post请求体中包含了应用级参数和系统级参数
String result=HttpClientUtils.kdSendPost(QueryReqURL, params);
return result;
}
/**
* 物流跟踪接口(增值版)
* 此接口用于向快递鸟订阅物流轨迹信息。
*
* 应用级参数
* R-必填RequiredO-可选OptionalC-报文中该参数在一定条件下可选Conditional
* Callback String(50) O 用户自定义回传字段
* ShipperCode String(10) R 快递公司编码 详细编码参考《快递鸟接口支持快递公司编码.xlsx》
* LogisticCode String(30) R 快递单号
* CustomerName String(50) C ShipperCode为SF时必填对应寄件人/收件人手机号后四位ShipperCode为其他快递时可不填或保留字段不可传值
*/
@RequestMapping("/track")
public String trackOrderByJson(@RequestParam Map<String,Object> param) throws Exception{
// 组装应用级参数
String RequestData= "{"+
"'Callback':'OrderCode',"+
"'ShipperCode':'" + param.get("ShipperCode") + "',"+
"'LogisticCode':'" + param.get("LogisticCode") + "',"+
"}";
// 组装系统级参数
Map<String,String> params = new HashMap<String,String>();
params.put("RequestData", KdUtils.urlEncoder(RequestData, "UTF-8"));
params.put("EBusinessID", EBusinessID);
params.put("RequestType", "8008");//在途监控订阅接口指令8008/地图版订阅接口指令8005
String dataSign=KdUtils.encrypt(RequestData, ApiKey, "UTF-8");
params.put("DataSign", KdUtils.urlEncoder(dataSign, "UTF-8"));
params.put("DataType", "2");
// 以form表单形式提交post请求post请求体中包含了应用级参数和系统级参数
String result=HttpClientUtils.kdSendPost(TrackReqURL, params);
return result;
}
/**
*
* 此接口用于快递鸟推送物流轨迹信息。
* @return
* @throws Exception
*/
// TODO 后续编写 获取信息存库 调用消息队列 异步推送给 一路健康 or 疯子读书
@RequestMapping("/pushOrder")
public String subscribeOrderByJSON() throws Exception{
// JSONObject json = JSONObject.parseObject(result);
// if(json.get("Success").equals("true")){
// // TODO 返回值为Success时 存入到系统中的 sys_interface_log 表
//
// }else{
// // TODO 存入到系统中的 sys_interface_fail 表中
// // TODO 存入interfaceType 值为 5 用作以后人工干预重推 区分是什么接口
//
// }
return "";
}
}

View File

@@ -0,0 +1,28 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 系统日志注解
*
* @author Mark sunlightcs@gmail.com
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
String value() default "";
}

View File

@@ -0,0 +1,46 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.aspect;
import com.peanut.common.exception.RRException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
/**
* Redis切面处理类
*
* @author Mark sunlightcs@gmail.com
*/
@Aspect
@Configuration
public class RedisAspect {
private Logger logger = LoggerFactory.getLogger(getClass());
//是否开启redis缓存 true开启 false关闭
@Value("${spring.redis.open: false}")
private boolean open;
@Around("execution(* com.peanut.common.utils.RedisUtils.*(..))")
public Object around(ProceedingJoinPoint point) throws Throwable {
Object result = null;
if(open){
try{
result = point.proceed();
}catch (Exception e){
logger.error("redis error", e);
throw new RRException("Redis服务异常");
}
}
return result;
}
}

View File

@@ -0,0 +1,101 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.aspect;
import com.google.gson.Gson;
import com.peanut.common.annotation.SysLog;
import com.peanut.common.utils.HttpContextUtils;
import com.peanut.common.utils.IPUtils;
import com.peanut.modules.sys.entity.SysLogEntity;
import com.peanut.modules.sys.entity.SysUserEntity;
import com.peanut.modules.sys.service.SysLogService;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
/**
* 系统日志,切面处理类
*
* @author Mark sunlightcs@gmail.com
*/
@Aspect
@Component
public class SysLogAspect {
@Autowired
private SysLogService sysLogService;
@Pointcut("@annotation(com.peanut.common.annotation.SysLog)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
//执行方法
Object result = point.proceed();
//执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
//保存日志
saveSysLog(point, time);
return result;
}
private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
SysLogEntity sysLog = new SysLogEntity();
SysLog syslog = method.getAnnotation(SysLog.class);
if(syslog != null){
//注解上的描述
sysLog.setOperation(syslog.value());
}
//请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLog.setMethod(className + "." + methodName + "()");
//请求的参数
Object[] args = joinPoint.getArgs();
try{
String params = new Gson().toJson(args);
sysLog.setParams(params);
}catch (Exception e){
}
//获取request
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
//设置IP地址
sysLog.setIp(IPUtils.getIpAddr(request));
//用户名
String username = ((SysUserEntity) SecurityUtils.getSubject().getPrincipal()).getUsername();
sysLog.setUsername(username);
sysLog.setTime(time);
sysLog.setCreateDate(new Date());
//保存系统日志
sysLogService.save(sysLog);
}
}

View File

@@ -0,0 +1,61 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.exception;
/**
* 自定义异常
*
* @author Mark sunlightcs@gmail.com
*/
public class RRException extends RuntimeException {
private static final long serialVersionUID = 1L;
private String msg;
private int code = 500;
public RRException(String msg) {
super(msg);
this.msg = msg;
}
public RRException(String msg, Throwable e) {
super(msg, e);
this.msg = msg;
}
public RRException(String msg, int code) {
super(msg);
this.msg = msg;
this.code = code;
}
public RRException(String msg, int code, Throwable e) {
super(msg, e);
this.msg = msg;
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}

View File

@@ -0,0 +1,64 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.exception;
import com.peanut.common.utils.R;
import org.apache.shiro.authz.AuthorizationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
/**
* 异常处理器
*
* @author Mark sunlightcs@gmail.com
*/
@RestControllerAdvice
public class RRExceptionHandler {
private Logger logger = LoggerFactory.getLogger(getClass());
/**
* 处理自定义异常
*/
@ExceptionHandler(RRException.class)
public R handleRRException(RRException e){
R r = new R();
r.put("code", e.getCode());
r.put("msg", e.getMessage());
return r;
}
@ExceptionHandler(NoHandlerFoundException.class)
public R handlerNoFoundException(Exception e) {
logger.error(e.getMessage(), e);
return R.error(404, "路径不存在,请检查路径是否正确");
}
@ExceptionHandler(DuplicateKeyException.class)
public R handleDuplicateKeyException(DuplicateKeyException e){
logger.error(e.getMessage(), e);
return R.error("数据库中已存在该记录");
}
@ExceptionHandler(AuthorizationException.class)
public R handleAuthorizationException(AuthorizationException e){
logger.error(e.getMessage(), e);
return R.error("没有权限,请联系管理员授权");
}
@ExceptionHandler(Exception.class)
public R handleException(Exception e){
logger.error(e.getMessage(), e);
return R.error();
}
}

View File

@@ -0,0 +1,71 @@
package com.peanut.common.utils;
import java.io.File;
import java.io.FileOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.UUID;
public class BaiduVoicesUtils {
// 填写申请百度语音申请的appkey 申请地址百度AI开放平台
private final static String appKey = "aKDun6vXyqPLhWMdoIsv87Ez";
// private final static String appKey = "eaPPX40oIazH8R4oWsD9U4IT";
// 填写申请百度语音申请的APP SECRET
private final static String secretKey = "ew9dMb4yGmwF1g4qutxNvogzjd9eP5tb";
// private final static String secretKey = "DTN0ioQywwM23IoT2ZzEBmvfBe63ATEY";
// text 的内容为"欢迎使用百度语音合成"的urlencode,utf-8 编码
private final String text = "百度百科是百度公司推出的一部内容开放、自由的网络百科全书。";
// 发音人选择, 0为普通女声1为普通男生3为情感合成-度逍遥4为情感合成-度丫丫,默认为普通女声
private final static int per = 3;
// 语速取值0-9默认为5中语速
private final static int spd = 5;
// 音调取值0-9默认为5中语调
private final static int pit = 5;
// 音量取值0-9默认为5中音量
private final static int vol = 5;
// 调用地址
public final static String url = "http://tsn.baidu.com/text2audio";
// 用户唯一标识,用来区分用户,填写机器 MAC 地址或 IMEI 码长度为60以内
private static String cuid = "0322java";
public static String run(String content) throws Exception {
TokenHolder holder = new TokenHolder(appKey, secretKey, TokenHolder.ASR_SCOPE);
holder.resfresh();
String token = holder.getToken();
// for (String a:list) {
String url2 = url + "?tex=" + ConnUtil.urlEncode(content);
url2 += "&per=" + per;
url2 += "&spd=" + spd;
url2 += "&pit=" + pit;
url2 += "&vol=" + vol;
url2 += "&cuid=" + cuid;
url2 += "&tok=" + token;
url2 += "&lan=zh&ctp=1";
HttpURLConnection conn = (HttpURLConnection) new URL(url2).openConnection();
conn.setConnectTimeout(5000);
String contentType = conn.getContentType();
if (contentType.contains("mp3")) {
byte[] bytes = ConnUtil.getResponseBytes(conn);
// 存在项目根目录下,去文件夹点击可以播放
String substring = UUID.randomUUID().toString().substring(0, 6);
File file = new File(substring+".mp3");
FileOutputStream os = new FileOutputStream(file);
os.write(bytes);
os.close();
System.out.println("mp3 file write to " + file.getAbsolutePath());
return file.getAbsolutePath();
} else {
System.err.println("ERROR: content-type= " + contentType);
String res = ConnUtil.getResponseString(conn);
System.err.println(res);
return res;
}
// }
}
}

View File

@@ -0,0 +1,21 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.utils;
/**
* 系统参数相关Key
*
* @author Mark sunlightcs@gmail.com
*/
public class ConfigConstant {
/**
* 云存储配置KEY
*/
public final static String CLOUD_STORAGE_CONFIG_KEY = "CLOUD_STORAGE_CONFIG_KEY";
}

View File

@@ -0,0 +1,92 @@
package com.peanut.common.utils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URLEncoder;
public class ConnUtil {
/**
* UrlEncode UTF-8 编码
*
* @param str
* 原始字符串
* @return
*/
public static String urlEncode(String str) {
String result = null;
try {
result = URLEncoder.encode(str, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
/**
* 从HttpURLConnection 获取返回的字符串
*
* @param conn
* @return
* @throws IOException
* @throws DemoException
*/
public static String getResponseString(HttpURLConnection conn) throws IOException, DemoException {
return new String(getResponseBytes(conn));
}
/**
* 从HttpURLConnection 获取返回的bytes 注意 HttpURLConnection自身问题
* 400类错误会直接抛出异常。不能获取conn.getInputStream();
*
* @param conn
* @return
* @throws IOException
* http请求错误
* @throws DemoException
* http 的状态码不是 200
*/
public static byte[] getResponseBytes(HttpURLConnection conn) throws IOException, DemoException {
int responseCode = conn.getResponseCode();
if (responseCode != 200) {
System.err.println("http 请求返回的状态码错误期望200 当前是 " + responseCode);
if (responseCode == 401) {
System.err.println("可能是appkey appSecret 填错");
}
throw new DemoException("http response code is" + responseCode);
}
InputStream inputStream = conn.getInputStream();
byte[] result = getInputStreamContent(inputStream);
return result;
}
/**
* 将InputStream内的内容全部读取作为bytes返回
*
* @param is
* @return
* @throws IOException
* @see InputStream.read()
*/
public static byte[] getInputStreamContent(InputStream is) throws IOException {
byte[] b = new byte[1024];
// 定义一个输出流存储接收到的数据
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
// 开始接收数据
int len = 0;
while (true) {
len = is.read(b);
if (len == -1) {
// 数据读完
break;
}
byteArrayOutputStream.write(b, 0, len);
}
return byteArrayOutputStream.toByteArray();
}
}

View File

@@ -0,0 +1,152 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
* <p>
* https://www.renren.io
* <p>
* 版权所有,侵权必究!
*/
package com.peanut.common.utils;
import com.peanut.common.validator.group.AliyunGroup;
import com.peanut.common.validator.group.QcloudGroup;
import com.peanut.common.validator.group.QiniuGroup;
import java.util.Optional;
import java.util.stream.Stream;
/**
* 常量
*
* @author Mark sunlightcs@gmail.com
*/
public class Constant {
/**
* 超级管理员ID
*/
public static final int SUPER_ADMIN = 1;
/**
* 当前页码
*/
public static final String PAGE = "page";
/**
* 每页显示记录数
*/
public static final String LIMIT = "limit";
/**
* 排序字段
*/
public static final String ORDER_FIELD = "sidx";
/**
* 排序方式
*/
public static final String ORDER = "order";
/**
* 升序
*/
public static final String ASC = "asc";
/**
* 菜单类型
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2016年11月15日 下午1:24:29
*/
public enum MenuType {
/**
* 目录
*/
CATALOG(0),
/**
* 菜单
*/
MENU(1),
/**
* 按钮
*/
BUTTON(2);
private int value;
MenuType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
/**
* 定时任务状态
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2016年12月3日 上午12:07:22
*/
public enum ScheduleStatus {
/**
* 正常
*/
NORMAL(0),
/**
* 暂停
*/
PAUSE(1);
private int value;
ScheduleStatus(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
/**
* 云服务商
*/
public enum CloudService {
/**
* 七牛云
*/
QINIU(1, QiniuGroup.class),
/**
* 阿里云
*/
ALIYUN(2, AliyunGroup.class),
/**
* 腾讯云
*/
QCLOUD(3, QcloudGroup.class);
private int value;
private Class<?> validatorGroupClass;
CloudService(int value, Class<?> validatorGroupClass) {
this.value = value;
this.validatorGroupClass = validatorGroupClass;
}
public int getValue() {
return value;
}
public Class<?> getValidatorGroupClass() {
return this.validatorGroupClass;
}
public static CloudService getByValue(Integer value) {
Optional<CloudService> first = Stream.of(CloudService.values()).filter(cs -> value.equals(cs.value)).findFirst();
if (!first.isPresent()) {
throw new IllegalArgumentException("非法的枚举值:" + value);
}
return first.get();
}
}
}

View File

@@ -0,0 +1,31 @@
package com.peanut.common.utils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Component
@PropertySource("classpath:application.properties") //变量名需要与配置文件相匹配
public class ConstantPropertiesUtil implements InitializingBean {
@Value("${wx.open.app_id}")
private String appId;
@Value("${wx.open.app_secret}")
private String appSecret;
@Value("${wx.open.redirect_url}")
private String redirectUrl;
public static String WX_OPEN_APP_ID;
public static String WX_OPEN_APP_SECRET;
public static String WX_OPEN_REDIRECT_URL;
@Override
public void afterPropertiesSet() throws Exception {
WX_OPEN_APP_ID = appId;
WX_OPEN_APP_SECRET = appSecret;
WX_OPEN_REDIRECT_URL = redirectUrl;
}
}

View File

@@ -0,0 +1,37 @@
package com.peanut.common.utils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//当项目已启动spring接口spring加载之后执行接口一个方法
@Component
public class ConstantPropertiesUtils implements InitializingBean {
//读取配置文件内容
@Value("${aliyun.oss.file.endpoint}")
private String endpoint;
@Value("${aliyun.oss.file.keyid}")
private String keyId;
@Value("${aliyun.oss.file.keysecret}")
private String keySecret;
@Value("${aliyun.oss.file.bucketname}")
private String bucketName;
//定义公开静态常量
public static String END_POIND;
public static String ACCESS_KEY_ID;
public static String ACCESS_KEY_SECRET;
public static String BUCKET_NAME;
@Override
public void afterPropertiesSet() throws Exception {
END_POIND = endpoint;
ACCESS_KEY_ID = keyId;
ACCESS_KEY_SECRET = keySecret;
BUCKET_NAME = bucketName;
}
}

View File

@@ -0,0 +1,27 @@
package com.peanut.common.utils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import java.util.HashSet;
import java.util.Set;
public class CopyUtils {
public static String[] getNullPropertyNames (Object source) {
final BeanWrapper src = new BeanWrapperImpl(source);
java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();
Set<String> emptyNames = new HashSet<String>();
for(java.beans.PropertyDescriptor pd : pds) {
Object srcValue = src.getPropertyValue(pd.getName());
if (srcValue == null) emptyNames.add(pd.getName());
}
String[] result = new String[emptyNames.size()];
return emptyNames.toArray(result);
}
public static void copyProperties(Object src, Object target) {
BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
}
}

View File

@@ -0,0 +1,37 @@
package com.peanut.common.utils;
import java.util.Calendar;
import java.util.Date;
public class DateUtil {
/**
* 判断当前时间是否在[startTime, endTime]区间,注意时间格式要一致
*
* @param nowTime 当前时间
* @param startTime 开始时间
* @param endTime 结束时间
* @return
* @author jqlin
*/
public static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) {
if (nowTime.getTime() == startTime.getTime()
|| nowTime.getTime() == endTime.getTime()) {
return true;
}
Calendar date = Calendar.getInstance();
date.setTime(nowTime);
Calendar begin = Calendar.getInstance();
begin.setTime(startTime);
Calendar end = Calendar.getInstance();
end.setTime(endTime);
if (date.after(begin) && date.before(end)) {
return true;
} else {
return false;
}
}
}

View File

@@ -0,0 +1,166 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.utils;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 日期处理
*
* @author Mark sunlightcs@gmail.com
*/
public class DateUtils {
/** 时间格式(yyyy-MM-dd) */
public final static String DATE_PATTERN = "yyyy-MM-dd";
/** 时间格式(yyyy-MM-dd HH:mm:ss) */
public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
/**
* 日期格式化 日期格式为yyyy-MM-dd
* @param date 日期
* @return 返回yyyy-MM-dd格式日期
*/
public static String format(Date date) {
return format(date, DATE_PATTERN);
}
/**
* 日期格式化 日期格式为yyyy-MM-dd
* @param date 日期
* @param pattern 格式DateUtils.DATE_TIME_PATTERN
* @return 返回yyyy-MM-dd格式日期
*/
public static String format(Date date, String pattern) {
if(date != null){
SimpleDateFormat df = new SimpleDateFormat(pattern);
return df.format(date);
}
return null;
}
/**
* 字符串转换成日期
* @param strDate 日期字符串
* @param pattern 日期的格式DateUtils.DATE_TIME_PATTERN
*/
public static Date stringToDate(String strDate, String pattern) {
if (StringUtils.isBlank(strDate)){
return null;
}
DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
return fmt.parseLocalDateTime(strDate).toDate();
}
/**
* 根据周数,获取开始日期、结束日期
* @param week 周期 0本周-1上周-2上上周1下周2下下周
* @return 返回date[0]开始日期、date[1]结束日期
*/
public static Date[] getWeekStartAndEnd(int week) {
DateTime dateTime = new DateTime();
LocalDate date = new LocalDate(dateTime.plusWeeks(week));
date = date.dayOfWeek().withMinimumValue();
Date beginDate = date.toDate();
Date endDate = date.plusDays(6).toDate();
return new Date[]{beginDate, endDate};
}
/**
* 对日期的【秒】进行加/减
*
* @param date 日期
* @param seconds 秒数,负数为减
* @return 加/减几秒后的日期
*/
public static Date addDateSeconds(Date date, int seconds) {
DateTime dateTime = new DateTime(date);
return dateTime.plusSeconds(seconds).toDate();
}
/**
* 对日期的【分钟】进行加/减
*
* @param date 日期
* @param minutes 分钟数,负数为减
* @return 加/减几分钟后的日期
*/
public static Date addDateMinutes(Date date, int minutes) {
DateTime dateTime = new DateTime(date);
return dateTime.plusMinutes(minutes).toDate();
}
/**
* 对日期的【小时】进行加/减
*
* @param date 日期
* @param hours 小时数,负数为减
* @return 加/减几小时后的日期
*/
public static Date addDateHours(Date date, int hours) {
DateTime dateTime = new DateTime(date);
return dateTime.plusHours(hours).toDate();
}
/**
* 对日期的【天】进行加/减
*
* @param date 日期
* @param days 天数,负数为减
* @return 加/减几天后的日期
*/
public static Date addDateDays(Date date, int days) {
DateTime dateTime = new DateTime(date);
return dateTime.plusDays(days).toDate();
}
/**
* 对日期的【周】进行加/减
*
* @param date 日期
* @param weeks 周数,负数为减
* @return 加/减几周后的日期
*/
public static Date addDateWeeks(Date date, int weeks) {
DateTime dateTime = new DateTime(date);
return dateTime.plusWeeks(weeks).toDate();
}
/**
* 对日期的【月】进行加/减
*
* @param date 日期
* @param months 月数,负数为减
* @return 加/减几月后的日期
*/
public static Date addDateMonths(Date date, int months) {
DateTime dateTime = new DateTime(date);
return dateTime.plusMonths(months).toDate();
}
/**
* 对日期的【年】进行加/减
*
* @param date 日期
* @param years 年数,负数为减
* @return 加/减几年后的日期
*/
public static Date addDateYears(Date date, int years) {
DateTime dateTime = new DateTime(date);
return dateTime.plusYears(years).toDate();
}
}

View File

@@ -0,0 +1,8 @@
package com.peanut.common.utils;
public class DemoException extends Exception {
public DemoException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,71 @@
package com.peanut.common.utils;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class FileDownloadUtil {
/**
* @return
* @description: 从服务器获得一个输入流
*/
public static InputStream getInputStream(String urlPath) {
InputStream inputStream = null;
HttpURLConnection httpURLConnection = null;
try {
URL url = new URL(urlPath);
httpURLConnection = (HttpURLConnection) url.openConnection();
// 设置网络连接超时时间
httpURLConnection.setConnectTimeout(3000);
// 设置应用程序要从网络连接读取数据
httpURLConnection.setDoInput(true);
httpURLConnection.setRequestMethod("GET");
int responseCode = httpURLConnection.getResponseCode();
System.out.println("responseCode is:" + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
// 从服务器返回一个输入流
inputStream = httpURLConnection.getInputStream();
} else {
inputStream = httpURLConnection.getErrorStream();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return inputStream;
}
/**
* @param resp
* @param inputStream
* @description: 将输入流输出到页面
*/
public static void writeFile(HttpServletResponse resp, InputStream inputStream) {
OutputStream out = null;
try {
out = resp.getOutputStream();
int len = 0;
byte[] b = new byte[1024];
while ((len = inputStream.read(b)) != -1) {
out.write(b, 0, len);
}
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,449 @@
package com.peanut.common.utils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.config.RequestConfig.Builder;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class HttpClientUtils {
public static final int connTimeout=10000;
public static final int readTimeout=10000;
public static final String charset="UTF-8";
private static HttpClient client = null;
private static final Logger log = LoggerFactory.getLogger(HttpClientUtils.class);
static {
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(128);
cm.setDefaultMaxPerRoute(128);
client = HttpClients.custom().setConnectionManager(cm).build();
}
public static String postParameters(String url, String parameterStr) throws ConnectTimeoutException, SocketTimeoutException, Exception{
return post(url,parameterStr,"application/x-www-form-urlencoded",charset,connTimeout,readTimeout);
}
public static String postParameters(String url, String parameterStr,String charset, Integer connTimeout, Integer readTimeout) throws ConnectTimeoutException, SocketTimeoutException, Exception{
return post(url,parameterStr,"application/x-www-form-urlencoded",charset,connTimeout,readTimeout);
}
public static String postParameters(String url, Map<String, Object> params) throws ConnectTimeoutException,
SocketTimeoutException, Exception {
return postForm(url, params, null, connTimeout, readTimeout);
}
public static String postParameters(String url, Map<String, Object> params, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,
SocketTimeoutException, Exception {
return postForm(url, params, null, connTimeout, readTimeout);
}
public static String get(String url) throws Exception {
return get(url, charset, null, null);
}
public static String get(String url, String charset) throws Exception {
return get(url, charset, connTimeout, readTimeout);
}
/**
* 发送一个 Post 请求, 使用指定的字符集编码.
*
* @param url
* @param body RequestBody
* @param mimeType 例如 application/xml "application/x-www-form-urlencoded" a=1&b=2&c=3
* @param charset 编码
* @param connTimeout 建立链接超时时间,毫秒.
* @param readTimeout 响应超时时间,毫秒.
* @return ResponseBody, 使用指定的字符集编码.
* @throws ConnectTimeoutException 建立链接超时异常
* @throws SocketTimeoutException 响应超时
* @throws Exception
*/
public static String post(String url, String body, String mimeType,String charset, Integer connTimeout, Integer readTimeout)
throws ConnectTimeoutException, SocketTimeoutException, Exception {
HttpClient client = null;
HttpPost post = new HttpPost(url);
String result = "";
try {
if (StringUtils.isNotBlank(body)) {
HttpEntity entity = new StringEntity(body, ContentType.create(mimeType, charset));
post.setEntity(entity);
}
// 设置参数
Builder customReqConf = RequestConfig.custom();
if (connTimeout != null) {
customReqConf.setConnectTimeout(connTimeout);
}
if (readTimeout != null) {
customReqConf.setSocketTimeout(readTimeout);
}
post.setConfig(customReqConf.build());
HttpResponse res;
if (url.startsWith("https")) {
// 执行 Https 请求.
client = createSSLInsecureClient();
res = client.execute(post);
} else {
// 执行 Http 请求.
client = HttpClientUtils.client;
res = client.execute(post);
}
result = IOUtils.toString(res.getEntity().getContent(), charset);
} finally {
post.releaseConnection();
if (url.startsWith("https") && client != null&& client instanceof CloseableHttpClient) {
((CloseableHttpClient) client).close();
}
}
return result;
}
/**
* 提交form表单
*
* @param url
* @param params
* @param connTimeout
* @param readTimeout
* @return
* @throws ConnectTimeoutException
* @throws SocketTimeoutException
* @throws Exception
*/
public static String postForm(String url, Map<String, Object> params, Map<String, String> headers, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,
SocketTimeoutException, Exception {
HttpClient client = null;
HttpPost post = new HttpPost(url);
try {
if (params != null && !params.isEmpty()) {
List<NameValuePair> formParams = new ArrayList<NameValuePair>();
Set<Entry<String, Object>> entrySet = params.entrySet();
for (Entry<String, Object> entry : entrySet) {
formParams.add(new BasicNameValuePair(entry.getKey(), entry.toString()));
}
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, Consts.UTF_8);
post.setEntity(entity);
}
if (headers != null && !headers.isEmpty()) {
for (Entry<String, String> entry : headers.entrySet()) {
post.addHeader(entry.getKey(), entry.getValue());
}
}
// 设置参数
Builder customReqConf = RequestConfig.custom();
if (connTimeout != null) {
customReqConf.setConnectTimeout(connTimeout);
}
if (readTimeout != null) {
customReqConf.setSocketTimeout(readTimeout);
}
post.setConfig(customReqConf.build());
HttpResponse res = null;
if (url.startsWith("https")) {
// 执行 Https 请求.
client = createSSLInsecureClient();
res = client.execute(post);
} else {
// 执行 Http 请求.
client = HttpClientUtils.client;
res = client.execute(post);
}
return IOUtils.toString(res.getEntity().getContent(), "UTF-8");
} finally {
post.releaseConnection();
if (url.startsWith("https") && client != null
&& client instanceof CloseableHttpClient) {
((CloseableHttpClient) client).close();
}
}
}
/**
* 发送一个 GET 请求
*/
public static String get(String url, String charset, Integer connTimeout,Integer readTimeout)
throws ConnectTimeoutException,SocketTimeoutException, Exception {
HttpClient client = null;
HttpGet get = new HttpGet(url);
String result = "";
try {
// 设置参数
Builder customReqConf = RequestConfig.custom();
if (connTimeout != null) {
customReqConf.setConnectTimeout(connTimeout);
}
if (readTimeout != null) {
customReqConf.setSocketTimeout(readTimeout);
}
get.setConfig(customReqConf.build());
HttpResponse res = null;
if (url.startsWith("https")) {
// 执行 Https 请求.
client = createSSLInsecureClient();
res = client.execute(get);
} else {
// 执行 Http 请求.
client = HttpClientUtils.client;
res = client.execute(get);
}
result = IOUtils.toString(res.getEntity().getContent(), charset);
} finally {
get.releaseConnection();
if (url.startsWith("https") && client != null && client instanceof CloseableHttpClient) {
((CloseableHttpClient) client).close();
}
}
return result;
}
/**
* 从 response 里获取 charset
*/
@SuppressWarnings("unused")
private static String getCharsetFromResponse(HttpResponse ressponse) {
// Content-Type:text/html; charset=GBK
if (ressponse.getEntity() != null && ressponse.getEntity().getContentType() != null && ressponse.getEntity().getContentType().getValue() != null) {
String contentType = ressponse.getEntity().getContentType().getValue();
if (contentType.contains("charset=")) {
return contentType.substring(contentType.indexOf("charset=") + 8);
}
}
return null;
}
/**
* 创建 SSL连接
* @return
* @throws GeneralSecurityException
*/
private static CloseableHttpClient createSSLInsecureClient() throws GeneralSecurityException {
try {
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
public boolean isTrusted(X509Certificate[] chain,String authType) throws CertificateException {
return true;
}
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
@Override
public void verify(String host, SSLSocket ssl)
throws IOException {
}
@Override
public void verify(String host, X509Certificate cert)
throws SSLException {
}
@Override
public void verify(String host, String[] cns,
String[] subjectAlts) throws SSLException {
}
});
return HttpClients.custom().setSSLSocketFactory(sslsf).build();
} catch (GeneralSecurityException e) {
throw e;
}
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param)
{
PrintWriter out = null;
BufferedReader in = null;
StringBuilder result = new StringBuilder();
try
{
log.info("sendPost - {}", url);
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setDoOutput(true);
conn.setDoInput(true);
out = new PrintWriter(conn.getOutputStream());
out.print(param);
out.flush();
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
String line;
while ((line = in.readLine()) != null)
{
result.append(line);
}
log.info("recv - {}", result);
}
catch (ConnectException e)
{
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
}
catch (SocketTimeoutException e)
{
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
}
catch (IOException e)
{
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
}
catch (Exception e)
{
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
}
finally
{
try
{
if (out != null)
{
out.close();
}
if (in != null)
{
in.close();
}
}
catch (IOException ex)
{
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
}
}
return result.toString();
}
/**
* 快递鸟向指定 URL 发送POST方法的请求
* url 发送请求的 URL
* params 请求的参数集合
* @return 远程资源的响应结果
*/
public static String kdSendPost(String url, Map<String, String> params) {
OutputStreamWriter out = null;
BufferedReader in = null;
StringBuilder result = new StringBuilder();
try {
URL realUrl = new URL(url);
HttpURLConnection conn =(HttpURLConnection) realUrl.openConnection();
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// POST方法
conn.setRequestMethod("POST");
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.connect();
// 获取URLConnection对象对应的输出流
out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
// 发送请求参数
if (params != null) {
StringBuilder param = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
if(param.length()>0){
param.append("&");
}
param.append(entry.getKey());
param.append("=");
param.append(entry.getValue());
log.info(entry.getKey()+":"+entry.getValue());
}
log.info("param:"+param.toString());
out.write(param.toString());
}
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
result.append(line);
}
} catch (Exception e) {
e.printStackTrace();
}
//使用finally块来关闭输出流、输入流
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result.toString();
}
}

View File

@@ -0,0 +1,32 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.utils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
public class HttpContextUtils {
public static HttpServletRequest getHttpServletRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
public static String getDomain(){
HttpServletRequest request = getHttpServletRequest();
StringBuffer url = request.getRequestURL();
return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();
}
public static String getOrigin(){
HttpServletRequest request = getHttpServletRequest();
return request.getHeader("Origin");
}
}

View File

@@ -0,0 +1,64 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.utils;
import com.alibaba.druid.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
/**
* IP地址
*
* @author Mark sunlightcs@gmail.com
*/
public class IPUtils {
private static Logger logger = LoggerFactory.getLogger(IPUtils.class);
/**
* 获取IP地址
*
* 使用Nginx等反向代理软件 则不能通过request.getRemoteAddr()获取IP地址
* 如果使用了多级反向代理的话X-Forwarded-For的值并不止一个而是一串IP地址X-Forwarded-For中第一个非unknown的有效IP字符串则为真实IP地址
*/
public static String getIpAddr(HttpServletRequest request) {
String ip = null;
try {
ip = request.getHeader("x-forwarded-for");
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
} catch (Exception e) {
logger.error("IPUtils ERROR ", e);
}
// //使用代理则获取第一个IP地址
// if(StringUtils.isEmpty(ip) && ip.length() > 15) {
// if(ip.indexOf(",") > 0) {
// ip = ip.substring(0, ip.indexOf(","));
// }
// }
return ip;
}
}

View File

@@ -0,0 +1,67 @@
package com.peanut.common.utils;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
public class KdUtils {
/**
* MD5加密
* str 内容
* charset 编码方式
* @throws Exception
*/
public static String MD5(String str, String charset) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes(charset));
byte[] result = md.digest();
StringBuffer sb = new StringBuffer(32);
for (int i = 0; i < result.length; i++) {
int val = result[i] & 0xff;
if (val <= 0xf) {
sb.append("0");
}
sb.append(Integer.toHexString(val));
}
return sb.toString().toLowerCase();
}
/**
* base64编码
* str 内容
* charset 编码方式
* @throws UnsupportedEncodingException
*/
public static String base64(String str, String charset) throws UnsupportedEncodingException{
String encoded = Base64.encode(str.getBytes(charset));
return encoded;
}
public static String urlEncoder(String str, String charset) throws UnsupportedEncodingException{
String result = URLEncoder.encode(str, charset);
return result;
}
/**
* 电商Sign签名生成
* content 内容
* keyValue ApiKey
* charset 编码方式
* @throws UnsupportedEncodingException ,Exception
* @return DataSign签名
*/
public static String encrypt (String content, String keyValue, String charset) throws UnsupportedEncodingException, Exception
{
if (keyValue != null)
{
return base64(MD5(content + keyValue, charset), charset);
}
return base64(MD5(content, charset), charset);
}
}

View File

@@ -0,0 +1,45 @@
package com.peanut.common.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Util {
private static MessageDigest mdigest = null;
private static char digits[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
private static MessageDigest getMdInst(){
if(null == mdigest){
try{
mdigest = MessageDigest.getInstance("MD5");
}catch(NoSuchAlgorithmException e){
e.printStackTrace();
}
}
return mdigest;
}
public static String encode(String s){
if(null == s){
return "";
}
try{
byte[] bytes = s.getBytes();
getMdInst().update(bytes);
byte[] md = getMdInst().digest();
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for(int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = digits[byte0 >>> 4 & 0xf];
str[k++] = digits[byte0 & 0xf];
}
return new String(str);
}catch(Exception e){
e.printStackTrace();
return null;
}
}
}

View File

@@ -0,0 +1,255 @@
package com.peanut.common.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import org.apache.commons.codec.binary.Hex;
/**
* @author hh@163.com:
* @version 创建时间2018-3-20 下午2:40:13
* @introduction
*/
public class MD5Utils {
/**
* 普通MD5加密 01
* <p>
*
* @Title : getStrMD5
* </p>
* <p>
* @Description : TODO
* </p>
* <p>
* @Author : HuaZai
* </p>
* <p>
* @Date : 2017年12月26日 下午2:49:44
* </p>
*/
public static String getStrMD5(String inStr) {
// 获取MD5实例
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
System.out.println(e.toString());
return "";
}
// 将加密字符串转换为字符数组
char[] charArray = inStr.toCharArray();
byte[] byteArray = new byte[charArray.length];
// 开始加密
for (int i = 0; i < charArray.length; i++)
byteArray[i] = (byte) charArray[i];
byte[] digest = md5.digest(byteArray);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < digest.length; i++) {
int var = digest[i] & 0xff;
if (var < 16)
sb.append("0");
sb.append(Integer.toHexString(var));
}
return sb.toString();
}
/**
* 普通MD5加密 02
* <p>
*
* @Title : getStrrMD5
* </p>
* <p>
* @Description : TODO
* </p>
* <p>
* @Author : HuaZai
* </p>
* <p>
* @Date : 2017年12月27日 上午11:18:39
* </p>
*/
public static String getStrrMD5(String password) {
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
try {
byte strTemp[] = password.getBytes("UTF-8");
MessageDigest mdTemp = MessageDigest.getInstance("MD5");
mdTemp.update(strTemp);
byte md[] = mdTemp.digest();
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 15];
str[k++] = hexDigits[byte0 & 15];
}
return new String(str);
} catch (Exception e) {
return null;
}
}
/**
* MD5双重解密
* <p>
*
* @Title : getconvertMD5
* </p>
* <p>
* @Description : TODO
* </p>
* <p>
* @Author : HuaZai
* </p>
* <p>
* @Date : 2017年12月26日 下午3:34:17
* </p>
*/
public static String getconvertMD5(String inStr) {
char[] charArray = inStr.toCharArray();
for (int i = 0; i < charArray.length; i++) {
charArray[i] = (char) (charArray[i] ^ 't');
}
String str = String.valueOf(charArray);
return str;
}
/**
* 使用Apache的Hex类实现Hex(16进制字符串和)和字节数组的互转
* <p>
*
* @Title : md5Hex
* </p>
* <p>
* @Description : TODO
* </p>
* <p>
* @Author : HuaZai
* </p>
* <p>
* @Date : 2017年12月27日 上午11:28:25
* </p>
*/
@SuppressWarnings("unused")
private static String md5Hex(String str) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(str.getBytes());
return new String(new Hex().encode(digest));
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.toString());
return "";
}
}
/**
* 加盐MD5加密
* <p>
*
* @Title : getSaltMD5
* </p>
* <p>
* @Description : TODO
* </p>
* <p>
* @Author : HuaZai
* </p>
* <p>
* @Date : 2017年12月27日 上午11:21:00
* </p>
*/
public static String getSaltMD5(String password) {
// 生成一个16位的随机数
Random random = new Random();
StringBuilder sBuilder = new StringBuilder(16);
sBuilder.append(random.nextInt(99999999)).append(random.nextInt(99999999));
int len = sBuilder.length();
if (len < 16) {
for (int i = 0; i < 16 - len; i++) {
sBuilder.append("0");
}
}
// 生成最终的加密盐
String Salt = sBuilder.toString();
password = md5Hex(password + Salt);
char[] cs = new char[48];
for (int i = 0; i < 48; i += 3) {
cs[i] = password.charAt(i / 3 * 2);
char c = Salt.charAt(i / 3);
cs[i + 1] = c;
cs[i + 2] = password.charAt(i / 3 * 2 + 1);
}
return String.valueOf(cs);
}
/**
* 验证加盐后是否和原文一致
* <p>
*
* @Title : verifyMD5
* </p>
* <p>
* @Description : TODO
* </p>
* <p>
* @Author : HuaZai
* </p>
* <p>
* @Date : 2017年12月27日 下午2:22:22
* </p>
*/
public static boolean getSaltverifyMD5(String password, String md5str) {
char[] cs1 = new char[32];
char[] cs2 = new char[16];
for (int i = 0; i < 48; i += 3) {
cs1[i / 3 * 2] = md5str.charAt(i);
cs1[i / 3 * 2 + 1] = md5str.charAt(i + 2);
cs2[i / 3] = md5str.charAt(i + 1);
}
String Salt = new String(cs2);
return md5Hex(password + Salt).equals(String.valueOf(cs1));
}
public static void main(String[] args) {
MD5Utils md = new MD5Utils();
String strMD5 = new String("12345");
System.out.println("原始:" + strMD5);
System.out.println("东东的:" + md.getStrrMD5(strMD5));
System.out.println("MD5后" + md.getStrMD5(strMD5));
System.out.println("加密的:" + md.getconvertMD5(strMD5));
System.out.println("解密的:" + md.getconvertMD5(md.getconvertMD5(strMD5)));
System.out.println("\t\t=======================================");
// 原文
String plaintext = "huazai";
// plaintext = "123456";
System.out.println("原始:" + plaintext);
System.out.println("普通MD5后" + MD5Utils.getStrMD5(plaintext));
// 获取加盐后的MD5值
String ciphertext = MD5Utils.getSaltMD5(plaintext);
System.out.println("加盐后MD5" + ciphertext);
System.out.println("是否是同一字符串:" + MD5Utils.getSaltverifyMD5(plaintext, ciphertext));
/**
* 其中某次DingSai字符串的MD5值
*/
String[] tempSalt = { "810e1ee9ee5e28188658f431451a29c2d81048de6a108e8a",
"66db82d9da2e35c95416471a147d12e46925d38e1185c043",
"61a718e4c15d914504a41d95230087a51816632183732b5a" };
for (String temp : tempSalt) {
System.out.println("是否是同一字符串:" + MD5Utils.getSaltverifyMD5(plaintext, temp));
}
}
}

View File

@@ -0,0 +1,26 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.utils;
import java.util.HashMap;
/**
* Map工具类
*
* @author Mark sunlightcs@gmail.com
*/
public class MapUtils extends HashMap<String, Object> {
@Override
public MapUtils put(String key, Object value) {
super.put(key, value);
return this;
}
}

View File

@@ -0,0 +1,24 @@
package com.peanut.common.utils;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime", new Date(), metaObject);
this.setFieldValByName("updateTime", new Date(), metaObject);
this.setFieldValByName("successTime", new Date(), metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", new Date(), metaObject);
this.setFieldValByName("successTime", new Date(), metaObject);
this.setFieldValByName("payTime", new Date(), metaObject);
}
}

View File

@@ -0,0 +1,115 @@
package com.peanut.common.utils;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
/**
* * 订单编码生成器生成32位数字编码
* * @生成规则 1位单号类型+17位时间戳+14位(用户id加密&随机数)
*/
public class OrderUtils {
/**
* 订单类别头
*/
private static final String ORDER_CODE = "";
/**
* 退货类别头
*/
private static final String RETURN_ORDER = "";
/**
* 退款类别头
*/
private static final String REFUND_ORDER = "";
/**
* 随即编码
*/
private static final int[] r = new int[]{7, 9, 6, 2, 8, 1, 3, 0, 5, 4};
/**
* 用户id和随机数总长度
*/
private static final int maxLength = 14;
/**
* 根据id进行加密+加随机数组成固定长度编码
*/
private static String toCode(Integer userId) {
String idStr = userId.toString();
StringBuilder idsbs = new StringBuilder();
for (int i = idStr.length() - 1; i >= 0; i--) {
idsbs.append(r[idStr.charAt(i) - '0']);
}
return idsbs.append(getRandom(maxLength - idStr.length())).toString();
}
/**
* 生成时间戳
*/
private static String getDateTime() {
DateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
return sdf.format(new Date());
}
/**
* 生成固定长度随机码
*
* @param n 长度
*/
private static long getRandom(long n) {
long min = 1, max = 9;
for (int i = 1; i < n; i++) {
min *= 10;
max *= 10;
}
long rangeLong = (((long) (new Random().nextDouble() * (max - min)))) + min;
return rangeLong;
}
/**
* 生成不带类别标头的编码
*
* @param userId
*/
private static synchronized String getCode(Integer userId) {
userId = userId == null ? 10000 : userId;
return getDateTime() + toCode(userId);
}
/**
* 生成订单单号编码(调用方法)
* @param userId 网站中该用户唯一ID 防止重复
*/
public static String getOrderCode(Integer userId) {
return ORDER_CODE + getCode(userId);
}
/**
* 生成退货单号编码(调用方法)
* @param userId 网站中该用户唯一ID 防止重复
*/
public static String getReturnCode(Integer userId) {
return RETURN_ORDER + getCode(userId);
}
/**
* 生成退款单号编码(调用方法)
* @param userId 网站中该用户唯一ID 防止重复
*/
public static String getRefundCode(Integer userId) {
return REFUND_ORDER + getCode(userId);
}
}

View File

@@ -0,0 +1,110 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.utils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import java.io.Serializable;
import java.util.List;
/**
* 分页工具类
*
* @author Mark sunlightcs@gmail.com
*/
public class PageUtils implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 总记录数
*/
private int totalCount;
/**
* 每页记录数
*/
private int pageSize;
/**
* 总页数
*/
private int totalPage;
/**
* 当前页数
*/
private int currPage;
/**
* 列表数据
*/
private List<?> list;
/**
* 分页
* @param list 列表数据
* @param totalCount 总记录数
* @param pageSize 每页记录数
* @param currPage 当前页数
*/
public PageUtils(List<?> list, int totalCount, int pageSize, int currPage) {
this.list = list;
this.totalCount = totalCount;
this.pageSize = pageSize;
this.currPage = currPage;
this.totalPage = (int)Math.ceil((double)totalCount/pageSize);
}
/**
* 分页
*/
public PageUtils(IPage<?> page) {
this.list = page.getRecords();
this.totalCount = (int)page.getTotal();
this.pageSize = (int)page.getSize();
this.currPage = (int)page.getCurrent();
this.totalPage = (int)page.getPages();
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getCurrPage() {
return currPage;
}
public void setCurrPage(int currPage) {
this.currPage = currPage;
}
public List<?> getList() {
return list;
}
public void setList(List<?> list) {
this.list = list;
}
}

View File

@@ -0,0 +1,77 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.utils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.peanut.common.xss.SQLFilter;
import org.apache.commons.lang.StringUtils;
import java.util.Map;
/**
* 查询参数
*
* @author Mark sunlightcs@gmail.com
*/
public class Query<T> {
public IPage<T> getPage(Map<String, Object> params) {
return this.getPage(params, null, false);
}
public IPage<T> getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) {
//分页参数
long curPage = 1;
long limit = 10;
if(params.get(Constant.PAGE) != null){
curPage = Long.parseLong((String)params.get(Constant.PAGE));
}
if(params.get(Constant.LIMIT) != null){
limit = Long.parseLong((String)params.get(Constant.LIMIT));
}
//分页对象
Page<T> page = new Page<>(curPage, limit);
//分页参数
params.put(Constant.PAGE, page);
//排序字段
//防止SQL注入因为sidx、order是通过拼接SQL实现排序的会有SQL注入风险
String orderField = SQLFilter.sqlInject((String)params.get(Constant.ORDER_FIELD));
String order = (String)params.get(Constant.ORDER);
//前端字段排序
if(StringUtils.isNotEmpty(orderField) && StringUtils.isNotEmpty(order)){
if(Constant.ASC.equalsIgnoreCase(order)) {
return page.addOrder(OrderItem.asc(orderField));
}else {
return page.addOrder(OrderItem.desc(orderField));
}
}
//没有排序字段,则不排序
if(StringUtils.isBlank(defaultOrderField)){
return page;
}
//默认排序
if(isAsc) {
page.addOrder(OrderItem.asc(defaultOrderField));
}else {
page.addOrder(OrderItem.desc(defaultOrderField));
}
return page;
}
}

View File

@@ -0,0 +1,64 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.utils;
import org.apache.http.HttpStatus;
import java.util.HashMap;
import java.util.Map;
/**
* 返回数据
*
* @author Mark sunlightcs@gmail.com
*/
public class R extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
public R() {
put("code", 0);
put("msg", "success");
}
public static R error() {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
}
public static R error(String msg) {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
}
public static R error(int code, String msg) {
R r = new R();
r.put("code", code);
r.put("msg", msg);
return r;
}
public static R ok(String msg) {
R r = new R();
r.put("msg", msg);
return r;
}
public static R ok(Map<String, Object> map) {
R r = new R();
r.putAll(map);
return r;
}
public static R ok() {
return new R();
}
public R put(String key, Object value) {
super.put(key, value);
return this;
}
}

View File

@@ -0,0 +1,86 @@
package com.peanut.common.utils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.peanut.modules.book.entity.CityEntity;
import com.peanut.modules.book.entity.CountyEntity;
import com.peanut.modules.book.entity.ProvinceEntity;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class ReadProvinceUtil {
public static List<ProvinceEntity> getFile(String filePath) {
JSONArray proJsonArray = null;
JSONArray cityJsonArray = null;
JSONArray countyJsonArray = null;
JSONObject cityJson = null;
JSONObject countyJson = null;
Date date = new Date();
List<ProvinceEntity> provinceList = null;
List<CityEntity> cityList = null;
List<CountyEntity> countyList = null;
// String path = request.getSession().getServletContext().getRealPath("/");
// path = path + filePath;
File file = new File(filePath);
try {
String input = FileUtils.readFileToString(file, "UTF-8");// 读取文件
System.out.println(input);
//文件转换jsonObject格式
String s = input.replaceAll("\n", "");
JSONObject proJson = JSONObject.parseObject(s);
if (proJson != null) {
// 取出数据
proJsonArray = proJson.getJSONArray("china");
provinceList = new ArrayList<ProvinceEntity>();
if (proJsonArray != null) {
for (int i = 0; i < proJsonArray.size(); i++) {
ProvinceEntity province = new ProvinceEntity();
JSONObject temp = proJsonArray.getJSONObject(i);
province.setProvName(temp.getString("name"));
province.setCreateDate(date);
province.setRegionCode(temp.getString("code"));
cityJsonArray = JSONArray.parseArray(temp.getString("cityList"));
cityList = new ArrayList<CityEntity>();
if (cityJsonArray != null) {
for (int j = 0; j < cityJsonArray.size(); j++) {
CityEntity city = new CityEntity();
cityJson = cityJsonArray.getJSONObject(j);
city.setCityName(cityJson.getString("name"));
city.setRegionCode(cityJson.getString("code"));
city.setCreateDate(date);
countyJsonArray = JSONArray.parseArray(cityJson.getString("areaList"));
countyList = new ArrayList<CountyEntity>();
if (countyJsonArray != null) {
for (int k = 0; k < countyJsonArray.size(); k++) {
CountyEntity county = new CountyEntity();
countyJson = countyJsonArray.getJSONObject(k);
county.setCountyName(countyJson.getString("name"));
county.setRegionCode(countyJson.getString("code"));
county.setCreateDate(date);
countyList.add(county);
}
city.setCountyList(countyList);
cityList.add(city);
}
}
province.setCityList(cityList);
provinceList.add(province);
}
}
}
}
} catch (Exception e) {
e.getStackTrace();
}
return provinceList;
}
}

View File

@@ -0,0 +1,21 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.utils;
/**
* Redis所有Keys
*
* @author Mark sunlightcs@gmail.com
*/
public class RedisKeys {
public static String getSysConfigKey(String key){
return "sys:config:" + key;
}
}

View File

@@ -0,0 +1,99 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.utils;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* Redis工具类
*
* @author Mark sunlightcs@gmail.com
*/
@Component
public class RedisUtils {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private ValueOperations<String, String> valueOperations;
@Autowired
private HashOperations<String, String, Object> hashOperations;
@Autowired
private ListOperations<String, Object> listOperations;
@Autowired
private SetOperations<String, Object> setOperations;
@Autowired
private ZSetOperations<String, Object> zSetOperations;
/** 默认过期时长,单位:秒 */
public final static long DEFAULT_EXPIRE = 60 * 60 * 24;
/** 不设置过期时长 */
public final static long NOT_EXPIRE = -1;
private final static Gson gson = new Gson();
public void set(String key, Object value, long expire){
valueOperations.set(key, toJson(value));
if(expire != NOT_EXPIRE){
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
}
public void set(String key, Object value){
set(key, value, DEFAULT_EXPIRE);
}
public <T> T get(String key, Class<T> clazz, long expire) {
String value = valueOperations.get(key);
if(expire != NOT_EXPIRE){
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
return value == null ? null : fromJson(value, clazz);
}
public <T> T get(String key, Class<T> clazz) {
return get(key, clazz, NOT_EXPIRE);
}
public String get(String key, long expire) {
String value = valueOperations.get(key);
if(expire != NOT_EXPIRE){
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
return value;
}
public String get(String key) {
return get(key, NOT_EXPIRE);
}
public void delete(String key) {
redisTemplate.delete(key);
}
/**
* Object转成JSON数据
*/
private String toJson(Object object){
if(object instanceof Integer || object instanceof Long || object instanceof Float ||
object instanceof Double || object instanceof Boolean || object instanceof String){
return String.valueOf(object);
}
return gson.toJson(object);
}
/**
* JSON数据转成Object
*/
private <T> T fromJson(String json, Class<T> clazz){
return gson.fromJson(json, clazz);
}
}

View File

@@ -0,0 +1,61 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.utils;
import com.peanut.common.exception.RRException;
import com.peanut.modules.sys.entity.SysUserEntity;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
/**
* Shiro工具类
*
* @author Mark sunlightcs@gmail.com
*/
public class ShiroUtils {
public static Session getSession() {
return SecurityUtils.getSubject().getSession();
}
public static Subject getSubject() {
return SecurityUtils.getSubject();
}
public static SysUserEntity getUserEntity() {
return (SysUserEntity)SecurityUtils.getSubject().getPrincipal();
}
public static Long getUserId() {
return getUserEntity().getUserId();
}
public static void setSessionAttribute(Object key, Object value) {
getSession().setAttribute(key, value);
}
public static Object getSessionAttribute(Object key) {
return getSession().getAttribute(key);
}
public static boolean isLogin() {
return SecurityUtils.getSubject().getPrincipal() != null;
}
public static String getKaptcha(String key) {
Object kaptcha = getSessionAttribute(key);
if(kaptcha == null){
throw new RRException("验证码已失效");
}
getSession().removeAttribute(key);
return kaptcha.toString();
}
}

View File

@@ -0,0 +1,51 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.utils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* Spring Context 工具类
*
* @author Mark sunlightcs@gmail.com
*/
@Component
public class SpringContextUtils implements ApplicationContextAware {
public static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
SpringContextUtils.applicationContext = applicationContext;
}
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
public static <T> T getBean(String name, Class<T> requiredType) {
return applicationContext.getBean(name, requiredType);
}
public static boolean containsBean(String name) {
return applicationContext.containsBean(name);
}
public static boolean isSingleton(String name) {
return applicationContext.isSingleton(name);
}
public static Class<? extends Object> getType(String name) {
return applicationContext.getType(name);
}
}

View File

@@ -0,0 +1,122 @@
package com.peanut.common.utils;
import org.json.JSONObject;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
public class TokenHolder {
public static final String ASR_SCOPE = "audio_voice_assistant_get";
public static final String TTS_SCOPE = "audio_tts_post";
/**
* url , Token的urlhttp可以改为https
*/
private static final String url = "http://openapi.baidu.com/oauth/2.0/token";
/**
* asr的权限 scope 是 "audio_voice_assistant_get" tts 的权限 scope 是
* "audio_tts_post"
*/
private String scope;
/**
* 网页上申请语音识别应用获取的apiKey
*/
private String apiKey;
/**
* 网页上申请语音识别应用获取的secretKey
*/
private String secretKey;
/**
* 保存访问接口获取的token
*/
private String token;
/**
* 当前的时间戳,毫秒
*/
private long expiresAt;
/**
* @param apiKey
* 网页上申请语音识别应用获取的apiKey
* @param secretKey
* 网页上申请语音识别应用获取的secretKey
*/
public TokenHolder(String apiKey, String secretKey, String scope) {
this.apiKey = apiKey;
this.secretKey = secretKey;
this.scope = scope;
}
/**
* 获取tokenrefresh 方法后调用有效
*
* @return
*/
public String getToken() {
return token;
}
/**
* 获取过期时间refresh 方法后调用有效
*
* @return
*/
public long getExpiresAt() {
return expiresAt;
}
/**
* 获取token
*
* @return
* @throws IOException
* http请求错误
* @throws DemoException
* http接口返回不是 200, access_token未获取
*/
public void resfresh() throws Exception {
String getTokenURL = url + "?grant_type=client_credentials" + "&client_id=" + ConnUtil.urlEncode(apiKey)
+ "&client_secret=" + ConnUtil.urlEncode(secretKey);
// 打印的url出来放到浏览器内可以复现
System.out.println("token url:" + getTokenURL);
URL url = new URL(getTokenURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
String result = ConnUtil.getResponseString(conn);
System.out.println("Token result json:" + result);
parseJson(result);
}
/**
* @param result
* token接口获得的result
* @throws DemoException
*/
private void parseJson(String result) throws Exception {
JSONObject json = new JSONObject(result);
if (!json.has("access_token")) {
// 返回没有access_token字段
throw new DemoException("access_token not obtained, " + result);
}
if (!json.has("scope")) {
// 返回没有scope字段
throw new DemoException("scopenot obtained, " + result);
}
if (!json.getString("scope").contains(scope)) {
throw new DemoException("scope not exist, " + scope + "," + result);
}
token = json.getString("access_token");
expiresAt = System.currentTimeMillis() + json.getLong("expires_in") * 1000;
}
}

View File

@@ -0,0 +1,38 @@
package com.peanut.common.utils;
import com.peanut.modules.app.entity.UEditorFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.Date;
@Component
public class UEditorUpload {
private Logger log = LoggerFactory.getLogger(UEditorUpload.class);
private String path = ClassUtils.getDefaultClassLoader().getResource("").getPath();
public UEditorFile uploadImage(MultipartFile file) throws IOException {
log.info("UEditor开始上传文件");
String fileName = file.getOriginalFilename(); //获取文件名
//Ueditor的config.json规定的返回路径格式
String returnPath = "/image/upload/ueditor/"+new Date().getTime()+"/"+fileName;
File saveFile = new File(path+"static"+returnPath);
if (!saveFile.exists()){
saveFile.mkdirs();
}
file.transferTo(saveFile); //将临时文件移动到保存路径
log.info("UEditor上传文件成功保存路径"+saveFile.getAbsolutePath());
UEditorFile uEditorFile = new UEditorFile();
uEditorFile.setState("SUCCESS");
uEditorFile.setUrl(returnPath); //访问URL
uEditorFile.setTitle(fileName);
uEditorFile.setOriginal(fileName);
return uEditorFile;
}
}

View File

@@ -0,0 +1,32 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.validator;
import com.peanut.common.exception.RRException;
import org.apache.commons.lang.StringUtils;
/**
* 数据校验
*
* @author Mark sunlightcs@gmail.com
*/
public abstract class Assert {
public static void isBlank(String str, String message) {
if (StringUtils.isBlank(str)) {
throw new RRException(message);
}
}
public static void isNull(Object object, String message) {
if (object == null) {
throw new RRException(message);
}
}
}

View File

@@ -0,0 +1,54 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
* <p>
* https://www.renren.io
* <p>
* 版权所有,侵权必究!
*/
package com.peanut.common.validator;
import com.peanut.common.exception.RRException;
import com.peanut.common.utils.Constant;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;
/**
* hibernate-validator校验工具类
*
* 参考文档http://docs.jboss.org/hibernate/validator/5.4/reference/en-US/html_single/
*
* @author Mark sunlightcs@gmail.com
*/
public class ValidatorUtils {
private static Validator validator;
static {
validator = Validation.buildDefaultValidatorFactory().getValidator();
}
/**
* 校验对象
* @param object 待校验对象
* @param groups 待校验的组
* @throws RRException 校验不通过则报RRException异常
*/
public static void validateEntity(Object object, Class<?>... groups)
throws RRException {
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
if (!constraintViolations.isEmpty()) {
StringBuilder msg = new StringBuilder();
for (ConstraintViolation<Object> constraint : constraintViolations) {
msg.append(constraint.getMessage()).append("<br>");
}
throw new RRException(msg.toString());
}
}
public static void validateEntity(Object object, Constant.CloudService type) {
validateEntity(object, type.getValidatorGroupClass());
}
}

View File

@@ -0,0 +1,17 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.validator.group;
/**
* 新增数据 Group
*
* @author Mark sunlightcs@gmail.com
*/
public interface AddGroup {
}

View File

@@ -0,0 +1,17 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.validator.group;
/**
* 阿里云
*
* @author Mark sunlightcs@gmail.com
*/
public interface AliyunGroup {
}

View File

@@ -0,0 +1,21 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.validator.group;
import javax.validation.GroupSequence;
/**
* 定义校验顺序如果AddGroup组失败则UpdateGroup组不会再校验
*
* @author Mark sunlightcs@gmail.com
*/
@GroupSequence({AddGroup.class, UpdateGroup.class})
public interface Group {
}

View File

@@ -0,0 +1,17 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.validator.group;
/**
* 腾讯云
*
* @author Mark sunlightcs@gmail.com
*/
public interface QcloudGroup {
}

View File

@@ -0,0 +1,17 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.validator.group;
/**
* 七牛
*
* @author Mark sunlightcs@gmail.com
*/
public interface QiniuGroup {
}

View File

@@ -0,0 +1,19 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.validator.group;
/**
* 更新数据 Group
*
* @author Mark sunlightcs@gmail.com
*/
public interface UpdateGroup {
}

View File

@@ -0,0 +1,530 @@
package com.peanut.common.xss;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* HTML filtering utility for protecting against XSS (Cross Site Scripting).
*
* This code is licensed LGPLv3
*
* This code is a Java port of the original work in PHP by Cal Hendersen.
* http://code.iamcal.com/php/lib_filter/
*
* The trickiest part of the translation was handling the differences in regex handling
* between PHP and Java. These resources were helpful in the process:
*
* http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html
* http://us2.php.net/manual/en/reference.pcre.pattern.modifiers.php
* http://www.regular-expressions.info/modifiers.html
*
* A note on naming conventions: instance variables are prefixed with a "v"; global
* constants are in all caps.
*
* Sample use:
* String input = ...
* String clean = new HTMLFilter().filter( input );
*
* The class is not thread safe. Create a new instance if in doubt.
*
* If you find bugs or have suggestions on improvement (especially regarding
* performance), please contact us. The latest version of this
* source, and our contact details, can be found at http://xss-html-filter.sf.net
*
* @author Joseph O'Connell
* @author Cal Hendersen
* @author Michael Semb Wever
*/
public final class HTMLFilter {
/** regex flag union representing /si modifiers in php **/
private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);
private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);
private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);
private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);
private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);
private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");
private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");
private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");
private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
private static final Pattern P_END_ARROW = Pattern.compile("^>");
private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
private static final Pattern P_AMP = Pattern.compile("&");
private static final Pattern P_QUOTE = Pattern.compile("<");
private static final Pattern P_LEFT_ARROW = Pattern.compile("<");
private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");
private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");
// @xxx could grow large... maybe use sesat's ReferenceMap
private static final ConcurrentMap<String,Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<String, Pattern>();
private static final ConcurrentMap<String,Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<String, Pattern>();
/** set of allowed html elements, along with allowed attributes for each element **/
private final Map<String, List<String>> vAllowed;
/** counts of open tags for each (allowable) html element **/
private final Map<String, Integer> vTagCounts = new HashMap<String, Integer>();
/** html elements which must always be self-closing (e.g. "<img />") **/
private final String[] vSelfClosingTags;
/** html elements which must always have separate opening and closing tags (e.g. "<b></b>") **/
private final String[] vNeedClosingTags;
/** set of disallowed html elements **/
private final String[] vDisallowed;
/** attributes which should be checked for valid protocols **/
private final String[] vProtocolAtts;
/** allowed protocols **/
private final String[] vAllowedProtocols;
/** tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />") **/
private final String[] vRemoveBlanks;
/** entities allowed within html markup **/
private final String[] vAllowedEntities;
/** flag determining whether comments are allowed in input String. */
private final boolean stripComment;
private final boolean encodeQuotes;
private boolean vDebug = false;
/**
* flag determining whether to try to make tags when presented with "unbalanced"
* angle brackets (e.g. "<b text </b>" becomes "<b> text </b>"). If set to false,
* unbalanced angle brackets will be html escaped.
*/
private final boolean alwaysMakeTags;
/** Default constructor.
*
*/
public HTMLFilter() {
vAllowed = new HashMap<>();
final ArrayList<String> a_atts = new ArrayList<String>();
a_atts.add("href");
a_atts.add("target");
vAllowed.put("a", a_atts);
final ArrayList<String> img_atts = new ArrayList<String>();
img_atts.add("src");
img_atts.add("width");
img_atts.add("height");
img_atts.add("alt");
vAllowed.put("img", img_atts);
final ArrayList<String> no_atts = new ArrayList<String>();
vAllowed.put("b", no_atts);
vAllowed.put("strong", no_atts);
vAllowed.put("i", no_atts);
vAllowed.put("em", no_atts);
vSelfClosingTags = new String[]{"img"};
vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"};
vDisallowed = new String[]{};
vAllowedProtocols = new String[]{"http", "mailto", "https"}; // no ftp.
vProtocolAtts = new String[]{"src", "href"};
vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"};
vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"};
stripComment = true;
encodeQuotes = true;
alwaysMakeTags = true;
}
/** Set debug flag to true. Otherwise use default settings. See the default constructor.
*
* @param debug turn debug on with a true argument
*/
public HTMLFilter(final boolean debug) {
this();
vDebug = debug;
}
/** Map-parameter configurable constructor.
*
* @param conf map containing configuration. keys match field names.
*/
public HTMLFilter(final Map<String,Object> conf) {
assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";
assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";
assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";
assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";
assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";
assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";
vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));
vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");
vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");
vDisallowed = (String[]) conf.get("vDisallowed");
vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");
vProtocolAtts = (String[]) conf.get("vProtocolAtts");
vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");
vAllowedEntities = (String[]) conf.get("vAllowedEntities");
stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;
encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;
alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;
}
private void reset() {
vTagCounts.clear();
}
private void debug(final String msg) {
if (vDebug) {
Logger.getAnonymousLogger().info(msg);
}
}
//---------------------------------------------------------------
// my versions of some PHP library functions
public static String chr(final int decimal) {
return String.valueOf((char) decimal);
}
public static String htmlSpecialChars(final String s) {
String result = s;
result = regexReplace(P_AMP, "&amp;", result);
result = regexReplace(P_QUOTE, "&quot;", result);
result = regexReplace(P_LEFT_ARROW, "&lt;", result);
result = regexReplace(P_RIGHT_ARROW, "&gt;", result);
return result;
}
//---------------------------------------------------------------
/**
* given a user submitted input String, filter out any invalid or restricted
* html.
*
* @param input text (i.e. submitted by a user) than may contain html
* @return "clean" version of input, with only valid, whitelisted html elements allowed
*/
public String filter(final String input) {
reset();
String s = input;
debug("************************************************");
debug(" INPUT: " + input);
s = escapeComments(s);
debug(" escapeComments: " + s);
s = balanceHTML(s);
debug(" balanceHTML: " + s);
s = checkTags(s);
debug(" checkTags: " + s);
s = processRemoveBlanks(s);
debug("processRemoveBlanks: " + s);
s = validateEntities(s);
debug(" validateEntites: " + s);
debug("************************************************\n\n");
return s;
}
public boolean isAlwaysMakeTags(){
return alwaysMakeTags;
}
public boolean isStripComments(){
return stripComment;
}
private String escapeComments(final String s) {
final Matcher m = P_COMMENTS.matcher(s);
final StringBuffer buf = new StringBuffer();
if (m.find()) {
final String match = m.group(1); //(.*?)
m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));
}
m.appendTail(buf);
return buf.toString();
}
private String balanceHTML(String s) {
if (alwaysMakeTags) {
//
// try and form html
//
s = regexReplace(P_END_ARROW, "", s);
s = regexReplace(P_BODY_TO_END, "<$1>", s);
s = regexReplace(P_XML_CONTENT, "$1<$2", s);
} else {
//
// escape stray brackets
//
s = regexReplace(P_STRAY_LEFT_ARROW, "&lt;$1", s);
s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2&gt;<", s);
//
// the last regexp causes '<>' entities to appear
// (we need to do a lookahead assertion so that the last bracket can
// be used in the next pass of the regexp)
//
s = regexReplace(P_BOTH_ARROWS, "", s);
}
return s;
}
private String checkTags(String s) {
Matcher m = P_TAGS.matcher(s);
final StringBuffer buf = new StringBuffer();
while (m.find()) {
String replaceStr = m.group(1);
replaceStr = processTag(replaceStr);
m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));
}
m.appendTail(buf);
s = buf.toString();
// these get tallied in processTag
// (remember to reset before subsequent calls to filter method)
for (String key : vTagCounts.keySet()) {
for (int ii = 0; ii < vTagCounts.get(key); ii++) {
s += "</" + key + ">";
}
}
return s;
}
private String processRemoveBlanks(final String s) {
String result = s;
for (String tag : vRemoveBlanks) {
if(!P_REMOVE_PAIR_BLANKS.containsKey(tag)){
P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));
}
result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);
if(!P_REMOVE_SELF_BLANKS.containsKey(tag)){
P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));
}
result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);
}
return result;
}
private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) {
Matcher m = regex_pattern.matcher(s);
return m.replaceAll(replacement);
}
private String processTag(final String s) {
// ending tags
Matcher m = P_END_TAG.matcher(s);
if (m.find()) {
final String name = m.group(1).toLowerCase();
if (allowed(name)) {
if (!inArray(name, vSelfClosingTags)) {
if (vTagCounts.containsKey(name)) {
vTagCounts.put(name, vTagCounts.get(name) - 1);
return "</" + name + ">";
}
}
}
}
// starting tags
m = P_START_TAG.matcher(s);
if (m.find()) {
final String name = m.group(1).toLowerCase();
final String body = m.group(2);
String ending = m.group(3);
//debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
if (allowed(name)) {
String params = "";
final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);
final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);
final List<String> paramNames = new ArrayList<String>();
final List<String> paramValues = new ArrayList<String>();
while (m2.find()) {
paramNames.add(m2.group(1)); //([a-z0-9]+)
paramValues.add(m2.group(3)); //(.*?)
}
while (m3.find()) {
paramNames.add(m3.group(1)); //([a-z0-9]+)
paramValues.add(m3.group(3)); //([^\"\\s']+)
}
String paramName, paramValue;
for (int ii = 0; ii < paramNames.size(); ii++) {
paramName = paramNames.get(ii).toLowerCase();
paramValue = paramValues.get(ii);
// debug( "paramName='" + paramName + "'" );
// debug( "paramValue='" + paramValue + "'" );
// debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
if (allowedAttribute(name, paramName)) {
if (inArray(paramName, vProtocolAtts)) {
paramValue = processParamProtocol(paramValue);
}
params += " " + paramName + "=\"" + paramValue + "\"";
}
}
if (inArray(name, vSelfClosingTags)) {
ending = " /";
}
if (inArray(name, vNeedClosingTags)) {
ending = "";
}
if (ending == null || ending.length() < 1) {
if (vTagCounts.containsKey(name)) {
vTagCounts.put(name, vTagCounts.get(name) + 1);
} else {
vTagCounts.put(name, 1);
}
} else {
ending = " /";
}
return "<" + name + params + ending + ">";
} else {
return "";
}
}
// comments
m = P_COMMENT.matcher(s);
if (!stripComment && m.find()) {
return "<" + m.group() + ">";
}
return "";
}
private String processParamProtocol(String s) {
s = decodeEntities(s);
final Matcher m = P_PROTOCOL.matcher(s);
if (m.find()) {
final String protocol = m.group(1);
if (!inArray(protocol, vAllowedProtocols)) {
// bad protocol, turn into local anchor link instead
s = "#" + s.substring(protocol.length() + 1, s.length());
if (s.startsWith("#//")) {
s = "#" + s.substring(3, s.length());
}
}
}
return s;
}
private String decodeEntities(String s) {
StringBuffer buf = new StringBuffer();
Matcher m = P_ENTITY.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.decode(match).intValue();
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
buf = new StringBuffer();
m = P_ENTITY_UNICODE.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.valueOf(match, 16).intValue();
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
buf = new StringBuffer();
m = P_ENCODE.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.valueOf(match, 16).intValue();
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
s = validateEntities(s);
return s;
}
private String validateEntities(final String s) {
StringBuffer buf = new StringBuffer();
// validate entities throughout the string
Matcher m = P_VALID_ENTITIES.matcher(s);
while (m.find()) {
final String one = m.group(1); //([^&;]*)
final String two = m.group(2); //(?=(;|&|$))
m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));
}
m.appendTail(buf);
return encodeQuotes(buf.toString());
}
private String encodeQuotes(final String s){
if(encodeQuotes){
StringBuffer buf = new StringBuffer();
Matcher m = P_VALID_QUOTES.matcher(s);
while (m.find()) {
final String one = m.group(1); //(>|^)
final String two = m.group(2); //([^<]+?)
final String three = m.group(3); //(<|$)
m.appendReplacement(buf, Matcher.quoteReplacement(one + regexReplace(P_QUOTE, "&quot;", two) + three));
}
m.appendTail(buf);
return buf.toString();
}else{
return s;
}
}
private String checkEntity(final String preamble, final String term) {
return ";".equals(term) && isValidEntity(preamble)
? '&' + preamble
: "&amp;" + preamble;
}
private boolean isValidEntity(final String entity) {
return inArray(entity, vAllowedEntities);
}
private static boolean inArray(final String s, final String[] array) {
for (String item : array) {
if (item != null && item.equals(s)) {
return true;
}
}
return false;
}
private boolean allowed(final String name) {
return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);
}
private boolean allowedAttribute(final String name, final String paramName) {
return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));
}
}

View File

@@ -0,0 +1,50 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.xss;
import com.peanut.common.exception.RRException;
import org.apache.commons.lang.StringUtils;
/**
* SQL过滤
*
* @author Mark sunlightcs@gmail.com
*/
public class SQLFilter {
/**
* SQL注入过滤
* @param str 待验证的字符串
*/
public static String sqlInject(String str){
if(StringUtils.isBlank(str)){
return null;
}
//去掉'|"|;|\字符
str = StringUtils.replace(str, "'", "");
str = StringUtils.replace(str, "\"", "");
str = StringUtils.replace(str, ";", "");
str = StringUtils.replace(str, "\\", "");
//转换成小写
str = str.toLowerCase();
//非法字符
String[] keywords = {"master", "truncate", "insert", "select", "delete", "update", "declare", "alter", "drop"};
//判断是否包含非法字符
for(String keyword : keywords){
if(str.indexOf(keyword) != -1){
throw new RRException("包含非法字符");
}
}
return str;
}
}

View File

@@ -0,0 +1,37 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.xss;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* XSS过滤
*
* @author Mark sunlightcs@gmail.com
*/
public class XssFilter implements Filter {
@Override
public void init(FilterConfig config) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(
(HttpServletRequest) request);
chain.doFilter(xssRequest, response);
}
@Override
public void destroy() {
}
}

View File

@@ -0,0 +1,147 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.peanut.common.xss;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* XSS过滤处理
*
* @author Mark sunlightcs@gmail.com
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
//没被包装过的HttpServletRequest特殊场景需要自己过滤
HttpServletRequest orgRequest;
//html过滤
private final static HTMLFilter htmlFilter = new HTMLFilter();
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
orgRequest = request;
}
@Override
public ServletInputStream getInputStream() throws IOException {
//非json类型直接返回
if(!MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(super.getHeader(HttpHeaders.CONTENT_TYPE))){
return super.getInputStream();
}
//为空,直接返回
String json = IOUtils.toString(super.getInputStream(), "utf-8");
if (StringUtils.isBlank(json)) {
return super.getInputStream();
}
//xss过滤
json = xssEncode(json);
final ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes("utf-8"));
return new ServletInputStream() {
@Override
public boolean isFinished() {
return true;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return bis.read();
}
};
}
@Override
public String getParameter(String name) {
String value = super.getParameter(xssEncode(name));
if (StringUtils.isNotBlank(value)) {
value = xssEncode(value);
}
return value;
}
@Override
public String[] getParameterValues(String name) {
String[] parameters = super.getParameterValues(name);
if (parameters == null || parameters.length == 0) {
return null;
}
for (int i = 0; i < parameters.length; i++) {
parameters[i] = xssEncode(parameters[i]);
}
return parameters;
}
@Override
public Map<String,String[]> getParameterMap() {
Map<String,String[]> map = new LinkedHashMap<>();
Map<String,String[]> parameters = super.getParameterMap();
for (String key : parameters.keySet()) {
String[] values = parameters.get(key);
for (int i = 0; i < values.length; i++) {
values[i] = xssEncode(values[i]);
}
map.put(key, values);
}
return map;
}
@Override
public String getHeader(String name) {
String value = super.getHeader(xssEncode(name));
if (StringUtils.isNotBlank(value)) {
value = xssEncode(value);
}
return value;
}
private String xssEncode(String input) {
return htmlFilter.filter(input);
}
/**
* 获取最原始的request
*/
public HttpServletRequest getOrgRequest() {
return orgRequest;
}
/**
* 获取最原始的request
*/
public static HttpServletRequest getOrgRequest(HttpServletRequest request) {
if (request instanceof XssHttpServletRequestWrapper) {
return ((XssHttpServletRequestWrapper) request).getOrgRequest();
}
return request;
}
}