因为之前写的项目中有使用到淘宝sdk中的WebUtils工具类,功能方面还是比较全,由于近期的项目又要调用外部api,在百度上面找了一圈后没有自己喜欢的,因此在淘宝sdk中将该方法提了出来。该工具支持携带头部消息(cookie等),使用起来也非常的方便。
自己只是简单测试了一下可以使用,功能是否完全正常未知!
先看看工具类的方法吧(因为是直接从淘宝sdk中拿过来的,所以可能有多余无用方法,同时部分类不是从淘宝sdk中复制过来的)
调用演示
携带头部消息调用演示
代码部分
WebUtils.java
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.zip.GZIPInputStream;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
/**
* 网络工具类。
*
* @author carver.gu
* @since 1.0, Sep 12, 2009
*/
public abstract class WebUtils {
private static final String DEFAULT_CHARSET = Constants.CHARSET_UTF8;
private static boolean ignoreSSLCheck = true; // 忽略SSL检查
private static boolean ignoreHostCheck = true; // 忽略HOST检查
public static class TrustAllTrustManager implements X509TrustManager {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
}
private WebUtils() {
}
public static void setIgnoreSSLCheck(boolean ignoreSSLCheck) {
WebUtils.ignoreSSLCheck = ignoreSSLCheck;
}
public static void setIgnoreHostCheck(boolean ignoreHostCheck) {
WebUtils.ignoreHostCheck = ignoreHostCheck;
}
/**
* 执行HTTP POST请求。
*
* @param url 请求地址
* @param params 请求参数
* @return 响应字符串
*/
public static String doPost(String url, Map<String, String> params, int connectTimeout, int readTimeout) throws IOException {
return doPost(url, params, DEFAULT_CHARSET, connectTimeout, readTimeout);
}
/**
* 执行HTTP POST请求。
*
* @param url 请求地址
* @param params 请求参数
* @param charset 字符集,如UTF-8, GBK, GB2312
* @return 响应字符串
*/
public static String doPost(String url, Map<String, String> params, String charset, int connectTimeout, int readTimeout) throws IOException {
return doPost(url, params, charset, connectTimeout, readTimeout, null, null);
}
public static String doPost(String url, Map<String, String> params, String charset, int connectTimeout, int readTimeout, Map<String, String> headerMap, Proxy proxy) throws IOException {
String ctype = "application/x-www-form-urlencoded;charset=" + charset;
String query = buildQuery(params, charset);
byte[] content = {};
if (query != null) {
content = query.getBytes(charset);
}
return _doPost(url, ctype, content, connectTimeout, readTimeout, headerMap, proxy);
}
public static String doPost(String url, String apiBody, String charset, int connectTimeout, int readTimeout, Map<String, String> headerMap) throws IOException {
String ctype = "text/plain;charset=" + charset;
byte[] content = apiBody.getBytes(charset);
return _doPost(url, ctype, content, connectTimeout, readTimeout, headerMap, null);
}
/**
* 执行HTTP POST请求。
*
* @param url 请求地址
* @param ctype 请求类型
* @param content 请求字节数组
* @return 响应字符串
*/
public static String doPost(String url, String ctype, byte[] content, int connectTimeout, int readTimeout) throws IOException {
return _doPost(url, ctype, content, connectTimeout, readTimeout, null, null);
}
/**
* 执行HTTP POST请求。
*
* @param url 请求地址
* @param ctype 请求类型
* @param content 请求字节数组
* @param headerMap 请求头部参数
* @return 响应字符串
*/
public static String doPost(String url, String ctype, byte[] content, int connectTimeout, int readTimeout, Map<String, String> headerMap, Proxy proxy) throws IOException {
return _doPost(url, ctype, content, connectTimeout, readTimeout, headerMap, proxy);
}
private static String _doPost(String url, String ctype, byte[] content, int connectTimeout, int readTimeout, Map<String, String> headerMap, Proxy proxy) throws IOException {
HttpURLConnection conn = null;
OutputStream out = null;
String rsp = null;
try {
conn = getConnection(new URL(url), Constants.METHOD_POST, ctype, headerMap, proxy);
conn.setConnectTimeout(connectTimeout);
conn.setReadTimeout(readTimeout);
out = conn.getOutputStream();
out.write(content);
rsp = getResponseAsString(conn);
} finally {
if (out != null) {
out.close();
}
if (conn != null) {
conn.disconnect();
}
}
return rsp;
}
/**
* 执行带文件上传的HTTP POST请求。
*
* @param url 请求地址
* @param fileParams 文件请求参数
* @return 响应字符串
*/
public static String doPost(String url, Map<String, String> params, Map<String, FileItem> fileParams, int connectTimeout, int readTimeout) throws IOException {
if (fileParams == null || fileParams.isEmpty()) {
return doPost(url, params, DEFAULT_CHARSET, connectTimeout, readTimeout);
} else {
return doPost(url, params, fileParams, DEFAULT_CHARSET, connectTimeout, readTimeout);
}
}
public static String doPost(String url, Map<String, String> params, Map<String, FileItem> fileParams, String charset, int connectTimeout, int readTimeout) throws IOException {
return doPost(url, params, fileParams, charset, connectTimeout, readTimeout, null);
}
/**
* 执行带文件上传的HTTP POST请求。
*
* @param url 请求地址
* @param fileParams 文件请求参数
* @param charset 字符集,如UTF-8, GBK, GB2312
* @param headerMap 需要传递的header头,可以为空
* @return 响应字符串
*/
public static String doPost(String url, Map<String, String> params, Map<String, FileItem> fileParams, String charset,
int connectTimeout, int readTimeout, Map<String, String> headerMap) throws IOException {
if (fileParams == null || fileParams.isEmpty()) {
return doPost(url, params, charset, connectTimeout, readTimeout, headerMap, null);
} else {
return _doPostWithFile(url, params, fileParams, charset, connectTimeout, readTimeout, headerMap);
}
}
/**
* 执行请求
* content_type: aplication/json
*
* @param url
* @param params
* @param charset
* @param connectTimeout
* @param readTimeout
* @return
* @throws IOException
*/
public static String doPostWithJson(String url, Map<String, Object> params, String charset, int connectTimeout, int readTimeout) throws IOException {
String ctype = "application/json;charset=" + charset;
byte[] content = {};
String body = JsonUtils.objectToJson(params);
if (body != null) {
content = body.getBytes(charset);
}
return _doPost(url, ctype, content, connectTimeout, readTimeout, null, null);
}
private static String _doPostWithFile(String url, Map<String, String> params, Map<String, FileItem> fileParams,
String charset, int connectTimeout, int readTimeout, Map<String, String> headerMap) throws IOException {
String boundary = String.valueOf(System.nanoTime()); // 随机分隔线
HttpURLConnection conn = null;
OutputStream out = null;
String rsp = null;
try {
String ctype = "multipart/form-data;charset=" + charset + ";boundary=" + boundary;
conn = getConnection(new URL(url), Constants.METHOD_POST, ctype, headerMap, null);
conn.setConnectTimeout(connectTimeout);
conn.setReadTimeout(readTimeout);
out = conn.getOutputStream();
byte[] entryBoundaryBytes = ("\r\n--" + boundary + "\r\n").getBytes(charset);
// 组装文本请求参数
Set<Entry<String, String>> textEntrySet = params.entrySet();
for (Entry<String, String> textEntry : textEntrySet) {
byte[] textBytes = getTextEntry(textEntry.getKey(), textEntry.getValue(), charset);
out.write(entryBoundaryBytes);
out.write(textBytes);
}
// 组装文件请求参数
Set<Entry<String, FileItem>> fileEntrySet = fileParams.entrySet();
for (Entry<String, FileItem> fileEntry : fileEntrySet) {
FileItem fileItem = fileEntry.getValue();
if (!fileItem.isValid()) {
throw new IOException("FileItem is invalid");
}
byte[] fileBytes = getFileEntry(fileEntry.getKey(), fileItem.getFileName(), fileItem.getMimeType(), charset);
out.write(entryBoundaryBytes);
out.write(fileBytes);
fileItem.write(out);
}
// 添加请求结束标志
byte[] endBoundaryBytes = ("\r\n--" + boundary + "--\r\n").getBytes(charset);
out.write(endBoundaryBytes);
rsp = getResponseAsString(conn);
} finally {
if (out != null) {
out.close();
}
if (conn != null) {
conn.disconnect();
}
}
return rsp;
}
private static byte[] getTextEntry(String fieldName, String fieldValue, String charset) throws IOException {
StringBuilder entry = new StringBuilder();
entry.append("Content-Disposition:form-data;name=\"");
entry.append(fieldName);
entry.append("\"\r\nContent-Type:text/plain\r\n\r\n");
entry.append(fieldValue);
return entry.toString().getBytes(charset);
}
private static byte[] getFileEntry(String fieldName, String fileName, String mimeType, String charset) throws IOException {
StringBuilder entry = new StringBuilder();
entry.append("Content-Disposition:form-data;name=\"");
entry.append(fieldName);
entry.append("\";filename=\"");
entry.append(fileName);
entry.append("\"\r\nContent-Type:");
entry.append(mimeType);
entry.append("\r\n\r\n");
return entry.toString().getBytes(charset);
}
/**
* 执行HTTP GET请求。
*
* @param url 请求地址
* @param params 请求参数
* @return 响应字符串
*/
public static String doGet(String url, Map<String, String> params) throws IOException {
return doGet(url, params, DEFAULT_CHARSET);
}
/**
* 执行HTTP GET请求。
*
* @param url 请求地址
* @param params 请求参数
* @param charset 字符集,如UTF-8, GBK, GB2312
* @return 响应字符串
*/
public static String doGet(String url, Map<String, String> params, String charset) throws IOException {
HttpURLConnection conn = null;
String rsp = null;
try {
String ctype = "application/x-www-form-urlencoded;charset=" + charset;
String query = buildQuery(params, charset);
conn = getConnection(buildGetUrl(url, query), Constants.METHOD_GET, ctype, null, null);
rsp = getResponseAsString(conn);
} finally {
if (conn != null) {
conn.disconnect();
}
}
return rsp;
}
private static HttpURLConnection getConnection(URL url, String method, String ctype, Map<String, String> headerMap, Proxy proxy) throws IOException {
HttpURLConnection conn = null;
if(proxy == null) {
conn = (HttpURLConnection) url.openConnection();
} else {
conn = (HttpURLConnection) url.openConnection(proxy);
}
if (conn instanceof HttpsURLConnection) {
HttpsURLConnection connHttps = (HttpsURLConnection) conn;
if (ignoreSSLCheck) {
try {
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, new TrustManager[] { new TrustAllTrustManager() }, new SecureRandom());
connHttps.setSSLSocketFactory(ctx.getSocketFactory());
connHttps.setHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
} catch (Exception e) {
throw new IOException(e.toString());
}
} else {
if (ignoreHostCheck) {
connHttps.setHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
}
}
conn = connHttps;
}
conn.setRequestMethod(method);
conn.setDoInput(true);
conn.setDoOutput(true);
if(headerMap != null && headerMap.get(Constants.TOP_HTTP_DNS_HOST) != null){
conn.setRequestProperty("Host", headerMap.get(Constants.TOP_HTTP_DNS_HOST));
}else{
conn.setRequestProperty("Host", url.getHost());
}
conn.setRequestProperty("Accept", "text/xml,text/javascript");
conn.setRequestProperty("User-Agent", "top-sdk-java");
conn.setRequestProperty("Content-Type", ctype);
if (headerMap != null) {
for (Map.Entry<String, String> entry : headerMap.entrySet()) {
if(!Constants.TOP_HTTP_DNS_HOST.equals(entry.getKey())){
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
}
}
return conn;
}
private static URL buildGetUrl(String url, String query) throws IOException {
if (StringUtils.isEmpty(query)) {
return new URL(url);
}
return new URL(buildRequestUrl(url, query));
}
public static String buildRequestUrl(String url, String... queries) {
if (queries == null || queries.length == 0) {
return url;
}
StringBuilder newUrl = new StringBuilder(url);
boolean hasQuery = url.contains("?");
boolean hasPrepend = url.endsWith("?") || url.endsWith("&");
for (String query : queries) {
if (!StringUtils.isEmpty(query)) {
if (!hasPrepend) {
if (hasQuery) {
newUrl.append("&");
} else {
newUrl.append("?");
hasQuery = true;
}
}
newUrl.append(query);
hasPrepend = false;
}
}
return newUrl.toString();
}
public static String buildQuery(Map<String, String> params, String charset) throws IOException {
if (params == null || params.isEmpty()) {
return null;
}
StringBuilder query = new StringBuilder();
Set<Entry<String, String>> entries = params.entrySet();
boolean hasParam = false;
for (Entry<String, String> entry : entries) {
String name = entry.getKey();
String value = entry.getValue();
// 忽略参数名或参数值为空的参数
if (StringUtils.areNotEmpty(name, value)) {
if (hasParam) {
query.append("&");
} else {
hasParam = true;
}
query.append(name).append("=").append(URLEncoder.encode(value, charset));
}
}
return query.toString();
}
protected static String getResponseAsString(HttpURLConnection conn) throws IOException {
String charset = getResponseCharset(conn.getContentType());
if (conn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
String contentEncoding = conn.getContentEncoding();
if (Constants.CONTENT_ENCODING_GZIP.equalsIgnoreCase(contentEncoding)) {
return getStreamAsString(new GZIPInputStream(conn.getInputStream()), charset);
} else {
return getStreamAsString(conn.getInputStream(), charset);
}
} else {
// OAuth bad request always return 400 status
if (conn.getResponseCode() == HttpURLConnection.HTTP_BAD_REQUEST) {
InputStream error = conn.getErrorStream();
if (error != null) {
return getStreamAsString(error, charset);
}
}
// Client Error 4xx and Server Error 5xx
throw new IOException(conn.getResponseCode() + " " + conn.getResponseMessage());
}
}
public static String getStreamAsString(InputStream stream, String charset) throws IOException {
try {
Reader reader = new InputStreamReader(stream, charset);
StringBuilder response = new StringBuilder();
final char[] buff = new char[1024];
int read = 0;
while ((read = reader.read(buff)) > 0) {
response.append(buff, 0, read);
}
return response.toString();
} finally {
if (stream != null) {
stream.close();
}
}
}
public static String getResponseCharset(String ctype) {
String charset = DEFAULT_CHARSET;
if (!StringUtils.isEmpty(ctype)) {
String[] params = ctype.split(";");
for (String param : params) {
param = param.trim();
if (param.startsWith("charset")) {
String[] pair = param.split("=", 2);
if (pair.length == 2) {
if (!StringUtils.isEmpty(pair[1])) {
charset = pair[1].trim();
}
}
break;
}
}
}
return charset;
}
/**
* 使用默认的UTF-8字符集反编码请求参数值。
*
* @param value 参数值
* @return 反编码后的参数值
*/
public static String decode(String value) {
return decode(value, DEFAULT_CHARSET);
}
/**
* 使用默认的UTF-8字符集编码请求参数值。
*
* @param value 参数值
* @return 编码后的参数值
*/
public static String encode(String value) {
return encode(value, DEFAULT_CHARSET);
}
/**
* 使用指定的字符集反编码请求参数值。
*
* @param value 参数值
* @param charset 字符集
* @return 反编码后的参数值
*/
public static String decode(String value, String charset) {
String result = null;
if (!StringUtils.isEmpty(value)) {
try {
result = URLDecoder.decode(value, charset);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return result;
}
/**
* 使用指定的字符集编码请求参数值。
*
* @param value 参数值
* @param charset 字符集
* @return 编码后的参数值
*/
public static String encode(String value, String charset) {
String result = null;
if (!StringUtils.isEmpty(value)) {
try {
result = URLEncoder.encode(value, charset);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return result;
}
/**
* 从URL中提取所有的参数。
*
* @param query URL地址
* @return 参数映射
*/
public static Map<String, String> splitUrlQuery(String query) {
Map<String, String> result = new HashMap<String, String>();
String[] pairs = query.split("&");
if (pairs != null && pairs.length > 0) {
for (String pair : pairs) {
String[] param = pair.split("=", 2);
if (param != null && param.length == 2) {
result.put(param[0], param[1]);
}
}
}
return result;
}
}
Constants.java
/**
* 公用常量类。
*
* @author carver.gu
* @since 1.0, Sep 12, 2009
*/
public abstract class Constants {
/** TOP协议入参共享参数 **/
public static final String APP_KEY = "app_key";
public static final String FORMAT = "format";
public static final String METHOD = "method";
public static final String TIMESTAMP = "timestamp";
public static final String VERSION = "v";
public static final String SIGN = "sign";
public static final String SIGN_METHOD = "sign_method";
public static final String PARTNER_ID = "partner_id";
public static final String SESSION = "session";
public static final String SIMPLIFY = "simplify";
public static final String TARGET_APP_KEY = "target_app_key";
/** TOP协议出参共享参数 */
public static final String ERROR_RESPONSE = "error_response";
public static final String ERROR_CODE = "code";
public static final String ERROR_MSG = "msg";
public static final String ERROR_SUB_CODE = "sub_code";
public static final String ERROR_SUB_MSG = "sub_msg";
/** 奇门协议共享参数 */
public static final String QIMEN_CLOUD_ERROR_RESPONSE = "response";
public static final String QM_ROOT_TAG = "request";
public static final String QM_CUSTOMER_ID = "customerId";
public static final String QM_CONTENT_TYPE = "text/xml;charset=utf-8";
public static final String QM_CONTENT_TYPE_JSON = "application/json;charset=utf-8";
/** TOP默认时间格式 **/
public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
/** TOP Date默认时区 **/
public static final String DATE_TIMEZONE = "GMT+8";
/** UTF-8字符集 **/
public static final String CHARSET_UTF8 = "UTF-8";
/** HTTP请求相关 **/
public static final String METHOD_POST = "POST";
public static final String METHOD_GET = "GET";
public static final String CTYPE_FORM_DATA = "application/x-www-form-urlencoded";
public static final String CTYPE_FILE_UPLOAD = "multipart/form-data";
public static final String CTYPE_TEXT_XML = "text/xml";
public static final String CTYPE_APPLICATION_XML = "application/xml";
public static final String CTYPE_TEXT_PLAIN = "text/plain";
public static final String CTYPE_APP_JSON = "application/json";
/** GBK字符集 **/
public static final String CHARSET_GBK = "GBK";
/** TOP JSON 应格式 */
public static final String FORMAT_JSON = "json";
/** TOP XML 应格式 */
public static final String FORMAT_XML = "xml";
/** TOP JSON 新格式 */
public static final String FORMAT_JSON2 = "json2";
/** TOP XML 新格式 */
public static final String FORMAT_XML2 = "xml2";
/** MD5签名方式 */
public static final String SIGN_METHOD_MD5 = "md5";
/** HMAC签名方式 */
public static final String SIGN_METHOD_HMAC = "hmac";
/** HMAC-SHA256签名方式 */
public static final String SIGN_METHOD_HMAC_SHA256 = "hmac-sha256";
/** SDK版本号 */
public static final String SDK_VERSION = "top-sdk-java-20190108";
/** 异步多活SDK版本号 */
public static final String SDK_VERSION_CLUSTER = "top-sdk-java-cluster-20190108";
/** httpdns SDK版本号 */
public static final String SDK_VERSION_HTTPDNS = "top-sdk-java-httpdns-20190108";
/** httpdns SDK版本号 */
public static final String QIMEN_SDK_VERSION_HTTPDNS = "top-qimen-sdk-java-httpdns";
/** 响应编码 */
public static final String ACCEPT_ENCODING = "Accept-Encoding";
public static final String CONTENT_ENCODING = "Content-Encoding";
public static final String CONTENT_ENCODING_GZIP = "gzip";
/** 默认媒体类型 **/
public static final String MIME_TYPE_DEFAULT = "application/octet-stream";
/** 默认流式读取缓冲区大小 **/
public static final int READ_BUFFER_SIZE = 1024 * 4;
public static final String TOP_HTTP_DNS_HOST = "TOP_HTTP_DNS_HOST";
/** API网关请求content type **/
public static final String CONTENT_TYPE_XML = "xml";
public static final String CONTENT_TYPE_JSON = "json";
public static final String CONTENT_TYPE_FORM = "form";
public static final String RESPONSE_TYPE_TOP = "top";
public static final String RESPONSE_TYPE_QIMEN = "qimen1";
public static final String RESPONSE_TYPE_QIMEN2 = "qimen2";
public static final String RESPONSE_TYPE_DINGTALK_OAPI = "dingtalk";
/** 钉钉调用方式 TOP标准格式,form-data */
public static final String CALL_TYPE_TOP = "top";
/** 钉钉调用方式 OAPI兼容格式,application/json */
public static final String CALL_TYPE_OAPI = "oapi";
}
FileItem.java
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* 文件包装类,支持本地文件、字节数组和输入流三种方式。
*
* @author carver.gu
* @since 1.0, Sep 12, 2009
*/
public class FileItem {
private Contract contract;
/**
* 基于本地文件的构造器,适用于上传本地文件。
*
* @param file 本地文件
*/
public FileItem(final File file) {
this.contract = new LocalContract(file);
}
/**
* 基于文件绝对路径的构造器,适用于上传本地文件。
*
* @param filePath 文件绝对路径
*/
public FileItem(String filePath) {
this(new File(filePath));
}
/**
* 基于文件名和字节数组的构造器。
*
* @param fileName 文件名
* @param content 文件字节数组
*/
public FileItem(String fileName, byte[] content) {
this(fileName, content, null);
}
/**
* 基于文件名、字节数组和媒体类型的构造器。
*
* @param fileName 文件名
* @param content 文件字节数组
* @param mimeType 媒体类型,如:image/jpeg, text/plain
*/
public FileItem(String fileName, byte[] content, String mimeType) {
this.contract = new ByteArrayContract(fileName, content, mimeType);
}
/**
* 基于文件名和字节流的构造器,适应于全流式上传,减少本地内存开销。
*
* @param fileName 文件名
* @param content 文件字节流
*/
public FileItem(String fileName, InputStream stream) {
this(fileName, stream, null);
}
/**
* 基于文件名、字节流和媒体类型的构造器,适应于全流式上传,减少本地内存开销。
*
* @param fileName 文件名
* @param content 文件字节流
* @param mimeType 媒体类型,如:image/jpeg, text/plain
*/
public FileItem(String fileName, InputStream stream, String mimeType) {
this.contract = new StreamContract(fileName, stream, mimeType);
}
public boolean isValid() {
return this.contract.isValid();
}
public String getFileName() {
return this.contract.getFileName();
}
public String getMimeType() throws IOException {
return this.contract.getMimeType();
}
public long getFileLength() {
return this.contract.getFileLength();
}
public void write(OutputStream output) throws IOException {
this.contract.write(output);
}
private static interface Contract {
public boolean isValid();
public String getFileName();
public String getMimeType();
public long getFileLength();
public void write(OutputStream output) throws IOException;
}
private static class LocalContract implements Contract {
private File file;
public LocalContract(File file) {
this.file = file;
}
public boolean isValid() {
return this.file != null && this.file.exists() && this.file.isFile();
}
public String getFileName() {
return this.file.getName();
}
public String getMimeType() {
return Constants.MIME_TYPE_DEFAULT;
}
public long getFileLength() {
return this.file.length();
}
public void write(OutputStream output) throws IOException {
InputStream input = null;
try {
input = new FileInputStream(this.file);
byte[] buffer = new byte[Constants.READ_BUFFER_SIZE];
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
}
} finally {
if (input != null) {
input.close();
}
}
}
}
private static class ByteArrayContract implements Contract {
private String fileName;
private byte[] content;
private String mimeType;
public ByteArrayContract(String fileName, byte[] content, String mimeType) {
this.fileName = fileName;
this.content = content;
this.mimeType = mimeType;
}
public boolean isValid() {
return this.content != null && this.fileName != null;
}
public String getFileName() {
return this.fileName;
}
public String getMimeType() {
if (this.mimeType == null) {
return Constants.MIME_TYPE_DEFAULT;
} else {
return this.mimeType;
}
}
public long getFileLength() {
return this.content.length;
}
public void write(OutputStream output) throws IOException {
output.write(this.content);
}
}
private static class StreamContract implements Contract {
private String fileName;
private InputStream stream;
private String mimeType;
public StreamContract(String fileName, InputStream stream, String mimeType) {
this.fileName = fileName;
this.stream = stream;
this.mimeType = mimeType;
}
public boolean isValid() {
return this.stream != null && this.fileName != null;
}
public String getFileName() {
return this.fileName;
}
public String getMimeType() {
if (this.mimeType == null) {
return Constants.MIME_TYPE_DEFAULT;
} else {
return this.mimeType;
}
}
public long getFileLength() {
return 0L;
}
public void write(OutputStream output) throws IOException {
try {
byte[] buffer = new byte[Constants.READ_BUFFER_SIZE];
int n = 0;
while (-1 != (n = stream.read(buffer))) {
output.write(buffer, 0, n);
}
} finally {
if (stream != null) {
stream.close();
}
}
}
}
}
StringUtils.java
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 字符串工具类。
*
* @author carver.gu
* @since 1.0, Sep 12, 2009
*/
public abstract class StringUtils {
/**
* An empty immutable <code>String</code> array.
*/
public static final String[] EMPTY_STRING_ARRAY = new String[0];
private static final TimeZone TZ_GMT8 = TimeZone.getTimeZone(Constants.DATE_TIMEZONE);
private static final Pattern PATTERN_CIDR = Pattern.compile("^(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})/(\\d{1,2})$");
private static final String QUOT = """;
private static final String AMP = "&";
private static final String APOS = "'";
private static final String GT = ">";
private static final String LT = "<";
private StringUtils() {}
/**
* 检查指定的字符串是否为空。
* <ul>
* <li>SysUtils.isEmpty(null) = true</li>
* <li>SysUtils.isEmpty("") = true</li>
* <li>SysUtils.isEmpty(" ") = true</li>
* <li>SysUtils.isEmpty("abc") = false</li>
* </ul>
*
* @param value 待检查的字符串
* @return true/false
*/
public static boolean isEmpty(String value) {
int strLen;
if (value == null || (strLen = value.length()) == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if ((Character.isWhitespace(value.charAt(i)) == false)) {
return false;
}
}
return true;
}
/**
* 检查对象是否为数字型字符串,包含负数开头的。
*/
public static boolean isNumeric(Object obj) {
if (obj == null) {
return false;
}
char[] chars = obj.toString().toCharArray();
int length = chars.length;
if(length < 1)
return false;
int i = 0;
if(length > 1 && chars[0] == '-')
i = 1;
for (; i < length; i++) {
if (!Character.isDigit(chars[i])) {
return false;
}
}
return true;
}
/**
* 检查指定的字符串列表是否不为空。
*/
public static boolean areNotEmpty(String... values) {
boolean result = true;
if (values == null || values.length == 0) {
result = false;
} else {
for (String value : values) {
result &= !isEmpty(value);
}
}
return result;
}
/**
* 把通用字符编码的字符串转化为汉字编码。
*/
public static String unicodeToChinese(String unicode) {
StringBuilder out = new StringBuilder();
if (!isEmpty(unicode)) {
for (int i = 0; i < unicode.length(); i++) {
out.append(unicode.charAt(i));
}
}
return out.toString();
}
/**
* 把名称转换为小写加下划线的形式。
*/
public static String toUnderlineStyle(String name) {
StringBuilder newName = new StringBuilder();
int len = name.length();
for (int i = 0; i < len; i++) {
char c = name.charAt(i);
if (Character.isUpperCase(c)) {
if (i > 0) {
newName.append("_");
}
newName.append(Character.toLowerCase(c));
} else {
newName.append(c);
}
}
return newName.toString();
}
/**
* 把名称转换为首字母小写的驼峰形式。
*/
public static String toCamelStyle(String name) {
StringBuilder newName = new StringBuilder();
int len = name.length();
for (int i = 0; i < len; i++) {
char c = name.charAt(i);
if (i == 0) {
newName.append(Character.toLowerCase(c));
} else {
newName.append(c);
}
}
return newName.toString();
}
/**
* 把字符串解释为日期对象,采用yyyy-MM-dd HH:mm:ss的格式。
*/
public static Date parseDateTime(String str) {
DateFormat format = new SimpleDateFormat(Constants.DATE_TIME_FORMAT);
format.setTimeZone(TZ_GMT8);
try {
return format.parse(str);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
/**
* 对日期进行字符串格式化,采用yyyy-MM-dd HH:mm:ss的格式。
*/
public static String formatDateTime(Date date) {
DateFormat format = new SimpleDateFormat(Constants.DATE_TIME_FORMAT);
format.setTimeZone(TZ_GMT8);
return format.format(date);
}
/**
* 对日期进行字符串格式化,采用指定的格式。
*/
public static String formatDateTime(Date date, String pattern) {
DateFormat format = new SimpleDateFormat(pattern);
format.setTimeZone(TZ_GMT8);
return format.format(date);
}
/**
* XML字符转义包括(<,>,',&,")五个字符.
*
* @param value 所需转义的字符串
*
* @return 转义后的字符串 @
*/
public static String escapeXml(String value) {
StringBuilder writer = new StringBuilder();
char[] chars = value.trim().toCharArray();
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
switch (c) {
case '<':
writer.append(LT);
break;
case '>':
writer.append(GT);
break;
case '\'':
writer.append(APOS);
break;
case '&':
writer.append(AMP);
break;
case '\"':
writer.append(QUOT);
break;
default:
if ((c == 0x9) || (c == 0xA) || (c == 0xD) || ((c >= 0x20) && (c <= 0xD7FF))
|| ((c >= 0xE000) && (c <= 0xFFFD)) || ((c >= 0x10000) && (c <= 0x10FFFF)))
writer.append(c);
}
}
return writer.toString();
}
/**
* 获取类的get/set属性名称集合。
*
* @param clazz 类
* @param isGet 是否获取读方法,true为读方法,false为写方法
* @return 属性名称集合
*/
public static Set<String> getClassProperties(Class<?> clazz, boolean isGet) {
Set<String> propNames = new HashSet<String>();
try {
if(clazz == null){
return propNames;
}
BeanInfo info = Introspector.getBeanInfo(clazz);
PropertyDescriptor[] props = info.getPropertyDescriptors();
for (PropertyDescriptor prop : props) {
String name = prop.getName();
Method method;
if (isGet) {
method = prop.getReadMethod();
} else {
method = prop.getWriteMethod();
}
if (!"class".equals(name) && method != null) {
propNames.add(name);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return propNames;
}
//-----------------------------------------------------------------------
/**
* <p>Checks whether the <code>String</code> contains only
* digit characters.</p>
*
* <p><code>Null</code> and empty String will return
* <code>false</code>.</p>
*
* @param str the <code>String</code> to check
* @return <code>true</code> if str contains only unicode numeric
*/
public static boolean isDigits(String str) {
if (StringUtils.isEmpty(str)) {
return false;
}
for (int i = 0; i < str.length(); i++) {
if (!Character.isDigit(str.charAt(i))) {
return false;
}
}
return true;
}
/**
* <p>Splits the provided text into an array, separator specified.
* This is an alternative to using StringTokenizer.</p>
*
* <p>The separator is not included in the returned String array.
* Adjacent separators are treated as one separator.
* For more control over the split use the StrTokenizer class.</p>
*
* <p>A <code>null</code> input String returns <code>null</code>.</p>
*
* <pre>
* StringUtils.split(null, *) = null
* StringUtils.split("", *) = []
* StringUtils.split("a.b.c", '.') = ["a", "b", "c"]
* StringUtils.split("a..b.c", '.') = ["a", "b", "c"]
* StringUtils.split("a:b:c", '.') = ["a:b:c"]
* StringUtils.split("a b c", ' ') = ["a", "b", "c"]
* </pre>
*
* @param str the String to parse, may be null
* @param separatorChar the character used as the delimiter
* @return an array of parsed Strings, <code>null</code> if null String input
* @since 2.0
*/
public static String[] split(String str, char separatorChar) {
return splitWorker(str, separatorChar, false);
}
/**
* Performs the logic for the <code>split</code> and
* <code>splitPreserveAllTokens</code> methods that do not return a
* maximum array length.
*
* @param str the String to parse, may be <code>null</code>
* @param separatorChar the separate character
* @param preserveAllTokens if <code>true</code>, adjacent separators are
* treated as empty token separators; if <code>false</code>, adjacent
* separators are treated as one separator.
* @return an array of parsed Strings, <code>null</code> if null String input
*/
private static String[] splitWorker(String str, char separatorChar, boolean preserveAllTokens) {
// Performance tuned for 2.0 (JDK1.4)
if (str == null) {
return null;
}
int len = str.length();
if (len == 0) {
return EMPTY_STRING_ARRAY;
}
List<String> list = new ArrayList<String>();
int i = 0, start = 0;
boolean match = false;
boolean lastMatch = false;
while (i < len) {
if (str.charAt(i) == separatorChar) {
if (match || preserveAllTokens) {
list.add(str.substring(start, i));
match = false;
lastMatch = true;
}
start = ++i;
continue;
}
lastMatch = false;
match = true;
i++;
}
if (match || (preserveAllTokens && lastMatch)) {
list.add(str.substring(start, i));
}
return (String[]) list.toArray(new String[list.size()]);
}
/**
* Performs the logic for the <code>split</code> and
* <code>splitPreserveAllTokens</code> methods that return a maximum array
* length.
*
* @param str the String to parse, may be <code>null</code>
* @param separatorChars the separate character
* @param max the maximum number of elements to include in the
* array. A zero or negative value implies no limit.
* @param preserveAllTokens if <code>true</code>, adjacent separators are
* treated as empty token separators; if <code>false</code>, adjacent
* separators are treated as one separator.
* @return an array of parsed Strings, <code>null</code> if null String input
*/
private static String[] splitWorker(String str, String separatorChars, int max, boolean preserveAllTokens) {
// Performance tuned for 2.0 (JDK1.4)
// Direct code is quicker than StringTokenizer.
// Also, StringTokenizer uses isSpace() not isWhitespace()
if (str == null) {
return null;
}
int len = str.length();
if (len == 0) {
return EMPTY_STRING_ARRAY;
}
List<String> list = new ArrayList<String>();
int sizePlus1 = 1;
int i = 0, start = 0;
boolean match = false;
boolean lastMatch = false;
if (separatorChars == null) {
// Null separator means use whitespace
while (i < len) {
if (Character.isWhitespace(str.charAt(i))) {
if (match || preserveAllTokens) {
lastMatch = true;
if (sizePlus1++ == max) {
i = len;
lastMatch = false;
}
list.add(str.substring(start, i));
match = false;
}
start = ++i;
continue;
}
lastMatch = false;
match = true;
i++;
}
} else if (separatorChars.length() == 1) {
// Optimise 1 character case
char sep = separatorChars.charAt(0);
while (i < len) {
if (str.charAt(i) == sep) {
if (match || preserveAllTokens) {
lastMatch = true;
if (sizePlus1++ == max) {
i = len;
lastMatch = false;
}
list.add(str.substring(start, i));
match = false;
}
start = ++i;
continue;
}
lastMatch = false;
match = true;
i++;
}
} else {
// standard case
while (i < len) {
if (separatorChars.indexOf(str.charAt(i)) >= 0) {
if (match || preserveAllTokens) {
lastMatch = true;
if (sizePlus1++ == max) {
i = len;
lastMatch = false;
}
list.add(str.substring(start, i));
match = false;
}
start = ++i;
continue;
}
lastMatch = false;
match = true;
i++;
}
}
if (match || (preserveAllTokens && lastMatch)) {
list.add(str.substring(start, i));
}
return (String[]) list.toArray(new String[list.size()]);
}
/**
* <p>Splits the provided text into an array, separators specified.
* This is an alternative to using StringTokenizer.</p>
*
* <p>The separator is not included in the returned String array.
* Adjacent separators are treated as one separator.
* For more control over the split use the StrTokenizer class.</p>
*
* <p>A <code>null</code> input String returns <code>null</code>.
* A <code>null</code> separatorChars splits on whitespace.</p>
*
* <pre>
* StringUtils.split(null, *) = null
* StringUtils.split("", *) = []
* StringUtils.split("abc def", null) = ["abc", "def"]
* StringUtils.split("abc def", " ") = ["abc", "def"]
* StringUtils.split("abc def", " ") = ["abc", "def"]
* StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
* </pre>
*
* @param str the String to parse, may be null
* @param separatorChars the characters used as the delimiters,
* <code>null</code> splits on whitespace
* @return an array of parsed Strings, <code>null</code> if null String input
*/
public static String[] split(String str, String separatorChars) {
return splitWorker(str, separatorChars, -1, false);
}
/**
* 判断指定的IP地址是否在IP段里面。
*
* @param ipAddr IP地址
* @param cidrAddr 用CIDR表示法的IP段信息
* @return true/false
*/
public static boolean isIpInRange(String ipAddr, String cidrAddr) {
Matcher matcher = PATTERN_CIDR.matcher(cidrAddr);
if (!matcher.matches()) {
throw new IllegalArgumentException("Invalid CIDR address: " + cidrAddr);
}
int[] minIpParts = new int[4];
int[] maxIpParts = new int[4];
String[] ipParts = matcher.group(1).split("\\.");
int intMask = Integer.parseInt(matcher.group(2));
for (int i = 0; i < ipParts.length; i++) {
int ipPart = Integer.parseInt(ipParts[i]);
if (intMask >= 8) {
minIpParts[i] = ipPart;
maxIpParts[i] = ipPart;
intMask -= 8;
} else if (intMask > 0) {
minIpParts[i] = ipPart >> intMask;
maxIpParts[i] = ipPart | (0xFF >> intMask);
intMask = 0;
} else {
minIpParts[i] = 1;
maxIpParts[i] = 0xFF - 1;
}
}
String[] realIpParts = ipAddr.split("\\.");
for (int i = 0; i < realIpParts.length; i++) {
int realIp = Integer.parseInt(realIpParts[i]);
if (realIp < minIpParts[i] || realIp > maxIpParts[i]) {
return false;
}
}
return true;
}
/**
* 将列表中的对象连接成字符串
*
* @param objs
* @param sep
* @return
*/
public static String join(Iterable<?> objs, String sep) {
StringBuilder buf = new StringBuilder();
join(buf, objs, sep);
return buf.toString();
}
/** 将列表中的对象连接起来。 */
public static void join(StringBuilder buf, Iterable<?> objs, String sep) {
try {
join((Appendable) buf, objs, sep);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/** 将列表中的对象连接起来。 */
public static void join(Appendable buf, Iterable<?> objs, String sep) throws IOException {
if (objs == null) {
return;
}
if (sep == null) {
sep = "";
}
for (Iterator<?> i = objs.iterator(); i.hasNext();) {
buf.append(String.valueOf(i.next()));
if (i.hasNext()) {
buf.append(sep);
}
}
}
}
JsonUtils.java
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
public class JsonUtils {
// 定义jackson对象
private static final ObjectMapper MAPPER = new ObjectMapper();
/**
* 将对象转换成json字符串。
* @param data
* @return
*/
public static String objectToJson(Object data) {
try {
String string = MAPPER.writeValueAsString(data);
return string;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
/**
* 将json结果集转化为对象
*
* @param jsonData json数据
* @param
* @return
*/
public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
try {
T t = MAPPER.readValue(jsonData, beanType);
return t;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将json数据转换成pojo对象list
* <p>Title: jsonToList</p>
* <p>Description: </p>
* @param jsonData
* @param beanType
* @return
*/
public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) {
JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
try {
List<T> list = MAPPER.readValue(jsonData, javaType);
return list;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}