first commit
This commit is contained in:
127
src/main/java/com/baidu/ueditor/ActionEnter.java
Normal file
127
src/main/java/com/baidu/ueditor/ActionEnter.java
Normal file
@@ -0,0 +1,127 @@
|
||||
package com.baidu.ueditor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.baidu.ueditor.define.ActionMap;
|
||||
import com.baidu.ueditor.define.AppInfo;
|
||||
import com.baidu.ueditor.define.BaseState;
|
||||
import com.baidu.ueditor.define.State;
|
||||
import com.baidu.ueditor.hunter.FileManager;
|
||||
import com.baidu.ueditor.hunter.ImageHunter;
|
||||
import com.baidu.ueditor.upload.Uploader;
|
||||
|
||||
public class ActionEnter {
|
||||
|
||||
private HttpServletRequest request = null;
|
||||
|
||||
private String rootPath = null;
|
||||
private String contextPath = null;
|
||||
|
||||
private String actionType = null;
|
||||
|
||||
private ConfigManager configManager = null;
|
||||
|
||||
public ActionEnter ( HttpServletRequest request, String rootPath ) {
|
||||
|
||||
this.request = request;
|
||||
this.rootPath = rootPath;
|
||||
this.actionType = request.getParameter( "action" );
|
||||
this.contextPath = request.getContextPath();
|
||||
this.configManager = ConfigManager.getInstance( this.rootPath, this.contextPath, request.getRequestURI() );
|
||||
|
||||
}
|
||||
|
||||
public String exec () {
|
||||
|
||||
String callbackName = this.request.getParameter("callback");
|
||||
|
||||
if ( callbackName != null ) {
|
||||
|
||||
if ( !validCallbackName( callbackName ) ) {
|
||||
return new BaseState( false, AppInfo.ILLEGAL ).toJSONString();
|
||||
}
|
||||
|
||||
return callbackName+"("+this.invoke()+");";
|
||||
|
||||
} else {
|
||||
return this.invoke();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String invoke() {
|
||||
|
||||
if ( actionType == null || !ActionMap.mapping.containsKey( actionType ) ) {
|
||||
return new BaseState( false, AppInfo.INVALID_ACTION ).toJSONString();
|
||||
}
|
||||
|
||||
if ( this.configManager == null || !this.configManager.valid() ) {
|
||||
return new BaseState( false, AppInfo.CONFIG_ERROR ).toJSONString();
|
||||
}
|
||||
|
||||
State state = null;
|
||||
|
||||
int actionCode = ActionMap.getType( this.actionType );
|
||||
|
||||
Map<String, Object> conf = null;
|
||||
|
||||
switch ( actionCode ) {
|
||||
|
||||
case ActionMap.CONFIG:
|
||||
return this.configManager.getAllConfig().toString();
|
||||
|
||||
case ActionMap.UPLOAD_IMAGE:
|
||||
case ActionMap.UPLOAD_SCRAWL:
|
||||
case ActionMap.UPLOAD_VIDEO:
|
||||
case ActionMap.UPLOAD_FILE:
|
||||
conf = this.configManager.getConfig( actionCode );
|
||||
state = new Uploader( request, conf ).doExec();
|
||||
break;
|
||||
|
||||
case ActionMap.CATCH_IMAGE:
|
||||
conf = configManager.getConfig( actionCode );
|
||||
String[] list = this.request.getParameterValues( (String)conf.get( "fieldName" ) );
|
||||
state = new ImageHunter( conf ).capture( list );
|
||||
break;
|
||||
|
||||
case ActionMap.LIST_IMAGE:
|
||||
case ActionMap.LIST_FILE:
|
||||
conf = configManager.getConfig( actionCode );
|
||||
int start = this.getStartIndex();
|
||||
state = new FileManager( conf ).listFile( start );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return state.toJSONString();
|
||||
|
||||
}
|
||||
|
||||
public int getStartIndex () {
|
||||
|
||||
String start = this.request.getParameter( "start" );
|
||||
|
||||
try {
|
||||
return Integer.parseInt( start );
|
||||
} catch ( Exception e ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* callback参数验证
|
||||
*/
|
||||
public boolean validCallbackName ( String name ) {
|
||||
|
||||
if ( name.matches( "^[a-zA-Z_]+[\\w0-9_]*$" ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
230
src/main/java/com/baidu/ueditor/ConfigManager.java
Normal file
230
src/main/java/com/baidu/ueditor/ConfigManager.java
Normal file
@@ -0,0 +1,230 @@
|
||||
package com.baidu.ueditor;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import com.baidu.ueditor.define.ActionMap;
|
||||
|
||||
/**
|
||||
* 配置管理器
|
||||
* @author hancong03@baidu.com
|
||||
*
|
||||
*/
|
||||
public final class ConfigManager {
|
||||
|
||||
private final String rootPath;
|
||||
private final String originalPath;
|
||||
private final String contextPath;
|
||||
private static final String configFileName = "uedit-config.json";
|
||||
private String parentPath = null;
|
||||
private JSONObject jsonConfig = null;
|
||||
// 涂鸦上传filename定义
|
||||
private final static String SCRAWL_FILE_NAME = "scrawl";
|
||||
// 远程图片抓取filename定义
|
||||
private final static String REMOTE_FILE_NAME = "remote";
|
||||
|
||||
/*
|
||||
* 通过一个给定的路径构建一个配置管理器, 该管理器要求地址路径所在目录下必须存在config.properties文件
|
||||
*/
|
||||
private ConfigManager ( String rootPath, String contextPath, String uri ) throws FileNotFoundException, IOException {
|
||||
|
||||
rootPath = rootPath.replace( "\\", "/" );
|
||||
|
||||
this.rootPath = rootPath;
|
||||
this.contextPath = contextPath;
|
||||
|
||||
if ( contextPath.length() > 0 ) {
|
||||
this.originalPath = this.rootPath + uri.substring( contextPath.length() );
|
||||
} else {
|
||||
this.originalPath = this.rootPath + uri;
|
||||
}
|
||||
|
||||
this.initEnv();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置管理器构造工厂
|
||||
* @param rootPath 服务器根路径
|
||||
* @param contextPath 服务器所在项目路径
|
||||
* @param uri 当前访问的uri
|
||||
* @return 配置管理器实例或者null
|
||||
*/
|
||||
public static ConfigManager getInstance ( String rootPath, String contextPath, String uri ) {
|
||||
|
||||
try {
|
||||
return new ConfigManager(rootPath, contextPath, uri);
|
||||
} catch ( Exception e ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 验证配置文件加载是否正确
|
||||
public boolean valid () {
|
||||
return this.jsonConfig != null;
|
||||
}
|
||||
|
||||
public JSONObject getAllConfig () {
|
||||
|
||||
return this.jsonConfig;
|
||||
|
||||
}
|
||||
|
||||
public Map<String, Object> getConfig ( int type ) {
|
||||
|
||||
Map<String, Object> conf = new HashMap<String, Object>();
|
||||
String savePath = null;
|
||||
|
||||
switch ( type ) {
|
||||
|
||||
case ActionMap.UPLOAD_FILE:
|
||||
conf.put( "isBase64", "false" );
|
||||
conf.put( "maxSize", this.jsonConfig.getLong( "fileMaxSize" ) );
|
||||
conf.put( "allowFiles", this.getArray( "fileAllowFiles" ) );
|
||||
conf.put( "fieldName", this.jsonConfig.getString( "fileFieldName" ) );
|
||||
savePath = this.jsonConfig.getString( "filePathFormat" );
|
||||
break;
|
||||
|
||||
case ActionMap.UPLOAD_IMAGE:
|
||||
conf.put( "isBase64", "false" );
|
||||
conf.put( "maxSize", this.jsonConfig.getLong( "imageMaxSize" ) );
|
||||
conf.put( "allowFiles", this.getArray( "imageAllowFiles" ) );
|
||||
conf.put( "fieldName", this.jsonConfig.getString( "imageFieldName" ) );
|
||||
savePath = this.jsonConfig.getString( "imagePathFormat" );
|
||||
break;
|
||||
|
||||
case ActionMap.UPLOAD_VIDEO:
|
||||
conf.put( "maxSize", this.jsonConfig.getLong( "videoMaxSize" ) );
|
||||
conf.put( "allowFiles", this.getArray( "videoAllowFiles" ) );
|
||||
conf.put( "fieldName", this.jsonConfig.getString( "videoFieldName" ) );
|
||||
savePath = this.jsonConfig.getString( "videoPathFormat" );
|
||||
break;
|
||||
|
||||
case ActionMap.UPLOAD_SCRAWL:
|
||||
conf.put( "filename", ConfigManager.SCRAWL_FILE_NAME );
|
||||
conf.put( "maxSize", this.jsonConfig.getLong( "scrawlMaxSize" ) );
|
||||
conf.put( "fieldName", this.jsonConfig.getString( "scrawlFieldName" ) );
|
||||
conf.put( "isBase64", "true" );
|
||||
savePath = this.jsonConfig.getString( "scrawlPathFormat" );
|
||||
break;
|
||||
|
||||
case ActionMap.CATCH_IMAGE:
|
||||
conf.put( "filename", ConfigManager.REMOTE_FILE_NAME );
|
||||
conf.put( "filter", this.getArray( "catcherLocalDomain" ) );
|
||||
conf.put( "maxSize", this.jsonConfig.getLong( "catcherMaxSize" ) );
|
||||
conf.put( "allowFiles", this.getArray( "catcherAllowFiles" ) );
|
||||
conf.put( "fieldName", this.jsonConfig.getString( "catcherFieldName" ) + "[]" );
|
||||
savePath = this.jsonConfig.getString( "catcherPathFormat" );
|
||||
break;
|
||||
|
||||
case ActionMap.LIST_IMAGE:
|
||||
conf.put( "allowFiles", this.getArray( "imageManagerAllowFiles" ) );
|
||||
conf.put( "dir", this.jsonConfig.getString( "imageManagerListPath" ) );
|
||||
conf.put( "count", this.jsonConfig.getInt( "imageManagerListSize" ) );
|
||||
break;
|
||||
|
||||
case ActionMap.LIST_FILE:
|
||||
conf.put( "allowFiles", this.getArray( "fileManagerAllowFiles" ) );
|
||||
conf.put( "dir", this.jsonConfig.getString( "fileManagerListPath" ) );
|
||||
conf.put( "count", this.jsonConfig.getInt( "fileManagerListSize" ) );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
conf.put( "savePath", savePath );
|
||||
conf.put( "rootPath", this.rootPath );
|
||||
|
||||
return conf;
|
||||
|
||||
}
|
||||
|
||||
private void initEnv () throws FileNotFoundException, IOException {
|
||||
|
||||
File file = new File( this.originalPath );
|
||||
|
||||
if ( !file.isAbsolute() ) {
|
||||
file = new File( file.getAbsolutePath() );
|
||||
}
|
||||
|
||||
this.parentPath = file.getParent();
|
||||
|
||||
String configContent = this.readFile( this.getConfigPath() );
|
||||
|
||||
try{
|
||||
JSONObject jsonConfig = new JSONObject( configContent );
|
||||
this.jsonConfig = jsonConfig;
|
||||
} catch ( Exception e ) {
|
||||
this.jsonConfig = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String getConfigPath () {
|
||||
// return this.parentPath + File.separator + ConfigManager.configFileName;
|
||||
// 修改源码
|
||||
try{
|
||||
return this.getClass().getClassLoader().getResource("uedit-config.json").toURI().getPath();
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String[] getArray ( String key ) {
|
||||
|
||||
JSONArray jsonArray = this.jsonConfig.getJSONArray( key );
|
||||
String[] result = new String[ jsonArray.length() ];
|
||||
|
||||
for ( int i = 0, len = jsonArray.length(); i < len; i++ ) {
|
||||
result[i] = jsonArray.getString( i );
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private String readFile ( String path ) throws IOException {
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
try {
|
||||
|
||||
InputStreamReader reader = new InputStreamReader( new FileInputStream( path ), "UTF-8" );
|
||||
BufferedReader bfReader = new BufferedReader( reader );
|
||||
|
||||
String tmpContent = null;
|
||||
|
||||
while ( ( tmpContent = bfReader.readLine() ) != null ) {
|
||||
builder.append( tmpContent );
|
||||
}
|
||||
|
||||
bfReader.close();
|
||||
|
||||
} catch ( UnsupportedEncodingException e ) {
|
||||
// 忽略
|
||||
}
|
||||
|
||||
return this.filter( builder.toString() );
|
||||
|
||||
}
|
||||
|
||||
// 过滤输入字符串, 剔除多行注释以及替换掉反斜杠
|
||||
private String filter ( String input ) {
|
||||
|
||||
return input.replaceAll( "/\\*[\\s\\S]*?\\*/", "" );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
24
src/main/java/com/baidu/ueditor/Encoder.java
Normal file
24
src/main/java/com/baidu/ueditor/Encoder.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.baidu.ueditor;
|
||||
|
||||
public class Encoder {
|
||||
|
||||
public static String toUnicode ( String input ) {
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
char[] chars = input.toCharArray();
|
||||
|
||||
for ( char ch : chars ) {
|
||||
|
||||
if ( ch < 256 ) {
|
||||
builder.append( ch );
|
||||
} else {
|
||||
builder.append( "\\u" + Integer.toHexString( ch& 0xffff ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
157
src/main/java/com/baidu/ueditor/PathFormat.java
Normal file
157
src/main/java/com/baidu/ueditor/PathFormat.java
Normal file
@@ -0,0 +1,157 @@
|
||||
package com.baidu.ueditor;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class PathFormat {
|
||||
|
||||
private static final String TIME = "time";
|
||||
private static final String FULL_YEAR = "yyyy";
|
||||
private static final String YEAR = "yy";
|
||||
private static final String MONTH = "mm";
|
||||
private static final String DAY = "dd";
|
||||
private static final String HOUR = "hh";
|
||||
private static final String MINUTE = "ii";
|
||||
private static final String SECOND = "ss";
|
||||
private static final String RAND = "rand";
|
||||
|
||||
private static Date currentDate = null;
|
||||
|
||||
public static String parse ( String input ) {
|
||||
|
||||
Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE );
|
||||
Matcher matcher = pattern.matcher(input);
|
||||
|
||||
PathFormat.currentDate = new Date();
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
while ( matcher.find() ) {
|
||||
|
||||
matcher.appendReplacement(sb, PathFormat.getString( matcher.group( 1 ) ) );
|
||||
|
||||
}
|
||||
|
||||
matcher.appendTail(sb);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化路径, 把windows路径替换成标准路径
|
||||
* @param input 待格式化的路径
|
||||
* @return 格式化后的路径
|
||||
*/
|
||||
public static String format ( String input ) {
|
||||
|
||||
return input.replace( "\\", "/" );
|
||||
|
||||
}
|
||||
|
||||
public static String parse ( String input, String filename ) {
|
||||
|
||||
Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE );
|
||||
Matcher matcher = pattern.matcher(input);
|
||||
String matchStr = null;
|
||||
|
||||
PathFormat.currentDate = new Date();
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
while ( matcher.find() ) {
|
||||
|
||||
matchStr = matcher.group( 1 );
|
||||
if ( matchStr.indexOf( "filename" ) != -1 ) {
|
||||
filename = filename.replace( "$", "\\$" ).replaceAll( "[\\/:*?\"<>|]", "" );
|
||||
matcher.appendReplacement(sb, filename );
|
||||
} else {
|
||||
matcher.appendReplacement(sb, PathFormat.getString( matchStr ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
matcher.appendTail(sb);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String getString ( String pattern ) {
|
||||
|
||||
pattern = pattern.toLowerCase();
|
||||
|
||||
// time 处理
|
||||
if ( pattern.indexOf( PathFormat.TIME ) != -1 ) {
|
||||
return PathFormat.getTimestamp();
|
||||
} else if ( pattern.indexOf( PathFormat.FULL_YEAR ) != -1 ) {
|
||||
return PathFormat.getFullYear();
|
||||
} else if ( pattern.indexOf( PathFormat.YEAR ) != -1 ) {
|
||||
return PathFormat.getYear();
|
||||
} else if ( pattern.indexOf( PathFormat.MONTH ) != -1 ) {
|
||||
return PathFormat.getMonth();
|
||||
} else if ( pattern.indexOf( PathFormat.DAY ) != -1 ) {
|
||||
return PathFormat.getDay();
|
||||
} else if ( pattern.indexOf( PathFormat.HOUR ) != -1 ) {
|
||||
return PathFormat.getHour();
|
||||
} else if ( pattern.indexOf( PathFormat.MINUTE ) != -1 ) {
|
||||
return PathFormat.getMinute();
|
||||
} else if ( pattern.indexOf( PathFormat.SECOND ) != -1 ) {
|
||||
return PathFormat.getSecond();
|
||||
} else if ( pattern.indexOf( PathFormat.RAND ) != -1 ) {
|
||||
return PathFormat.getRandom( pattern );
|
||||
}
|
||||
|
||||
return pattern;
|
||||
|
||||
}
|
||||
|
||||
private static String getTimestamp () {
|
||||
return System.currentTimeMillis() + "";
|
||||
}
|
||||
|
||||
private static String getFullYear () {
|
||||
return new SimpleDateFormat( "yyyy" ).format( PathFormat.currentDate );
|
||||
}
|
||||
|
||||
private static String getYear () {
|
||||
return new SimpleDateFormat( "yy" ).format( PathFormat.currentDate );
|
||||
}
|
||||
|
||||
private static String getMonth () {
|
||||
return new SimpleDateFormat( "MM" ).format( PathFormat.currentDate );
|
||||
}
|
||||
|
||||
private static String getDay () {
|
||||
return new SimpleDateFormat( "dd" ).format( PathFormat.currentDate );
|
||||
}
|
||||
|
||||
private static String getHour () {
|
||||
return new SimpleDateFormat( "HH" ).format( PathFormat.currentDate );
|
||||
}
|
||||
|
||||
private static String getMinute () {
|
||||
return new SimpleDateFormat( "mm" ).format( PathFormat.currentDate );
|
||||
}
|
||||
|
||||
private static String getSecond () {
|
||||
return new SimpleDateFormat( "ss" ).format( PathFormat.currentDate );
|
||||
}
|
||||
|
||||
private static String getRandom ( String pattern ) {
|
||||
|
||||
int length = 0;
|
||||
pattern = pattern.split( ":" )[ 1 ].trim();
|
||||
|
||||
length = Integer.parseInt( pattern );
|
||||
|
||||
return ( Math.random() + "" ).replace( ".", "" ).substring( 0, length );
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
42
src/main/java/com/baidu/ueditor/define/ActionMap.java
Normal file
42
src/main/java/com/baidu/ueditor/define/ActionMap.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package com.baidu.ueditor.define;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* 定义请求action类型
|
||||
* @author hancong03@baidu.com
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public final class ActionMap {
|
||||
|
||||
public static final Map<String, Integer> mapping;
|
||||
// 获取配置请求
|
||||
public static final int CONFIG = 0;
|
||||
public static final int UPLOAD_IMAGE = 1;
|
||||
public static final int UPLOAD_SCRAWL = 2;
|
||||
public static final int UPLOAD_VIDEO = 3;
|
||||
public static final int UPLOAD_FILE = 4;
|
||||
public static final int CATCH_IMAGE = 5;
|
||||
public static final int LIST_FILE = 6;
|
||||
public static final int LIST_IMAGE = 7;
|
||||
|
||||
static {
|
||||
mapping = new HashMap<String, Integer>(){{
|
||||
put( "config", ActionMap.CONFIG );
|
||||
put( "uploadimage", ActionMap.UPLOAD_IMAGE );
|
||||
put( "uploadscrawl", ActionMap.UPLOAD_SCRAWL );
|
||||
put( "uploadvideo", ActionMap.UPLOAD_VIDEO );
|
||||
put( "uploadfile", ActionMap.UPLOAD_FILE );
|
||||
put( "catchimage", ActionMap.CATCH_IMAGE );
|
||||
put( "listfile", ActionMap.LIST_FILE );
|
||||
put( "listimage", ActionMap.LIST_IMAGE );
|
||||
}};
|
||||
}
|
||||
|
||||
public static int getType ( String key ) {
|
||||
return ActionMap.mapping.get( key );
|
||||
}
|
||||
|
||||
}
|
||||
5
src/main/java/com/baidu/ueditor/define/ActionState.java
Normal file
5
src/main/java/com/baidu/ueditor/define/ActionState.java
Normal file
@@ -0,0 +1,5 @@
|
||||
package com.baidu.ueditor.define;
|
||||
|
||||
public enum ActionState {
|
||||
UNKNOW_ERROR
|
||||
}
|
||||
77
src/main/java/com/baidu/ueditor/define/AppInfo.java
Normal file
77
src/main/java/com/baidu/ueditor/define/AppInfo.java
Normal file
@@ -0,0 +1,77 @@
|
||||
package com.baidu.ueditor.define;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class AppInfo {
|
||||
|
||||
public static final int SUCCESS = 0;
|
||||
public static final int MAX_SIZE = 1;
|
||||
public static final int PERMISSION_DENIED = 2;
|
||||
public static final int FAILED_CREATE_FILE = 3;
|
||||
public static final int IO_ERROR = 4;
|
||||
public static final int NOT_MULTIPART_CONTENT = 5;
|
||||
public static final int PARSE_REQUEST_ERROR = 6;
|
||||
public static final int NOTFOUND_UPLOAD_DATA = 7;
|
||||
public static final int NOT_ALLOW_FILE_TYPE = 8;
|
||||
|
||||
public static final int INVALID_ACTION = 101;
|
||||
public static final int CONFIG_ERROR = 102;
|
||||
|
||||
public static final int PREVENT_HOST = 201;
|
||||
public static final int CONNECTION_ERROR = 202;
|
||||
public static final int REMOTE_FAIL = 203;
|
||||
|
||||
public static final int NOT_DIRECTORY = 301;
|
||||
public static final int NOT_EXIST = 302;
|
||||
|
||||
public static final int ILLEGAL = 401;
|
||||
|
||||
public static Map<Integer, String> info = new HashMap<Integer, String>(){{
|
||||
|
||||
put( AppInfo.SUCCESS, "SUCCESS" );
|
||||
|
||||
// 无效的Action
|
||||
put( AppInfo.INVALID_ACTION, "\u65E0\u6548\u7684Action" );
|
||||
// 配置文件初始化失败
|
||||
put( AppInfo.CONFIG_ERROR, "\u914D\u7F6E\u6587\u4EF6\u521D\u59CB\u5316\u5931\u8D25" );
|
||||
// 抓取远程图片失败
|
||||
put( AppInfo.REMOTE_FAIL, "\u6293\u53D6\u8FDC\u7A0B\u56FE\u7247\u5931\u8D25" );
|
||||
|
||||
// 被阻止的远程主机
|
||||
put( AppInfo.PREVENT_HOST, "\u88AB\u963B\u6B62\u7684\u8FDC\u7A0B\u4E3B\u673A" );
|
||||
// 远程连接出错
|
||||
put( AppInfo.CONNECTION_ERROR, "\u8FDC\u7A0B\u8FDE\u63A5\u51FA\u9519" );
|
||||
|
||||
// "文件大小超出限制"
|
||||
put( AppInfo.MAX_SIZE, "\u6587\u4ef6\u5927\u5c0f\u8d85\u51fa\u9650\u5236" );
|
||||
// 权限不足, 多指写权限
|
||||
put( AppInfo.PERMISSION_DENIED, "\u6743\u9650\u4E0D\u8DB3" );
|
||||
// 创建文件失败
|
||||
put( AppInfo.FAILED_CREATE_FILE, "\u521B\u5EFA\u6587\u4EF6\u5931\u8D25" );
|
||||
// IO错误
|
||||
put( AppInfo.IO_ERROR, "IO\u9519\u8BEF" );
|
||||
// 上传表单不是multipart/form-data类型
|
||||
put( AppInfo.NOT_MULTIPART_CONTENT, "\u4E0A\u4F20\u8868\u5355\u4E0D\u662Fmultipart/form-data\u7C7B\u578B" );
|
||||
// 解析上传表单错误
|
||||
put( AppInfo.PARSE_REQUEST_ERROR, "\u89E3\u6790\u4E0A\u4F20\u8868\u5355\u9519\u8BEF" );
|
||||
// 未找到上传数据
|
||||
put( AppInfo.NOTFOUND_UPLOAD_DATA, "\u672A\u627E\u5230\u4E0A\u4F20\u6570\u636E" );
|
||||
// 不允许的文件类型
|
||||
put( AppInfo.NOT_ALLOW_FILE_TYPE, "\u4E0D\u5141\u8BB8\u7684\u6587\u4EF6\u7C7B\u578B" );
|
||||
|
||||
// 指定路径不是目录
|
||||
put( AppInfo.NOT_DIRECTORY, "\u6307\u5B9A\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55" );
|
||||
// 指定路径并不存在
|
||||
put( AppInfo.NOT_EXIST, "\u6307\u5B9A\u8DEF\u5F84\u5E76\u4E0D\u5B58\u5728" );
|
||||
|
||||
// callback参数名不合法
|
||||
put( AppInfo.ILLEGAL, "Callback\u53C2\u6570\u540D\u4E0D\u5408\u6CD5" );
|
||||
|
||||
}};
|
||||
|
||||
public static String getStateInfo ( int key ) {
|
||||
return AppInfo.info.get( key );
|
||||
}
|
||||
|
||||
}
|
||||
90
src/main/java/com/baidu/ueditor/define/BaseState.java
Normal file
90
src/main/java/com/baidu/ueditor/define/BaseState.java
Normal file
@@ -0,0 +1,90 @@
|
||||
package com.baidu.ueditor.define;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import com.baidu.ueditor.Encoder;
|
||||
|
||||
public class BaseState implements State {
|
||||
|
||||
private boolean state = false;
|
||||
private String info = null;
|
||||
|
||||
private Map<String, String> infoMap = new HashMap<String, String>();
|
||||
|
||||
public BaseState () {
|
||||
this.state = true;
|
||||
}
|
||||
|
||||
public BaseState ( boolean state ) {
|
||||
this.setState( state );
|
||||
}
|
||||
|
||||
public BaseState ( boolean state, String info ) {
|
||||
this.setState( state );
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public BaseState ( boolean state, int infoCode ) {
|
||||
this.setState( state );
|
||||
this.info = AppInfo.getStateInfo( infoCode );
|
||||
}
|
||||
|
||||
public boolean isSuccess () {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
public void setState ( boolean state ) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void setInfo ( String info ) {
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public void setInfo ( int infoCode ) {
|
||||
this.info = AppInfo.getStateInfo( infoCode );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toJSONString() {
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
public String toString () {
|
||||
|
||||
String key = null;
|
||||
String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info;
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append( "{\"state\": \"" + stateVal + "\"" );
|
||||
|
||||
Iterator<String> iterator = this.infoMap.keySet().iterator();
|
||||
|
||||
while ( iterator.hasNext() ) {
|
||||
|
||||
key = iterator.next();
|
||||
|
||||
builder.append( ",\"" + key + "\": \"" + this.infoMap.get(key) + "\"" );
|
||||
|
||||
}
|
||||
|
||||
builder.append( "}" );
|
||||
|
||||
return Encoder.toUnicode( builder.toString() );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putInfo(String name, String val) {
|
||||
this.infoMap.put(name, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putInfo(String name, long val) {
|
||||
this.putInfo(name, val+"");
|
||||
}
|
||||
|
||||
}
|
||||
31
src/main/java/com/baidu/ueditor/define/FileType.java
Normal file
31
src/main/java/com/baidu/ueditor/define/FileType.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package com.baidu.ueditor.define;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class FileType {
|
||||
|
||||
public static final String JPG = "JPG";
|
||||
|
||||
private static final Map<String, String> types = new HashMap<String, String>(){{
|
||||
|
||||
put( FileType.JPG, ".jpg" );
|
||||
|
||||
}};
|
||||
|
||||
public static String getSuffix ( String key ) {
|
||||
return FileType.types.get( key );
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据给定的文件名,获取其后缀信息
|
||||
* @param filename
|
||||
* @return
|
||||
*/
|
||||
public static String getSuffixByFilename ( String filename ) {
|
||||
|
||||
return filename.substring( filename.lastIndexOf( "." ) ).toLowerCase();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
20
src/main/java/com/baidu/ueditor/define/MIMEType.java
Normal file
20
src/main/java/com/baidu/ueditor/define/MIMEType.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package com.baidu.ueditor.define;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class MIMEType {
|
||||
|
||||
public static final Map<String, String> types = new HashMap<String, String>(){{
|
||||
put( "image/gif", ".gif" );
|
||||
put( "image/jpeg", ".jpg" );
|
||||
put( "image/jpg", ".jpg" );
|
||||
put( "image/png", ".png" );
|
||||
put( "image/bmp", ".bmp" );
|
||||
}};
|
||||
|
||||
public static String getSuffix ( String mime ) {
|
||||
return MIMEType.types.get( mime );
|
||||
}
|
||||
|
||||
}
|
||||
112
src/main/java/com/baidu/ueditor/define/MultiState.java
Normal file
112
src/main/java/com/baidu/ueditor/define/MultiState.java
Normal file
@@ -0,0 +1,112 @@
|
||||
package com.baidu.ueditor.define;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.baidu.ueditor.Encoder;
|
||||
|
||||
/**
|
||||
* 多状态集合状态
|
||||
* 其包含了多个状态的集合, 其本身自己也是一个状态
|
||||
* @author hancong03@baidu.com
|
||||
*
|
||||
*/
|
||||
public class MultiState implements State {
|
||||
|
||||
private boolean state = false;
|
||||
private String info = null;
|
||||
private Map<String, Long> intMap = new HashMap<String, Long>();
|
||||
private Map<String, String> infoMap = new HashMap<String, String>();
|
||||
private List<String> stateList = new ArrayList<String>();
|
||||
|
||||
public MultiState ( boolean state ) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public MultiState ( boolean state, String info ) {
|
||||
this.state = state;
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public MultiState ( boolean state, int infoKey ) {
|
||||
this.state = state;
|
||||
this.info = AppInfo.getStateInfo( infoKey );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuccess() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
public void addState ( State state ) {
|
||||
stateList.add( state.toJSONString() );
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法调用无效果
|
||||
*/
|
||||
@Override
|
||||
public void putInfo(String name, String val) {
|
||||
this.infoMap.put(name, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toJSONString() {
|
||||
|
||||
String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info;
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append( "{\"state\": \"" + stateVal + "\"" );
|
||||
|
||||
// 数字转换
|
||||
Iterator<String> iterator = this.intMap.keySet().iterator();
|
||||
|
||||
while ( iterator.hasNext() ) {
|
||||
|
||||
stateVal = iterator.next();
|
||||
|
||||
builder.append( ",\""+ stateVal +"\": " + this.intMap.get( stateVal ) );
|
||||
|
||||
}
|
||||
|
||||
iterator = this.infoMap.keySet().iterator();
|
||||
|
||||
while ( iterator.hasNext() ) {
|
||||
|
||||
stateVal = iterator.next();
|
||||
|
||||
builder.append( ",\""+ stateVal +"\": \"" + this.infoMap.get( stateVal ) + "\"" );
|
||||
|
||||
}
|
||||
|
||||
builder.append( ", list: [" );
|
||||
|
||||
|
||||
iterator = this.stateList.iterator();
|
||||
|
||||
while ( iterator.hasNext() ) {
|
||||
|
||||
builder.append( iterator.next() + "," );
|
||||
|
||||
}
|
||||
|
||||
if ( this.stateList.size() > 0 ) {
|
||||
builder.deleteCharAt( builder.length() - 1 );
|
||||
}
|
||||
|
||||
builder.append( " ]}" );
|
||||
|
||||
return Encoder.toUnicode( builder.toString() );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putInfo(String name, long val) {
|
||||
this.intMap.put( name, val );
|
||||
}
|
||||
|
||||
}
|
||||
18
src/main/java/com/baidu/ueditor/define/State.java
Normal file
18
src/main/java/com/baidu/ueditor/define/State.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package com.baidu.ueditor.define;
|
||||
|
||||
/**
|
||||
* 处理状态接口
|
||||
* @author hancong03@baidu.com
|
||||
*
|
||||
*/
|
||||
public interface State {
|
||||
|
||||
public boolean isSuccess();
|
||||
|
||||
public void putInfo(String name, String val);
|
||||
|
||||
public void putInfo(String name, long val);
|
||||
|
||||
public String toJSONString();
|
||||
|
||||
}
|
||||
112
src/main/java/com/baidu/ueditor/hunter/FileManager.java
Normal file
112
src/main/java/com/baidu/ueditor/hunter/FileManager.java
Normal file
@@ -0,0 +1,112 @@
|
||||
package com.baidu.ueditor.hunter;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import com.baidu.ueditor.PathFormat;
|
||||
import com.baidu.ueditor.define.AppInfo;
|
||||
import com.baidu.ueditor.define.BaseState;
|
||||
import com.baidu.ueditor.define.MultiState;
|
||||
import com.baidu.ueditor.define.State;
|
||||
|
||||
public class FileManager {
|
||||
|
||||
private String dir = null;
|
||||
private String rootPath = null;
|
||||
private String[] allowFiles = null;
|
||||
private int count = 0;
|
||||
|
||||
public FileManager ( Map<String, Object> conf ) {
|
||||
|
||||
this.rootPath = (String)conf.get( "rootPath" );
|
||||
this.dir = this.rootPath + (String)conf.get( "dir" );
|
||||
this.allowFiles = this.getAllowFiles( conf.get("allowFiles") );
|
||||
this.count = (Integer)conf.get( "count" );
|
||||
|
||||
}
|
||||
|
||||
public State listFile ( int index ) {
|
||||
|
||||
File dir = new File( this.dir );
|
||||
State state = null;
|
||||
|
||||
if ( !dir.exists() ) {
|
||||
return new BaseState( false, AppInfo.NOT_EXIST );
|
||||
}
|
||||
|
||||
if ( !dir.isDirectory() ) {
|
||||
return new BaseState( false, AppInfo.NOT_DIRECTORY );
|
||||
}
|
||||
|
||||
Collection<File> list = FileUtils.listFiles( dir, this.allowFiles, true );
|
||||
|
||||
if ( index < 0 || index > list.size() ) {
|
||||
state = new MultiState( true );
|
||||
} else {
|
||||
Object[] fileList = Arrays.copyOfRange( list.toArray(), index, index + this.count );
|
||||
state = this.getState( fileList );
|
||||
}
|
||||
|
||||
state.putInfo( "start", index );
|
||||
state.putInfo( "total", list.size() );
|
||||
|
||||
return state;
|
||||
|
||||
}
|
||||
|
||||
private State getState ( Object[] files ) {
|
||||
|
||||
MultiState state = new MultiState( true );
|
||||
BaseState fileState = null;
|
||||
|
||||
File file = null;
|
||||
|
||||
for ( Object obj : files ) {
|
||||
if ( obj == null ) {
|
||||
break;
|
||||
}
|
||||
file = (File)obj;
|
||||
fileState = new BaseState( true );
|
||||
fileState.putInfo( "url", PathFormat.format( this.getPath( file ) ) );
|
||||
state.addState( fileState );
|
||||
}
|
||||
|
||||
return state;
|
||||
|
||||
}
|
||||
|
||||
private String getPath ( File file ) {
|
||||
|
||||
String path = file.getAbsolutePath();
|
||||
|
||||
return path.replace( this.rootPath, "/" );
|
||||
|
||||
}
|
||||
|
||||
private String[] getAllowFiles ( Object fileExt ) {
|
||||
|
||||
String[] exts = null;
|
||||
String ext = null;
|
||||
|
||||
if ( fileExt == null ) {
|
||||
return new String[ 0 ];
|
||||
}
|
||||
|
||||
exts = (String[])fileExt;
|
||||
|
||||
for ( int i = 0, len = exts.length; i < len; i++ ) {
|
||||
|
||||
ext = exts[ i ];
|
||||
exts[ i ] = ext.replace( ".", "" );
|
||||
|
||||
}
|
||||
|
||||
return exts;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
144
src/main/java/com/baidu/ueditor/hunter/ImageHunter.java
Normal file
144
src/main/java/com/baidu/ueditor/hunter/ImageHunter.java
Normal file
@@ -0,0 +1,144 @@
|
||||
package com.baidu.ueditor.hunter;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.baidu.ueditor.PathFormat;
|
||||
import com.baidu.ueditor.define.AppInfo;
|
||||
import com.baidu.ueditor.define.BaseState;
|
||||
import com.baidu.ueditor.define.MIMEType;
|
||||
import com.baidu.ueditor.define.MultiState;
|
||||
import com.baidu.ueditor.define.State;
|
||||
import com.baidu.ueditor.upload.StorageManager;
|
||||
|
||||
/**
|
||||
* 图片抓取器
|
||||
* @author hancong03@baidu.com
|
||||
*
|
||||
*/
|
||||
public class ImageHunter {
|
||||
|
||||
private String filename = null;
|
||||
private String savePath = null;
|
||||
private String rootPath = null;
|
||||
private List<String> allowTypes = null;
|
||||
private long maxSize = -1;
|
||||
|
||||
private List<String> filters = null;
|
||||
|
||||
public ImageHunter ( Map<String, Object> conf ) {
|
||||
|
||||
this.filename = (String)conf.get( "filename" );
|
||||
this.savePath = (String)conf.get( "savePath" );
|
||||
this.rootPath = (String)conf.get( "rootPath" );
|
||||
this.maxSize = (Long)conf.get( "maxSize" );
|
||||
this.allowTypes = Arrays.asList( (String[])conf.get( "allowFiles" ) );
|
||||
this.filters = Arrays.asList( (String[])conf.get( "filter" ) );
|
||||
|
||||
}
|
||||
|
||||
public State capture ( String[] list ) {
|
||||
|
||||
MultiState state = new MultiState( true );
|
||||
|
||||
for ( String source : list ) {
|
||||
state.addState( captureRemoteData( source ) );
|
||||
}
|
||||
|
||||
return state;
|
||||
|
||||
}
|
||||
|
||||
public State captureRemoteData ( String urlStr ) {
|
||||
|
||||
HttpURLConnection connection = null;
|
||||
URL url = null;
|
||||
String suffix = null;
|
||||
|
||||
try {
|
||||
url = new URL( urlStr );
|
||||
|
||||
if ( !validHost( url.getHost() ) ) {
|
||||
return new BaseState( false, AppInfo.PREVENT_HOST );
|
||||
}
|
||||
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
connection.setInstanceFollowRedirects( true );
|
||||
connection.setUseCaches( true );
|
||||
|
||||
if ( !validContentState( connection.getResponseCode() ) ) {
|
||||
return new BaseState( false, AppInfo.CONNECTION_ERROR );
|
||||
}
|
||||
|
||||
suffix = MIMEType.getSuffix( connection.getContentType() );
|
||||
|
||||
if ( !validFileType( suffix ) ) {
|
||||
return new BaseState( false, AppInfo.NOT_ALLOW_FILE_TYPE );
|
||||
}
|
||||
|
||||
if ( !validFileSize( connection.getContentLength() ) ) {
|
||||
return new BaseState( false, AppInfo.MAX_SIZE );
|
||||
}
|
||||
|
||||
String savePath = this.getPath( this.savePath, this.filename, suffix );
|
||||
String physicalPath = this.rootPath + savePath;
|
||||
|
||||
State state = StorageManager.saveFileByInputStream( connection.getInputStream(), physicalPath );
|
||||
|
||||
if ( state.isSuccess() ) {
|
||||
state.putInfo( "url", PathFormat.format( savePath ) );
|
||||
state.putInfo( "source", urlStr );
|
||||
}
|
||||
|
||||
return state;
|
||||
|
||||
} catch ( Exception e ) {
|
||||
return new BaseState( false, AppInfo.REMOTE_FAIL );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String getPath ( String savePath, String filename, String suffix ) {
|
||||
|
||||
return PathFormat.parse( savePath + suffix, filename );
|
||||
|
||||
}
|
||||
|
||||
private boolean validHost ( String hostname ) {
|
||||
try {
|
||||
InetAddress ip = InetAddress.getByName(hostname);
|
||||
|
||||
if (ip.isSiteLocalAddress()) {
|
||||
return false;
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !filters.contains( hostname );
|
||||
|
||||
}
|
||||
|
||||
private boolean validContentState ( int code ) {
|
||||
|
||||
return HttpURLConnection.HTTP_OK == code;
|
||||
|
||||
}
|
||||
|
||||
private boolean validFileType ( String type ) {
|
||||
|
||||
return this.allowTypes.contains( type );
|
||||
|
||||
}
|
||||
|
||||
private boolean validFileSize ( int size ) {
|
||||
return size < this.maxSize;
|
||||
}
|
||||
|
||||
}
|
||||
52
src/main/java/com/baidu/ueditor/upload/Base64Uploader.java
Normal file
52
src/main/java/com/baidu/ueditor/upload/Base64Uploader.java
Normal file
@@ -0,0 +1,52 @@
|
||||
package com.baidu.ueditor.upload;
|
||||
|
||||
import com.baidu.ueditor.PathFormat;
|
||||
import com.baidu.ueditor.define.AppInfo;
|
||||
import com.baidu.ueditor.define.BaseState;
|
||||
import com.baidu.ueditor.define.FileType;
|
||||
import com.baidu.ueditor.define.State;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
public final class Base64Uploader {
|
||||
|
||||
public static State save(String content, Map<String, Object> conf) {
|
||||
|
||||
byte[] data = decode(content);
|
||||
|
||||
long maxSize = ((Long) conf.get("maxSize")).longValue();
|
||||
|
||||
if (!validSize(data, maxSize)) {
|
||||
return new BaseState(false, AppInfo.MAX_SIZE);
|
||||
}
|
||||
|
||||
String suffix = FileType.getSuffix("JPG");
|
||||
|
||||
String savePath = PathFormat.parse((String) conf.get("savePath"),
|
||||
(String) conf.get("filename"));
|
||||
|
||||
savePath = savePath + suffix;
|
||||
String physicalPath = (String) conf.get("rootPath") + savePath;
|
||||
|
||||
State storageState = StorageManager.saveBinaryFile(data, physicalPath);
|
||||
|
||||
if (storageState.isSuccess()) {
|
||||
storageState.putInfo("url", PathFormat.format(savePath));
|
||||
storageState.putInfo("type", suffix);
|
||||
storageState.putInfo("original", "");
|
||||
}
|
||||
|
||||
return storageState;
|
||||
}
|
||||
|
||||
private static byte[] decode(String content) {
|
||||
return Base64.decodeBase64(content);
|
||||
}
|
||||
|
||||
private static boolean validSize(byte[] data, long length) {
|
||||
return data.length <= length;
|
||||
}
|
||||
|
||||
}
|
||||
98
src/main/java/com/baidu/ueditor/upload/BinaryUploader.java
Normal file
98
src/main/java/com/baidu/ueditor/upload/BinaryUploader.java
Normal file
@@ -0,0 +1,98 @@
|
||||
package com.baidu.ueditor.upload;
|
||||
|
||||
import com.baidu.ueditor.PathFormat;
|
||||
import com.baidu.ueditor.define.AppInfo;
|
||||
import com.baidu.ueditor.define.BaseState;
|
||||
import com.baidu.ueditor.define.FileType;
|
||||
import com.baidu.ueditor.define.State;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.fileupload.FileItemIterator;
|
||||
import org.apache.commons.fileupload.FileItemStream;
|
||||
import org.apache.commons.fileupload.FileUploadException;
|
||||
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
|
||||
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
||||
|
||||
public class BinaryUploader {
|
||||
|
||||
public static final State save(HttpServletRequest request,
|
||||
Map<String, Object> conf) {
|
||||
FileItemStream fileStream = null;
|
||||
boolean isAjaxUpload = request.getHeader( "X_Requested_With" ) != null;
|
||||
|
||||
if (!ServletFileUpload.isMultipartContent(request)) {
|
||||
return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT);
|
||||
}
|
||||
|
||||
ServletFileUpload upload = new ServletFileUpload(
|
||||
new DiskFileItemFactory());
|
||||
|
||||
if ( isAjaxUpload ) {
|
||||
upload.setHeaderEncoding( "UTF-8" );
|
||||
}
|
||||
|
||||
try {
|
||||
FileItemIterator iterator = upload.getItemIterator(request);
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
fileStream = iterator.next();
|
||||
|
||||
if (!fileStream.isFormField())
|
||||
break;
|
||||
fileStream = null;
|
||||
}
|
||||
|
||||
if (fileStream == null) {
|
||||
return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
|
||||
}
|
||||
|
||||
String savePath = (String) conf.get("savePath");
|
||||
String originFileName = fileStream.getName();
|
||||
String suffix = FileType.getSuffixByFilename(originFileName);
|
||||
|
||||
originFileName = originFileName.substring(0,
|
||||
originFileName.length() - suffix.length());
|
||||
savePath = savePath + suffix;
|
||||
|
||||
long maxSize = ((Long) conf.get("maxSize")).longValue();
|
||||
|
||||
if (!validType(suffix, (String[]) conf.get("allowFiles"))) {
|
||||
return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE);
|
||||
}
|
||||
|
||||
savePath = PathFormat.parse(savePath, originFileName);
|
||||
|
||||
String physicalPath = (String) conf.get("rootPath") + savePath;
|
||||
|
||||
InputStream is = fileStream.openStream();
|
||||
State storageState = StorageManager.saveFileByInputStream(is,
|
||||
physicalPath, maxSize);
|
||||
is.close();
|
||||
|
||||
if (storageState.isSuccess()) {
|
||||
storageState.putInfo("url", PathFormat.format(savePath));
|
||||
storageState.putInfo("type", suffix);
|
||||
storageState.putInfo("original", originFileName + suffix);
|
||||
}
|
||||
|
||||
return storageState;
|
||||
} catch (FileUploadException e) {
|
||||
return new BaseState(false, AppInfo.PARSE_REQUEST_ERROR);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
return new BaseState(false, AppInfo.IO_ERROR);
|
||||
}
|
||||
|
||||
private static boolean validType(String type, String[] allowTypes) {
|
||||
List<String> list = Arrays.asList(allowTypes);
|
||||
|
||||
return list.contains(type);
|
||||
}
|
||||
}
|
||||
155
src/main/java/com/baidu/ueditor/upload/StorageManager.java
Normal file
155
src/main/java/com/baidu/ueditor/upload/StorageManager.java
Normal file
@@ -0,0 +1,155 @@
|
||||
package com.baidu.ueditor.upload;
|
||||
|
||||
import com.baidu.ueditor.define.AppInfo;
|
||||
import com.baidu.ueditor.define.BaseState;
|
||||
import com.baidu.ueditor.define.State;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
public class StorageManager {
|
||||
public static final int BUFFER_SIZE = 8192;
|
||||
|
||||
public StorageManager() {
|
||||
}
|
||||
|
||||
public static State saveBinaryFile(byte[] data, String path) {
|
||||
File file = new File(path);
|
||||
|
||||
State state = valid(file);
|
||||
|
||||
if (!state.isSuccess()) {
|
||||
return state;
|
||||
}
|
||||
|
||||
try {
|
||||
BufferedOutputStream bos = new BufferedOutputStream(
|
||||
new FileOutputStream(file));
|
||||
bos.write(data);
|
||||
bos.flush();
|
||||
bos.close();
|
||||
} catch (IOException ioe) {
|
||||
return new BaseState(false, AppInfo.IO_ERROR);
|
||||
}
|
||||
|
||||
state = new BaseState(true, file.getAbsolutePath());
|
||||
state.putInfo( "size", data.length );
|
||||
state.putInfo( "title", file.getName() );
|
||||
return state;
|
||||
}
|
||||
|
||||
public static State saveFileByInputStream(InputStream is, String path,
|
||||
long maxSize) {
|
||||
State state = null;
|
||||
|
||||
File tmpFile = getTmpFile();
|
||||
|
||||
byte[] dataBuf = new byte[ 2048 ];
|
||||
BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE);
|
||||
|
||||
try {
|
||||
BufferedOutputStream bos = new BufferedOutputStream(
|
||||
new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE);
|
||||
|
||||
int count = 0;
|
||||
while ((count = bis.read(dataBuf)) != -1) {
|
||||
bos.write(dataBuf, 0, count);
|
||||
}
|
||||
bos.flush();
|
||||
bos.close();
|
||||
|
||||
if (tmpFile.length() > maxSize) {
|
||||
tmpFile.delete();
|
||||
return new BaseState(false, AppInfo.MAX_SIZE);
|
||||
}
|
||||
|
||||
state = saveTmpFile(tmpFile, path);
|
||||
|
||||
if (!state.isSuccess()) {
|
||||
tmpFile.delete();
|
||||
}
|
||||
|
||||
return state;
|
||||
|
||||
} catch (IOException e) {
|
||||
}
|
||||
return new BaseState(false, AppInfo.IO_ERROR);
|
||||
}
|
||||
|
||||
public static State saveFileByInputStream(InputStream is, String path) {
|
||||
State state = null;
|
||||
|
||||
File tmpFile = getTmpFile();
|
||||
|
||||
byte[] dataBuf = new byte[ 2048 ];
|
||||
BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE);
|
||||
|
||||
try {
|
||||
BufferedOutputStream bos = new BufferedOutputStream(
|
||||
new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE);
|
||||
|
||||
int count = 0;
|
||||
while ((count = bis.read(dataBuf)) != -1) {
|
||||
bos.write(dataBuf, 0, count);
|
||||
}
|
||||
bos.flush();
|
||||
bos.close();
|
||||
|
||||
state = saveTmpFile(tmpFile, path);
|
||||
|
||||
if (!state.isSuccess()) {
|
||||
tmpFile.delete();
|
||||
}
|
||||
|
||||
return state;
|
||||
} catch (IOException e) {
|
||||
}
|
||||
return new BaseState(false, AppInfo.IO_ERROR);
|
||||
}
|
||||
|
||||
private static File getTmpFile() {
|
||||
File tmpDir = FileUtils.getTempDirectory();
|
||||
String tmpFileName = (Math.random() * 10000 + "").replace(".", "");
|
||||
return new File(tmpDir, tmpFileName);
|
||||
}
|
||||
|
||||
private static State saveTmpFile(File tmpFile, String path) {
|
||||
State state = null;
|
||||
File targetFile = new File(path);
|
||||
|
||||
if (targetFile.canWrite()) {
|
||||
return new BaseState(false, AppInfo.PERMISSION_DENIED);
|
||||
}
|
||||
try {
|
||||
FileUtils.moveFile(tmpFile, targetFile);
|
||||
} catch (IOException e) {
|
||||
return new BaseState(false, AppInfo.IO_ERROR);
|
||||
}
|
||||
|
||||
state = new BaseState(true);
|
||||
state.putInfo( "size", targetFile.length() );
|
||||
state.putInfo( "title", targetFile.getName() );
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
private static State valid(File file) {
|
||||
File parentPath = file.getParentFile();
|
||||
|
||||
if ((!parentPath.exists()) && (!parentPath.mkdirs())) {
|
||||
return new BaseState(false, AppInfo.FAILED_CREATE_FILE);
|
||||
}
|
||||
|
||||
if (!parentPath.canWrite()) {
|
||||
return new BaseState(false, AppInfo.PERMISSION_DENIED);
|
||||
}
|
||||
|
||||
return new BaseState(true);
|
||||
}
|
||||
}
|
||||
29
src/main/java/com/baidu/ueditor/upload/Uploader.java
Normal file
29
src/main/java/com/baidu/ueditor/upload/Uploader.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.baidu.ueditor.upload;
|
||||
|
||||
import com.baidu.ueditor.define.State;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
public class Uploader {
|
||||
private HttpServletRequest request = null;
|
||||
private Map<String, Object> conf = null;
|
||||
|
||||
public Uploader(HttpServletRequest request, Map<String, Object> conf) {
|
||||
this.request = request;
|
||||
this.conf = conf;
|
||||
}
|
||||
|
||||
public final State doExec() {
|
||||
String filedName = (String) this.conf.get("fieldName");
|
||||
State state = null;
|
||||
|
||||
if ("true".equals(this.conf.get("isBase64"))) {
|
||||
state = Base64Uploader.save(this.request.getParameter(filedName),
|
||||
this.conf);
|
||||
} else {
|
||||
state = BinaryUploader.save(this.request, this.conf);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
11
src/main/java/com/peanut/PeanutBookApplication.java
Normal file
11
src/main/java/com/peanut/PeanutBookApplication.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package com.peanut;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class PeanutBookApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(PeanutBookApplication.class, args);
|
||||
}
|
||||
}
|
||||
342
src/main/java/com/peanut/common/Interface/KdApiEOrder.java
Normal file
342
src/main/java/com/peanut/common/Interface/KdApiEOrder.java
Normal 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-必填(Required),O-可选(Optional),C-报文中该参数在一定条件下可选(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-必填(Required),O-可选(Optional),C-报文中该参数在一定条件下可选(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-必填(Required),O-可选(Optional),C-报文中该参数在一定条件下可选(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-必填(Required),O-可选(Optional),C-报文中该参数在一定条件下可选(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 "";
|
||||
}
|
||||
|
||||
}
|
||||
28
src/main/java/com/peanut/common/annotation/SysLog.java
Normal file
28
src/main/java/com/peanut/common/annotation/SysLog.java
Normal 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 "";
|
||||
}
|
||||
46
src/main/java/com/peanut/common/aspect/RedisAspect.java
Normal file
46
src/main/java/com/peanut/common/aspect/RedisAspect.java
Normal 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;
|
||||
}
|
||||
}
|
||||
101
src/main/java/com/peanut/common/aspect/SysLogAspect.java
Normal file
101
src/main/java/com/peanut/common/aspect/SysLogAspect.java
Normal 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);
|
||||
}
|
||||
}
|
||||
61
src/main/java/com/peanut/common/exception/RRException.java
Normal file
61
src/main/java/com/peanut/common/exception/RRException.java
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
71
src/main/java/com/peanut/common/utils/BaiduVoicesUtils.java
Normal file
71
src/main/java/com/peanut/common/utils/BaiduVoicesUtils.java
Normal 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;
|
||||
}
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
21
src/main/java/com/peanut/common/utils/ConfigConstant.java
Normal file
21
src/main/java/com/peanut/common/utils/ConfigConstant.java
Normal 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";
|
||||
}
|
||||
92
src/main/java/com/peanut/common/utils/ConnUtil.java
Normal file
92
src/main/java/com/peanut/common/utils/ConnUtil.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
152
src/main/java/com/peanut/common/utils/Constant.java
Normal file
152
src/main/java/com/peanut/common/utils/Constant.java
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
27
src/main/java/com/peanut/common/utils/CopyUtils.java
Normal file
27
src/main/java/com/peanut/common/utils/CopyUtils.java
Normal 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));
|
||||
}
|
||||
}
|
||||
37
src/main/java/com/peanut/common/utils/DateUtil.java
Normal file
37
src/main/java/com/peanut/common/utils/DateUtil.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
166
src/main/java/com/peanut/common/utils/DateUtils.java
Normal file
166
src/main/java/com/peanut/common/utils/DateUtils.java
Normal 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();
|
||||
}
|
||||
}
|
||||
8
src/main/java/com/peanut/common/utils/DemoException.java
Normal file
8
src/main/java/com/peanut/common/utils/DemoException.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
|
||||
public class DemoException extends Exception {
|
||||
public DemoException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
71
src/main/java/com/peanut/common/utils/FileDownloadUtil.java
Normal file
71
src/main/java/com/peanut/common/utils/FileDownloadUtil.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
449
src/main/java/com/peanut/common/utils/HttpClientUtils.java
Normal file
449
src/main/java/com/peanut/common/utils/HttpClientUtils.java
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
32
src/main/java/com/peanut/common/utils/HttpContextUtils.java
Normal file
32
src/main/java/com/peanut/common/utils/HttpContextUtils.java
Normal 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");
|
||||
}
|
||||
}
|
||||
64
src/main/java/com/peanut/common/utils/IPUtils.java
Normal file
64
src/main/java/com/peanut/common/utils/IPUtils.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
67
src/main/java/com/peanut/common/utils/KdUtils.java
Normal file
67
src/main/java/com/peanut/common/utils/KdUtils.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
45
src/main/java/com/peanut/common/utils/MD5Util.java
Normal file
45
src/main/java/com/peanut/common/utils/MD5Util.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
255
src/main/java/com/peanut/common/utils/MD5Utils.java
Normal file
255
src/main/java/com/peanut/common/utils/MD5Utils.java
Normal 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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
26
src/main/java/com/peanut/common/utils/MapUtils.java
Normal file
26
src/main/java/com/peanut/common/utils/MapUtils.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
115
src/main/java/com/peanut/common/utils/OrderUtils.java
Normal file
115
src/main/java/com/peanut/common/utils/OrderUtils.java
Normal 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);
|
||||
}
|
||||
}
|
||||
110
src/main/java/com/peanut/common/utils/PageUtils.java
Normal file
110
src/main/java/com/peanut/common/utils/PageUtils.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
77
src/main/java/com/peanut/common/utils/Query.java
Normal file
77
src/main/java/com/peanut/common/utils/Query.java
Normal 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;
|
||||
}
|
||||
}
|
||||
64
src/main/java/com/peanut/common/utils/R.java
Normal file
64
src/main/java/com/peanut/common/utils/R.java
Normal 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;
|
||||
}
|
||||
}
|
||||
86
src/main/java/com/peanut/common/utils/ReadProvinceUtil.java
Normal file
86
src/main/java/com/peanut/common/utils/ReadProvinceUtil.java
Normal 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;
|
||||
}
|
||||
}
|
||||
21
src/main/java/com/peanut/common/utils/RedisKeys.java
Normal file
21
src/main/java/com/peanut/common/utils/RedisKeys.java
Normal 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;
|
||||
}
|
||||
}
|
||||
99
src/main/java/com/peanut/common/utils/RedisUtils.java
Normal file
99
src/main/java/com/peanut/common/utils/RedisUtils.java
Normal 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);
|
||||
}
|
||||
}
|
||||
61
src/main/java/com/peanut/common/utils/ShiroUtils.java
Normal file
61
src/main/java/com/peanut/common/utils/ShiroUtils.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
122
src/main/java/com/peanut/common/utils/TokenHolder.java
Normal file
122
src/main/java/com/peanut/common/utils/TokenHolder.java
Normal 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的url,http可以改为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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token,refresh 方法后调用有效
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
38
src/main/java/com/peanut/common/utils/UEditorUpload.java
Normal file
38
src/main/java/com/peanut/common/utils/UEditorUpload.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
32
src/main/java/com/peanut/common/validator/Assert.java
Normal file
32
src/main/java/com/peanut/common/validator/Assert.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
21
src/main/java/com/peanut/common/validator/group/Group.java
Normal file
21
src/main/java/com/peanut/common/validator/group/Group.java
Normal 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 {
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
530
src/main/java/com/peanut/common/xss/HTMLFilter.java
Normal file
530
src/main/java/com/peanut/common/xss/HTMLFilter.java
Normal 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, "&", result);
|
||||
result = regexReplace(P_QUOTE, """, result);
|
||||
result = regexReplace(P_LEFT_ARROW, "<", result);
|
||||
result = regexReplace(P_RIGHT_ARROW, ">", 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, "<$1", s);
|
||||
s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", 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, """, 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
|
||||
: "&" + 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));
|
||||
}
|
||||
}
|
||||
50
src/main/java/com/peanut/common/xss/SQLFilter.java
Normal file
50
src/main/java/com/peanut/common/xss/SQLFilter.java
Normal 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;
|
||||
}
|
||||
}
|
||||
37
src/main/java/com/peanut/common/xss/XssFilter.java
Normal file
37
src/main/java/com/peanut/common/xss/XssFilter.java
Normal 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() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
26
src/main/java/com/peanut/config/CorsConfig.java
Normal file
26
src/main/java/com/peanut/config/CorsConfig.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class CorsConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedOriginPatterns("*")
|
||||
.allowCredentials(true)
|
||||
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
|
||||
.maxAge(3600);
|
||||
}
|
||||
}
|
||||
185
src/main/java/com/peanut/config/DelayQueueConfig.java
Normal file
185
src/main/java/com/peanut/config/DelayQueueConfig.java
Normal file
@@ -0,0 +1,185 @@
|
||||
package com.peanut.config;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.core.*;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* RabbitMq 延时队列实现
|
||||
* @author AnYuan
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class DelayQueueConfig {
|
||||
|
||||
/**
|
||||
* 延迟队列
|
||||
*/
|
||||
public static final String DELAY_EXCHANGE = "delay.queue.business.exchange";
|
||||
public static final String DELAY_QUEUE = "delay.queue.business.queue";
|
||||
public static final String DELAY_QUEUE_ROUTING_KEY = "delay.queue.business.queue.routingKey";
|
||||
|
||||
|
||||
/**
|
||||
* 订单队列
|
||||
*/
|
||||
public static final String ORDER_EVENT_EXCHANGE = "order-event-exchange";
|
||||
public static final String ORDER_DELAY_QUEUE = "order.delay.queue";
|
||||
public static final String ORDER_RELEASE_QUEUE = "order.release.queue";
|
||||
public static final String ORDER_QUEUE_ROUTING_KEY = "order.release.order";
|
||||
|
||||
/**
|
||||
* 死信队列
|
||||
*/
|
||||
public static final String DEAD_LETTER_EXCHANGE = "delay.queue.deadLetter.exchange";
|
||||
public static final String DEAD_LETTER_QUEUE_ROUTING_KEY = "delay.queue.deadLetter.delay_10s.routingKey";
|
||||
public static final String DEAD_LETTER_QUEUE = "delay.queue.deadLetter.queue";
|
||||
|
||||
|
||||
/**
|
||||
* 快递队列
|
||||
*/
|
||||
public static final String FMS_QUEUE= "fms.queue";
|
||||
public static final String FMS_EXCHANGE = "fms.exchange";
|
||||
public static final String FMS_ROUTING_KEY = "fms.routing.key";
|
||||
|
||||
|
||||
/**
|
||||
* 声明 死信交换机
|
||||
* @return deadLetterExchange
|
||||
*/
|
||||
@Bean
|
||||
public DirectExchange deadLetterExchange() {
|
||||
return new DirectExchange(DEAD_LETTER_EXCHANGE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 声明 订单交换机
|
||||
* @return deadLetterExchange
|
||||
*/
|
||||
@Bean
|
||||
public Exchange orderEventExchange() {
|
||||
return new TopicExchange(ORDER_EVENT_EXCHANGE,true,false);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public Queue orderDelayQueue() {
|
||||
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
|
||||
// 队列绑定DLX参数(关键一步)
|
||||
map.put("x-dead-letter-exchange", ORDER_EVENT_EXCHANGE);
|
||||
// 队列绑定 死信RoutingKey参数
|
||||
map.put("x-dead-letter-routing-key", ORDER_QUEUE_ROUTING_KEY);
|
||||
|
||||
map.put("x-message-ttl", 60000);
|
||||
|
||||
Queue queue = new Queue(ORDER_DELAY_QUEUE, true, false, false,map);
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public Queue orderReleaseOrderQueue() {
|
||||
|
||||
Queue queue = new Queue(ORDER_RELEASE_QUEUE, true, false, false);
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 声明 死信队列 用于接收死信消息
|
||||
* @return deadLetterQueueA
|
||||
*/
|
||||
@Bean
|
||||
public Queue deadLetterQueueA() {
|
||||
return new Queue(DEAD_LETTER_QUEUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 死信队列 绑定到死信交换机上
|
||||
* @return deadLetterBindingA
|
||||
*/
|
||||
@Bean
|
||||
public Binding deadLetterBindingA() {
|
||||
return BindingBuilder
|
||||
.bind(deadLetterQueueA())
|
||||
.to(deadLetterExchange())
|
||||
.with(DEAD_LETTER_QUEUE_ROUTING_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 声明 延时交换机
|
||||
* @return delayExchange
|
||||
*/
|
||||
@Bean
|
||||
public DirectExchange directExchange() {
|
||||
return new DirectExchange(DELAY_EXCHANGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 延时队列 绑定参数
|
||||
* @return Queue
|
||||
*/
|
||||
@Bean
|
||||
public Queue delayQueueA() {
|
||||
Map<String, Object> maps = Maps.newHashMapWithExpectedSize(3);
|
||||
// 队列绑定DLX参数(关键一步)
|
||||
maps.put("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE);
|
||||
// 队列绑定 死信RoutingKey参数
|
||||
maps.put("x-dead-letter-routing-key", DEAD_LETTER_QUEUE_ROUTING_KEY);
|
||||
// 消息过期采用第一种设置队列的 ttl 时间,消息过期时间全部相同。 单位:毫秒,这里设置为8秒
|
||||
// maps.put("x-message-ttl", 8000);
|
||||
return QueueBuilder.durable(DELAY_QUEUE).withArguments(maps).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 延时队列 绑定到延时交换机上面
|
||||
* @return delayBindingA
|
||||
*/
|
||||
@Bean
|
||||
public Binding delayBindingA() {
|
||||
return BindingBuilder
|
||||
.bind(delayQueueA())
|
||||
.to(directExchange())
|
||||
.with(DELAY_QUEUE_ROUTING_KEY);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public Binding orderCreateOrderBingding(){
|
||||
return new Binding(ORDER_DELAY_QUEUE, Binding.DestinationType.QUEUE,ORDER_EVENT_EXCHANGE,"order.create.order",null);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding orderReleaseOrderBingding(){
|
||||
return new Binding(ORDER_RELEASE_QUEUE, Binding.DestinationType.QUEUE,ORDER_EVENT_EXCHANGE,ORDER_QUEUE_ROUTING_KEY,null);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public Queue FMSQueue(){
|
||||
return new Queue(FMS_QUEUE);
|
||||
}
|
||||
@Bean
|
||||
TopicExchange FMSExchange() {
|
||||
return new TopicExchange(FMS_EXCHANGE);
|
||||
}
|
||||
|
||||
Binding bindingExchangeMessage(){
|
||||
return BindingBuilder.bind(FMSQueue()).to(FMSExchange()).with(FMS_ROUTING_KEY);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
49
src/main/java/com/peanut/config/FilterConfig.java
Normal file
49
src/main/java/com/peanut/config/FilterConfig.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.config;
|
||||
|
||||
import com.peanut.common.xss.XssFilter;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.filter.DelegatingFilterProxy;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
|
||||
/**
|
||||
* Filter配置
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Configuration
|
||||
public class FilterConfig {
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean shiroFilterRegistration() {
|
||||
FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||
registration.setFilter(new DelegatingFilterProxy("shiroFilter"));
|
||||
//该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理
|
||||
registration.addInitParameter("targetFilterLifecycle", "true");
|
||||
registration.setEnabled(true);
|
||||
registration.setOrder(Integer.MAX_VALUE - 1);
|
||||
registration.addUrlPatterns("/*");
|
||||
return registration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean xssFilterRegistration() {
|
||||
FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||
registration.setDispatcherTypes(DispatcherType.REQUEST);
|
||||
registration.setFilter(new XssFilter());
|
||||
registration.addUrlPatterns("/*");
|
||||
registration.setName("xssFilter");
|
||||
registration.setOrder(Integer.MAX_VALUE);
|
||||
return registration;
|
||||
}
|
||||
}
|
||||
39
src/main/java/com/peanut/config/KaptchaConfig.java
Normal file
39
src/main/java/com/peanut/config/KaptchaConfig.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.config;
|
||||
|
||||
import com.google.code.kaptcha.impl.DefaultKaptcha;
|
||||
import com.google.code.kaptcha.util.Config;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
/**
|
||||
* 生成验证码配置
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Configuration
|
||||
public class KaptchaConfig {
|
||||
|
||||
@Bean
|
||||
public DefaultKaptcha producer() {
|
||||
Properties properties = new Properties();
|
||||
properties.put("kaptcha.border", "no");
|
||||
properties.put("kaptcha.textproducer.font.color", "black");
|
||||
properties.put("kaptcha.textproducer.char.space", "5");
|
||||
properties.put("kaptcha.textproducer.font.names", "Arial,Courier,cmr10,宋体,楷体,微软雅黑");
|
||||
Config config = new Config(properties);
|
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||
defaultKaptcha.setConfig(config);
|
||||
return defaultKaptcha;
|
||||
}
|
||||
}
|
||||
19
src/main/java/com/peanut/config/MyRedissonConfig.java
Normal file
19
src/main/java/com/peanut/config/MyRedissonConfig.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.peanut.config;
|
||||
|
||||
import org.redisson.Redisson;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.redisson.config.Config;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class MyRedissonConfig {
|
||||
|
||||
@Bean
|
||||
public RedissonClient redissonClient() {
|
||||
Config config = new Config();
|
||||
config.useSingleServer().setAddress("redis://59.110.212.44:6379").setPassword("Jgll2015");
|
||||
RedissonClient redissonClient = Redisson.create(config);
|
||||
return redissonClient;
|
||||
}
|
||||
}
|
||||
31
src/main/java/com/peanut/config/MybatisPlusConfig.java
Normal file
31
src/main/java/com/peanut/config/MybatisPlusConfig.java
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.config;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* mybatis-plus配置
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Configuration
|
||||
public class MybatisPlusConfig {
|
||||
|
||||
/**
|
||||
* 分页插件
|
||||
*/
|
||||
@Bean
|
||||
public PaginationInterceptor paginationInterceptor() {
|
||||
return new PaginationInterceptor();
|
||||
}
|
||||
|
||||
}
|
||||
63
src/main/java/com/peanut/config/RedisConfig.java
Normal file
63
src/main/java/com/peanut/config/RedisConfig.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.*;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* Redis配置
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
@Autowired
|
||||
private RedisConnectionFactory factory;
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate() {
|
||||
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
|
||||
redisTemplate.setValueSerializer(new StringRedisSerializer());
|
||||
redisTemplate.setConnectionFactory(factory);
|
||||
return redisTemplate;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
|
||||
return redisTemplate.opsForHash();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
|
||||
return redisTemplate.opsForValue();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
|
||||
return redisTemplate.opsForList();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
|
||||
return redisTemplate.opsForSet();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
|
||||
return redisTemplate.opsForZSet();
|
||||
}
|
||||
}
|
||||
12
src/main/java/com/peanut/config/ScheduledConfig.java
Normal file
12
src/main/java/com/peanut/config/ScheduledConfig.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package com.peanut.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@EnableAsync
|
||||
@Configuration
|
||||
@EnableScheduling
|
||||
public class ScheduledConfig {
|
||||
|
||||
}
|
||||
88
src/main/java/com/peanut/config/ShiroConfig.java
Normal file
88
src/main/java/com/peanut/config/ShiroConfig.java
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.config;
|
||||
|
||||
import com.peanut.modules.sys.oauth2.OAuth2Filter;
|
||||
import com.peanut.modules.sys.oauth2.OAuth2Realm;
|
||||
import org.apache.shiro.mgt.SecurityManager;
|
||||
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
|
||||
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
||||
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
||||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Shiro配置
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Configuration
|
||||
public class ShiroConfig {
|
||||
|
||||
@Bean("securityManager")
|
||||
public SecurityManager securityManager(OAuth2Realm oAuth2Realm) {
|
||||
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
|
||||
securityManager.setRealm(oAuth2Realm);
|
||||
securityManager.setRememberMeManager(null);
|
||||
return securityManager;
|
||||
}
|
||||
|
||||
@Bean("shiroFilter")
|
||||
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
|
||||
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
|
||||
shiroFilter.setSecurityManager(securityManager);
|
||||
|
||||
//oauth过滤
|
||||
Map<String, Filter> filters = new HashMap<>();
|
||||
filters.put("oauth2", new OAuth2Filter());
|
||||
shiroFilter.setFilters(filters);
|
||||
|
||||
Map<String, String> filterMap = new LinkedHashMap<>();
|
||||
filterMap.put("/oss/**","anon");
|
||||
filterMap.put("/image/**","anon");
|
||||
filterMap.put("/book/book/listForWebsite","anon"); // 网站接口
|
||||
filterMap.put("/book/shopproduct/forWebList","anon"); // 网站接口
|
||||
filterMap.put("/pay/aliPay/notify","anon"); // 支付宝回调接口
|
||||
// filterMap.put("/book/bookchaptercontent/**","anon");
|
||||
filterMap.put("/book/user/**","anon");
|
||||
filterMap.put("/webjars/**", "anon");
|
||||
filterMap.put("/druid/**", "anon");
|
||||
filterMap.put("/app/**", "anon");
|
||||
filterMap.put("/sys/login", "anon");
|
||||
filterMap.put("/swagger/**", "anon");
|
||||
filterMap.put("/v2/api-docs", "anon");
|
||||
filterMap.put("/swagger-ui.html", "anon");
|
||||
filterMap.put("/swagger-resources/**", "anon");
|
||||
filterMap.put("/captcha.jpg", "anon");
|
||||
filterMap.put("/aaa.txt", "anon");
|
||||
filterMap.put("/**", "oauth2");
|
||||
shiroFilter.setFilterChainDefinitionMap(filterMap);
|
||||
|
||||
return shiroFilter;
|
||||
}
|
||||
|
||||
@Bean("lifecycleBeanPostProcessor")
|
||||
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
|
||||
return new LifecycleBeanPostProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
|
||||
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
|
||||
advisor.setSecurityManager(securityManager);
|
||||
return advisor;
|
||||
}
|
||||
|
||||
}
|
||||
61
src/main/java/com/peanut/config/SwaggerConfig.java
Normal file
61
src/main/java/com/peanut/config/SwaggerConfig.java
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.config;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
import springfox.documentation.service.ApiInfo;
|
||||
import springfox.documentation.service.ApiKey;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
|
||||
@Configuration
|
||||
@EnableSwagger2
|
||||
public class SwaggerConfig implements WebMvcConfigurer {
|
||||
|
||||
@Bean
|
||||
public Docket createRestApi() {
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
.apiInfo(apiInfo())
|
||||
.select()
|
||||
//加了ApiOperation注解的类,才生成接口文档
|
||||
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
||||
//包下的类,才生成接口文档
|
||||
//.apis(RequestHandlerSelectors.basePackage("io.renren.controller"))
|
||||
.paths(PathSelectors.any())
|
||||
.build()
|
||||
.securitySchemes(security());
|
||||
}
|
||||
|
||||
private ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder()
|
||||
.title("人人开源")
|
||||
.description("renren-fast文档")
|
||||
.termsOfServiceUrl("https://www.renren.io")
|
||||
.version("3.0.0")
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<ApiKey> security() {
|
||||
return newArrayList(
|
||||
new ApiKey("token", "token", "header")
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.datasource.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 多数据源注解
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
public @interface DataSource {
|
||||
String value() default "";
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.datasource.aspect;
|
||||
|
||||
|
||||
import com.peanut.datasource.annotation.DataSource;
|
||||
import com.peanut.datasource.config.DynamicContextHolder;
|
||||
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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 多数据源,切面处理类
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class DataSourceAspect {
|
||||
protected Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Pointcut("@annotation(com.peanut.datasource.annotation.DataSource) " +
|
||||
"|| @within(com.peanut.datasource.annotation.DataSource)")
|
||||
public void dataSourcePointCut() {
|
||||
|
||||
}
|
||||
|
||||
@Around("dataSourcePointCut()")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||
Class targetClass = point.getTarget().getClass();
|
||||
Method method = signature.getMethod();
|
||||
|
||||
DataSource targetDataSource = (DataSource)targetClass.getAnnotation(DataSource.class);
|
||||
DataSource methodDataSource = method.getAnnotation(DataSource.class);
|
||||
if(targetDataSource != null || methodDataSource != null){
|
||||
String value;
|
||||
if(methodDataSource != null){
|
||||
value = methodDataSource.value();
|
||||
}else {
|
||||
value = targetDataSource.value();
|
||||
}
|
||||
|
||||
DynamicContextHolder.push(value);
|
||||
logger.debug("set datasource is {}", value);
|
||||
}
|
||||
|
||||
try {
|
||||
return point.proceed();
|
||||
} finally {
|
||||
DynamicContextHolder.poll();
|
||||
logger.debug("clean datasource");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.datasource.config;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
/**
|
||||
* 多数据源上下文
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class DynamicContextHolder {
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final ThreadLocal<Deque<String>> CONTEXT_HOLDER = new ThreadLocal() {
|
||||
@Override
|
||||
protected Object initialValue() {
|
||||
return new ArrayDeque();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获得当前线程数据源
|
||||
*
|
||||
* @return 数据源名称
|
||||
*/
|
||||
public static String peek() {
|
||||
return CONTEXT_HOLDER.get().peek();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前线程数据源
|
||||
*
|
||||
* @param dataSource 数据源名称
|
||||
*/
|
||||
public static void push(String dataSource) {
|
||||
CONTEXT_HOLDER.get().push(dataSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空当前线程数据源
|
||||
*/
|
||||
public static void poll() {
|
||||
Deque<String> deque = CONTEXT_HOLDER.get();
|
||||
deque.poll();
|
||||
if (deque.isEmpty()) {
|
||||
CONTEXT_HOLDER.remove();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.datasource.config;
|
||||
|
||||
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
|
||||
|
||||
/**
|
||||
* 多数据源
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class DynamicDataSource extends AbstractRoutingDataSource {
|
||||
|
||||
@Override
|
||||
protected Object determineCurrentLookupKey() {
|
||||
return DynamicContextHolder.peek();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.datasource.config;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.peanut.datasource.properties.DataSourceProperties;
|
||||
import com.peanut.datasource.properties.DynamicDataSourceProperties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 配置多数据源
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(DynamicDataSourceProperties.class)
|
||||
public class DynamicDataSourceConfig {
|
||||
@Autowired
|
||||
private DynamicDataSourceProperties properties;
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "spring.datasource.druid")
|
||||
public DataSourceProperties dataSourceProperties() {
|
||||
return new DataSourceProperties();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DynamicDataSource dynamicDataSource(DataSourceProperties dataSourceProperties) {
|
||||
DynamicDataSource dynamicDataSource = new DynamicDataSource();
|
||||
dynamicDataSource.setTargetDataSources(getDynamicDataSource());
|
||||
|
||||
//默认数据源
|
||||
DruidDataSource defaultDataSource = DynamicDataSourceFactory.buildDruidDataSource(dataSourceProperties);
|
||||
dynamicDataSource.setDefaultTargetDataSource(defaultDataSource);
|
||||
|
||||
return dynamicDataSource;
|
||||
}
|
||||
|
||||
private Map<Object, Object> getDynamicDataSource(){
|
||||
Map<String, DataSourceProperties> dataSourcePropertiesMap = properties.getDatasource();
|
||||
Map<Object, Object> targetDataSources = new HashMap<>(dataSourcePropertiesMap.size());
|
||||
dataSourcePropertiesMap.forEach((k, v) -> {
|
||||
DruidDataSource druidDataSource = DynamicDataSourceFactory.buildDruidDataSource(v);
|
||||
targetDataSources.put(k, druidDataSource);
|
||||
});
|
||||
|
||||
return targetDataSources;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.datasource.config;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.peanut.datasource.properties.DataSourceProperties;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* DruidDataSource
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class DynamicDataSourceFactory {
|
||||
|
||||
public static DruidDataSource buildDruidDataSource(DataSourceProperties properties) {
|
||||
DruidDataSource druidDataSource = new DruidDataSource();
|
||||
druidDataSource.setDriverClassName(properties.getDriverClassName());
|
||||
druidDataSource.setUrl(properties.getUrl());
|
||||
druidDataSource.setUsername(properties.getUsername());
|
||||
druidDataSource.setPassword(properties.getPassword());
|
||||
|
||||
druidDataSource.setInitialSize(properties.getInitialSize());
|
||||
druidDataSource.setMaxActive(properties.getMaxActive());
|
||||
druidDataSource.setMinIdle(properties.getMinIdle());
|
||||
druidDataSource.setMaxWait(properties.getMaxWait());
|
||||
druidDataSource.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRunsMillis());
|
||||
druidDataSource.setMinEvictableIdleTimeMillis(properties.getMinEvictableIdleTimeMillis());
|
||||
druidDataSource.setMaxEvictableIdleTimeMillis(properties.getMaxEvictableIdleTimeMillis());
|
||||
druidDataSource.setValidationQuery(properties.getValidationQuery());
|
||||
druidDataSource.setValidationQueryTimeout(properties.getValidationQueryTimeout());
|
||||
druidDataSource.setTestOnBorrow(properties.isTestOnBorrow());
|
||||
druidDataSource.setTestOnReturn(properties.isTestOnReturn());
|
||||
druidDataSource.setPoolPreparedStatements(properties.isPoolPreparedStatements());
|
||||
druidDataSource.setMaxOpenPreparedStatements(properties.getMaxOpenPreparedStatements());
|
||||
druidDataSource.setSharePreparedStatements(properties.isSharePreparedStatements());
|
||||
|
||||
try {
|
||||
druidDataSource.setFilters(properties.getFilters());
|
||||
druidDataSource.init();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return druidDataSource;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.datasource.properties;
|
||||
|
||||
/**
|
||||
* 多数据源属性
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class DataSourceProperties {
|
||||
private String driverClassName;
|
||||
private String url;
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Druid默认参数
|
||||
*/
|
||||
private int initialSize = 2;
|
||||
private int maxActive = 10;
|
||||
private int minIdle = -1;
|
||||
private long maxWait = 60 * 1000L;
|
||||
private long timeBetweenEvictionRunsMillis = 60 * 1000L;
|
||||
private long minEvictableIdleTimeMillis = 1000L * 60L * 30L;
|
||||
private long maxEvictableIdleTimeMillis = 1000L * 60L * 60L * 7;
|
||||
private String validationQuery = "select 1";
|
||||
private int validationQueryTimeout = -1;
|
||||
private boolean testOnBorrow = false;
|
||||
private boolean testOnReturn = false;
|
||||
private boolean testWhileIdle = true;
|
||||
private boolean poolPreparedStatements = false;
|
||||
private int maxOpenPreparedStatements = -1;
|
||||
private boolean sharePreparedStatements = false;
|
||||
private String filters = "stat,wall";
|
||||
|
||||
public String getDriverClassName() {
|
||||
return driverClassName;
|
||||
}
|
||||
|
||||
public void setDriverClassName(String driverClassName) {
|
||||
this.driverClassName = driverClassName;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public int getInitialSize() {
|
||||
return initialSize;
|
||||
}
|
||||
|
||||
public void setInitialSize(int initialSize) {
|
||||
this.initialSize = initialSize;
|
||||
}
|
||||
|
||||
public int getMaxActive() {
|
||||
return maxActive;
|
||||
}
|
||||
|
||||
public void setMaxActive(int maxActive) {
|
||||
this.maxActive = maxActive;
|
||||
}
|
||||
|
||||
public int getMinIdle() {
|
||||
return minIdle;
|
||||
}
|
||||
|
||||
public void setMinIdle(int minIdle) {
|
||||
this.minIdle = minIdle;
|
||||
}
|
||||
|
||||
public long getMaxWait() {
|
||||
return maxWait;
|
||||
}
|
||||
|
||||
public void setMaxWait(long maxWait) {
|
||||
this.maxWait = maxWait;
|
||||
}
|
||||
|
||||
public long getTimeBetweenEvictionRunsMillis() {
|
||||
return timeBetweenEvictionRunsMillis;
|
||||
}
|
||||
|
||||
public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
|
||||
this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
|
||||
}
|
||||
|
||||
public long getMinEvictableIdleTimeMillis() {
|
||||
return minEvictableIdleTimeMillis;
|
||||
}
|
||||
|
||||
public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
|
||||
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
|
||||
}
|
||||
|
||||
public long getMaxEvictableIdleTimeMillis() {
|
||||
return maxEvictableIdleTimeMillis;
|
||||
}
|
||||
|
||||
public void setMaxEvictableIdleTimeMillis(long maxEvictableIdleTimeMillis) {
|
||||
this.maxEvictableIdleTimeMillis = maxEvictableIdleTimeMillis;
|
||||
}
|
||||
|
||||
public String getValidationQuery() {
|
||||
return validationQuery;
|
||||
}
|
||||
|
||||
public void setValidationQuery(String validationQuery) {
|
||||
this.validationQuery = validationQuery;
|
||||
}
|
||||
|
||||
public int getValidationQueryTimeout() {
|
||||
return validationQueryTimeout;
|
||||
}
|
||||
|
||||
public void setValidationQueryTimeout(int validationQueryTimeout) {
|
||||
this.validationQueryTimeout = validationQueryTimeout;
|
||||
}
|
||||
|
||||
public boolean isTestOnBorrow() {
|
||||
return testOnBorrow;
|
||||
}
|
||||
|
||||
public void setTestOnBorrow(boolean testOnBorrow) {
|
||||
this.testOnBorrow = testOnBorrow;
|
||||
}
|
||||
|
||||
public boolean isTestOnReturn() {
|
||||
return testOnReturn;
|
||||
}
|
||||
|
||||
public void setTestOnReturn(boolean testOnReturn) {
|
||||
this.testOnReturn = testOnReturn;
|
||||
}
|
||||
|
||||
public boolean isTestWhileIdle() {
|
||||
return testWhileIdle;
|
||||
}
|
||||
|
||||
public void setTestWhileIdle(boolean testWhileIdle) {
|
||||
this.testWhileIdle = testWhileIdle;
|
||||
}
|
||||
|
||||
public boolean isPoolPreparedStatements() {
|
||||
return poolPreparedStatements;
|
||||
}
|
||||
|
||||
public void setPoolPreparedStatements(boolean poolPreparedStatements) {
|
||||
this.poolPreparedStatements = poolPreparedStatements;
|
||||
}
|
||||
|
||||
public int getMaxOpenPreparedStatements() {
|
||||
return maxOpenPreparedStatements;
|
||||
}
|
||||
|
||||
public void setMaxOpenPreparedStatements(int maxOpenPreparedStatements) {
|
||||
this.maxOpenPreparedStatements = maxOpenPreparedStatements;
|
||||
}
|
||||
|
||||
public boolean isSharePreparedStatements() {
|
||||
return sharePreparedStatements;
|
||||
}
|
||||
|
||||
public void setSharePreparedStatements(boolean sharePreparedStatements) {
|
||||
this.sharePreparedStatements = sharePreparedStatements;
|
||||
}
|
||||
|
||||
public String getFilters() {
|
||||
return filters;
|
||||
}
|
||||
|
||||
public void setFilters(String filters) {
|
||||
this.filters = filters;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.datasource.properties;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 多数据源属性
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "dynamic")
|
||||
public class DynamicDataSourceProperties {
|
||||
private Map<String, DataSourceProperties> datasource = new LinkedHashMap<>();
|
||||
|
||||
public Map<String, DataSourceProperties> getDatasource() {
|
||||
return datasource;
|
||||
}
|
||||
|
||||
public void setDatasource(Map<String, DataSourceProperties> datasource) {
|
||||
this.datasource = datasource;
|
||||
}
|
||||
}
|
||||
22
src/main/java/com/peanut/modules/app/annotation/Login.java
Normal file
22
src/main/java/com/peanut/modules/app/annotation/Login.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.modules.app.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* app登录效验
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Login {
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.modules.app.annotation;
|
||||
|
||||
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.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface LoginUser {
|
||||
|
||||
}
|
||||
17
src/main/java/com/peanut/modules/app/config/SMSConfig.java
Normal file
17
src/main/java/com/peanut/modules/app/config/SMSConfig.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.peanut.modules.app.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ConfigurationProperties(prefix = "aliyun.sms")
|
||||
@Component
|
||||
@Data
|
||||
public class SMSConfig {
|
||||
|
||||
private String accessKeyId;
|
||||
private String accessKeySecret;
|
||||
private String singName;
|
||||
private String templateCode;
|
||||
|
||||
}
|
||||
17
src/main/java/com/peanut/modules/app/config/Sample.java
Normal file
17
src/main/java/com/peanut/modules/app/config/Sample.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.peanut.modules.app.config;
|
||||
|
||||
import com.aliyun.teaopenapi.models.*;
|
||||
|
||||
|
||||
public class Sample {
|
||||
public static com.aliyun.dysmsapi20170525.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
|
||||
Config config = new Config()
|
||||
// 您的 AccessKey ID
|
||||
.setAccessKeyId(accessKeyId)
|
||||
// 您的 AccessKey Secret
|
||||
.setAccessKeySecret(accessKeySecret);
|
||||
// 访问的域名
|
||||
config.endpoint = "dysmsapi.aliyuncs.com";
|
||||
return new com.aliyun.dysmsapi20170525.Client(config);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.modules.app.config;
|
||||
|
||||
import com.peanut.modules.app.interceptor.AuthorizationInterceptor;
|
||||
import com.peanut.modules.app.resolver.LoginUserHandlerMethodArgumentResolver;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MVC配置
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Configuration
|
||||
public class WebMvcConfig implements WebMvcConfigurer {
|
||||
@Autowired
|
||||
private AuthorizationInterceptor authorizationInterceptor;
|
||||
@Autowired
|
||||
private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(authorizationInterceptor).addPathPatterns("/app/**");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
argumentResolvers.add(loginUserHandlerMethodArgumentResolver);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.modules.app.controller;
|
||||
|
||||
|
||||
import com.peanut.common.utils.R;
|
||||
import com.peanut.common.validator.ValidatorUtils;
|
||||
import com.peanut.modules.app.form.LoginForm;
|
||||
import com.peanut.modules.app.service.UserService;
|
||||
import com.peanut.modules.app.utils.JwtUtils;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* APP登录授权
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/app")
|
||||
@Api("APP登录接口")
|
||||
public class AppLoginController {
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
@Autowired
|
||||
private JwtUtils jwtUtils;
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
@PostMapping("login")
|
||||
@ApiOperation("登录")
|
||||
public R login(@RequestBody LoginForm form){
|
||||
//表单校验
|
||||
ValidatorUtils.validateEntity(form);
|
||||
|
||||
//用户登录
|
||||
long userId = userService.login(form);
|
||||
|
||||
//生成token
|
||||
String token = jwtUtils.generateToken(userId);
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("token", token);
|
||||
map.put("expire", jwtUtils.getExpire());
|
||||
|
||||
return R.ok(map);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.modules.app.controller;
|
||||
|
||||
|
||||
import com.peanut.common.utils.R;
|
||||
import com.peanut.common.validator.ValidatorUtils;
|
||||
import com.peanut.modules.app.entity.UserEntity;
|
||||
import com.peanut.modules.app.form.RegisterForm;
|
||||
import com.peanut.modules.app.service.UserService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 注册
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/app")
|
||||
@Api("APP注册接口")
|
||||
public class AppRegisterController {
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@PostMapping("register")
|
||||
@ApiOperation("注册")
|
||||
public R register(@RequestBody RegisterForm form){
|
||||
//表单校验
|
||||
ValidatorUtils.validateEntity(form);
|
||||
|
||||
UserEntity user = new UserEntity();
|
||||
user.setMobile(form.getMobile());
|
||||
user.setUsername(form.getMobile());
|
||||
user.setPassword(DigestUtils.sha256Hex(form.getPassword()));
|
||||
user.setCreateTime(new Date());
|
||||
userService.save(user);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.modules.app.controller;
|
||||
|
||||
|
||||
import com.peanut.common.utils.R;
|
||||
import com.peanut.modules.app.annotation.Login;
|
||||
import com.peanut.modules.app.annotation.LoginUser;
|
||||
import com.peanut.modules.app.entity.UserEntity;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* APP测试接口
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/app")
|
||||
@Api("APP测试接口")
|
||||
public class AppTestController {
|
||||
|
||||
@Login
|
||||
@GetMapping("userInfo")
|
||||
@ApiOperation("获取用户信息")
|
||||
public R userInfo(@LoginUser UserEntity user){
|
||||
return R.ok().put("user", user);
|
||||
}
|
||||
|
||||
@Login
|
||||
@GetMapping("userId")
|
||||
@ApiOperation("获取用户ID")
|
||||
public R userInfo(@RequestAttribute("userId") Integer userId){
|
||||
return R.ok().put("userId", userId);
|
||||
}
|
||||
|
||||
@GetMapping("notToken")
|
||||
@ApiOperation("忽略Token验证测试")
|
||||
public R notToken(){
|
||||
return R.ok().put("msg", "无需token也能访问。。。");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.peanut.modules.app.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baidu.ueditor.ActionEnter;
|
||||
import com.peanut.common.utils.UEditorUpload;
|
||||
import com.peanut.modules.app.entity.UEditorFile;
|
||||
import com.peanut.modules.oss.service.OssService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/ueditor")
|
||||
public class UeditorController {
|
||||
|
||||
@Autowired
|
||||
ResourceLoader resourceLoader;
|
||||
@Autowired
|
||||
UEditorUpload ueditorUpload;
|
||||
|
||||
@RequestMapping("/config")
|
||||
@ResponseBody
|
||||
public String exec(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@RequestParam(value = "action") String action,
|
||||
@RequestParam(value = "upfile", required = false) MultipartFile upfile) throws Exception {
|
||||
if (action.equals("config")) {
|
||||
request.setCharacterEncoding("utf-8");
|
||||
response.setContentType("text/html");
|
||||
String rootPath = request.getSession().getServletContext().getRealPath("/");
|
||||
return new ActionEnter(request, rootPath).exec();
|
||||
} else if (action.equals("uploadimage")) {
|
||||
UEditorFile uEditorFile = ueditorUpload.uploadImage(upfile);
|
||||
String jsonString = JSONObject.toJSONString(uEditorFile);
|
||||
|
||||
return jsonString;
|
||||
} else if (action.equals("uploadfile")) {
|
||||
UEditorFile uEditorFile = ueditorUpload.uploadImage(upfile);
|
||||
String jsonString = JSONObject.toJSONString(uEditorFile);
|
||||
|
||||
return jsonString;
|
||||
}
|
||||
return "无效Action";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
23
src/main/java/com/peanut/modules/app/dao/UserDao.java
Normal file
23
src/main/java/com/peanut/modules/app/dao/UserDao.java
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.modules.app.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.peanut.modules.app.entity.UserEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 用户
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface UserDao extends BaseMapper<UserEntity> {
|
||||
|
||||
}
|
||||
31
src/main/java/com/peanut/modules/app/entity/UEditorFile.java
Normal file
31
src/main/java/com/peanut/modules/app/entity/UEditorFile.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package com.peanut.modules.app.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public class UEditorFile {
|
||||
|
||||
private static final long serialVersionUID=1L;
|
||||
|
||||
private String state;
|
||||
|
||||
private String url;
|
||||
|
||||
private String title;
|
||||
|
||||
private String original;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{" +
|
||||
"state='" + state + '\'' +
|
||||
", url='" + url + '\'' +
|
||||
", title='" + title + '\'' +
|
||||
", original='" + original + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
51
src/main/java/com/peanut/modules/app/entity/UserEntity.java
Normal file
51
src/main/java/com/peanut/modules/app/entity/UserEntity.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.modules.app.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 用户
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@TableName("tb_user")
|
||||
public class UserEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@TableId
|
||||
private Long userId;
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
private String mobile;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
33
src/main/java/com/peanut/modules/app/form/LoginForm.java
Normal file
33
src/main/java/com/peanut/modules/app/form/LoginForm.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.modules.app.form;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 登录表单
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "登录表单")
|
||||
public class LoginForm {
|
||||
@ApiModelProperty(value = "手机号")
|
||||
@NotBlank(message="手机号不能为空")
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty(value = "密码")
|
||||
@NotBlank(message="密码不能为空")
|
||||
private String password;
|
||||
|
||||
}
|
||||
33
src/main/java/com/peanut/modules/app/form/RegisterForm.java
Normal file
33
src/main/java/com/peanut/modules/app/form/RegisterForm.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.modules.app.form;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 注册表单
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "注册表单")
|
||||
public class RegisterForm {
|
||||
@ApiModelProperty(value = "手机号")
|
||||
@NotBlank(message="手机号不能为空")
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty(value = "密码")
|
||||
@NotBlank(message="密码不能为空")
|
||||
private String password;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.modules.app.interceptor;
|
||||
|
||||
|
||||
import com.peanut.common.exception.RRException;
|
||||
import com.peanut.modules.app.annotation.Login;
|
||||
import com.peanut.modules.app.utils.JwtUtils;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 权限(Token)验证
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Component
|
||||
public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
|
||||
@Autowired
|
||||
private JwtUtils jwtUtils;
|
||||
|
||||
public static final String USER_KEY = "userId";
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
Login annotation;
|
||||
if(handler instanceof HandlerMethod) {
|
||||
annotation = ((HandlerMethod) handler).getMethodAnnotation(Login.class);
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
|
||||
if(annotation == null){
|
||||
return true;
|
||||
}
|
||||
|
||||
//获取用户凭证
|
||||
String token = request.getHeader(jwtUtils.getHeader());
|
||||
if(StringUtils.isBlank(token)){
|
||||
token = request.getParameter(jwtUtils.getHeader());
|
||||
}
|
||||
|
||||
//凭证为空
|
||||
if(StringUtils.isBlank(token)){
|
||||
throw new RRException(jwtUtils.getHeader() + "不能为空", HttpStatus.UNAUTHORIZED.value());
|
||||
}
|
||||
|
||||
Claims claims = jwtUtils.getClaimByToken(token);
|
||||
if(claims == null || jwtUtils.isTokenExpired(claims.getExpiration())){
|
||||
throw new RRException(jwtUtils.getHeader() + "失效,请重新登录", HttpStatus.UNAUTHORIZED.value());
|
||||
}
|
||||
|
||||
//设置userId到request里,后续根据userId,获取用户信息
|
||||
request.setAttribute(USER_KEY, Long.parseLong(claims.getSubject()));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user