JDK环境变量配置, 以及一些常用Java工具类

一. JDK环境变量配置

1. 位置

我的电脑右键 --> 属性 --> 高级系统设置 --> 环境变量

2. 作用域

环境变量窗口中有用户变量和系统变量, 两者的作用域不同, 前者作用域为当前登录用户, 后者作用域为整个计算机.

3. 配置内容

添加如下三个变量, 如果变量已经存在, 则在已有的变量值后面追加即可, 变量值的每一项内容之间要用英文分号隔开.

变量名 变量值
JAVA_HOME D:Javajdk1.8;
PATH %JAVA_HOME%bin;
CLASSPATH %JAVA_HOME%libtools.jar;

二. Java后台获得客户端IP

import com.alibaba.druid.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;

/**
 * 获取客户端IP地址
 * 
 * @author paulandcode
 * @email paulandcode@gmail.com
 * @date 2017年3月8日 下午12:57:02
 */
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);
        }
        return ip;
    }
}

三. 无参获取Request和Response

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 
 * @author paulandcode
 * @email paulandcode@gmail.com
 * @date 2017年3月8日 下午12:57:02
 */
public class HttpContextUtils {
  /**
   * 获取Request
   */
  public static HttpServletRequest getHttpServletRequest() {
    if(RequestContextHolder.getRequestAttributes()==null){
      return null;
    }
    return ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
  }
  
  /**
   * 获取Response
   */
  public static HttpServletResponse getHttpServletResponse() {
    if(RequestContextHolder.getRequestAttributes()==null){
      return null;
    }
    return ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
  }
}

四. Java代码行数统计

该类须放在src/test/java下

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

/**
 * 
 * @author paulandcode
 * @email paulandcode@gmail.com
 * @date 2017年5月18日 下午13:27:13
 */
public class CodeCounter {
  static long files = 0;
  static long codeLines = 0;
  static long commentLines = 0;
  static long blankLines = 0;
  static ArrayList<File> fileArray = new ArrayList<File>();
  
  /**
   * 获得目录下的文件和子目录下的文件
   * @param f
   * @return
   */
  public static ArrayList<File> getFile(File f) {
    File[] ff = f.listFiles();
    for (File child : ff) {
      if (child.isDirectory()) {
        getFile(child);
      } else
        fileArray.add(child);
    }
    return fileArray;
  }

  /**
   * 统计方法
   * @param f
   */
  private static void count(File f) {
    BufferedReader br = null;
    boolean flag = false;
    try {
      br = new BufferedReader(new FileReader(f));
      String line = "";
      while ((line = br.readLine()) != null) {
        line = line.trim(); // 除去注释前的空格
        if (line.matches("^[ ]*$")) { // 匹配空行
          blankLines++;
        } else if (line.startsWith("//")) {
          commentLines++;
        } else if (line.startsWith("/*") && !line.endsWith("*/")) {
          commentLines++;
          flag = true;
        } else if (line.startsWith("/*") && line.endsWith("*/")) {
          commentLines++;
        } else if (flag == true) {
          commentLines++;
          if (line.endsWith("*/")) {
            flag = false;
          }
        } else {
          codeLines++;
        }
      }
      files++;
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (br != null) {
        try {
          br.close();
          br = null;
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }

  /**
   * 代码行数统计
   */
  public static void main(String[] args) {
    String file = CodeCounter.class.getResource("/").getFile();
    String path = file.replace("target/test-classes", "src");

    ArrayList<File> al = getFile(new File(path));
    for (File f : al) {
      if (f.getName().matches(".*\\.java$")){ // 匹配java格式的文件
        count(f);
        System.out.println(f);
      }
    }
    System.out.println("统计文件:" + files);
    System.out.println("代码行数:" + codeLines);
    System.out.println("注释行数:" + commentLines);
    System.out.println("空白行数:" + blankLines);
  }
}

五. 判断设备类型(PC, 手机等), 浏览器类型(IE, Google等)

1. Maven导包如下

<dependency>
  <groupId>eu.bitwalker</groupId>
  <artifactId>UserAgentUtils</artifactId>
  <version>1.21</version>
</dependency>

2. 工具类如下

import javax.servlet.http.HttpServletRequest;

import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.DeviceType;
import eu.bitwalker.useragentutils.UserAgent;

/**
 * 用户代理字符串识别工具
 * 
 * @author paulandcode
 * @email paulandcode@gmail.com
 * @date 2017年5月18日 下午13:27:13
 */
public class UserAgentUtils {
  /**
   * 获取用户代理对象
   * 
   * @param request
   * @return
   */
  public static UserAgent getUserAgent(HttpServletRequest request) {
    return UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
  }

  /**
   * 获取设备类型
   * 
   * @param request
   * @return
   */
  public static DeviceType getDeviceType(HttpServletRequest request) {
    return getUserAgent(request).getOperatingSystem().getDeviceType();
  }

  /**
   * 是否是PC
   * 
   * @param request
   * @return
   */
  public static boolean isComputer(HttpServletRequest request) {
    return DeviceType.COMPUTER.equals(getDeviceType(request));
  }

  /**
   * 是否是手机
   * 
   * @param request
   * @return
   */
  public static boolean isMobile(HttpServletRequest request) {
    return DeviceType.MOBILE.equals(getDeviceType(request));
  }

  /**
   * 是否是平板
   * 
   * @param request
   * @return
   */
  public static boolean isTablet(HttpServletRequest request) {
    return DeviceType.TABLET.equals(getDeviceType(request));
  }

    /**
   * 是否是手机和平板
     *
   * @param request
   * @return
   */
  public static boolean isMobileOrTablet(HttpServletRequest request){
    DeviceType deviceType = getDeviceType(request);
    return DeviceType.MOBILE.equals(deviceType) || DeviceType.TABLET.equals(deviceType);
  }

  /**
   * 获取浏览类型
   * 
   * @param request
   * @return
   */
  public static Browser getBrowser(HttpServletRequest request) {
    return getUserAgent(request).getBrowser();
  }

  /**
   * 是否是IE版本且小于等于IE8
   * 
   * @param request
   * @return
   */
  public static boolean isLteIE8(HttpServletRequest request) {
    Browser browser = getBrowser(request);
    return Browser.IE5.equals(browser) || Browser.IE6.equals(browser) || Browser.IE7.equals(browser)
        || Browser.IE8.equals(browser);
  }
}

3. 进行拦截并根据需要进行处理

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import org.apache.commons.lang3.StringUtils;
import com.paulandcode.utils.UserAgentUtils;

/**
 * 根据需要进行拦截, 并做不同处理
 * 
 * @author paulandcode
 * @email paulandcode@gmail.com
 * @date 2017年5月18日 下午13:27:13
 */
public class MobileInterceptor implements HandlerInterceptor {
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {
    return true;
  }

  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
      ModelAndView modelAndView) throws Exception {
    if (modelAndView != null) {
      // 如果是手机或平板访问的话,则跳转到手机视图页面。
      if (UserAgentUtils.isMobileOrTablet(request)
          && !StringUtils.startsWithIgnoreCase(modelAndView.getViewName(), "redirect:")) {
        modelAndView.setViewName("mobile/" + modelAndView.getViewName());
      }
    }
  }

  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
      throws Exception {
  }
}

六. 根据日期生成目录

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 根据日期生成目录
 *
 * @author paulandcode
 * @since 2018年7月26日 上午10:33:33
 */
public class DirectoryUtils {
  /**
   * 生成目录
   * return 2018/07/26/1532572300220
   */
  public static String getDir() {
    StringBuilder sb = new StringBuilder("");
    Date date = new Date();
    SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
    String path = format.format(date);
    long time = new Date().getTime();
    sb.append(path).append("/").append(time);
    return sb.toString();
  }
}

七. 根据附件名获得附件类型

1. Maven导包

<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.6</version>
</dependency>

2. 工具类

import org.apache.commons.io.FilenameUtils;

/**
 * 附件类型工具类
 *
 * @author paulandcode
 * @since 2018年7月26日 上午10:57:28
 */
public class FileTypeUtils {
  /**
   * 根据附件名获得附件类型
   * 
   * @param fileName
   * @return
   */
  public static String getFileType(String fileName) {
    if (fileName != null && !"".equals(fileName)) {
      String extension = FilenameUtils.getExtension(fileName);
      if ("jng".equalsIgnoreCase(extension) || "jpg".equalsIgnoreCase(extension)
          || "png".equalsIgnoreCase(extension) || "gif".equalsIgnoreCase(extension)
          || "jpeg".equalsIgnoreCase(extension) || "bmp".equalsIgnoreCase(extension)) {
        return "IMG";
      } else if ("txt".equalsIgnoreCase(extension)) {
        return "TXT";
      } else if ("doc".equalsIgnoreCase(extension) || "docx".equalsIgnoreCase(extension)) {
        return "DOC";
      } else if ("pdf".equalsIgnoreCase(extension)) {
        return "PDF";
      } else if ("xls".equalsIgnoreCase(extension) || "xlsx".equalsIgnoreCase(extension)) {
        return "XLS";
      } else if ("ppt".equalsIgnoreCase(extension) || "pptx".equalsIgnoreCase(extension)) {
        return "PPT";
      } else if ("zip".equalsIgnoreCase(extension)) {
        return "ZIP";
      } else if ("mp3".equalsIgnoreCase(extension)) {
        return "MP3";
      } else if ("mp4".equalsIgnoreCase(extension) || "flv".equalsIgnoreCase(extension)
          || "avi".equalsIgnoreCase(extension)) {
        return "AVI";
      } else if ("HTML".equalsIgnoreCase(extension)) {
        return "HTM";
      } else if ("VSD".equalsIgnoreCase(extension)) {
        return "VSD";
      } else {
        return "OTHER";
      }
    }
    return "";
  }
}

八. 附件上传下载

1. web.xml中需要加入如下代码

<context-param>
  <param-name>webAppRootKey</param-name>
  <param-value>webPath</param-value>
</context-param>

2. Java代码如下

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.multipart.MultipartFile;

/**
 * 附件上传下载
 *
 * @author paulandcode
 * @since 2018年7月26日 上午11:20:35
 */
public class FileUtils {
  /**
   * 附件上传
   * 
   * @author Paul
   * @param file
   *            HTML表单上传的附件
   * @param subPath
   *            如: storage/excel
   * @return 附件最终路径
   */
  public static String fileUpload(MultipartFile file, String subPath) {
    // webPath在web.xml中配置, D:\Java\apache-tomcat-9.0.0\webapps\blog\
    String basePath = System.getProperty("webPath");
    // D:/Java/apache-tomcat-9.0.0/webapps/blog/storage/excel
    String path = basePath.replaceAll("\\\\", "/") + subPath;
    // D:/Java/apache-tomcat-9.0.0/webapps/blog/storage/excel/test.xls
    String finalPath = path + "/" + file.getOriginalFilename();
    File dir = new File(path);
    if (!dir.exists()) {
      dir.mkdirs();
    }
    try {
      file.transferTo(new File(finalPath));
    } catch (IOException e) {
      System.out.println("文件: " + file.getOriginalFilename() + "上传失败!");
      e.printStackTrace();
    }
    return finalPath;
  }

  /**
   * 附件下载
   * 
   * @param request
   * @param response
   * @param filePath
   *            项目根目录下的文件路径, 如: storage/excel/test.xls
   * @param fileShowName
   *            下载文件所显示的文件名,需要带后缀名, 如: 测试.xls
   * @return
   */
  public static boolean excelOutTemplate(HttpServletRequest request, HttpServletResponse response, String filePath, String fileShowName) {
    // http://127.0.0.1:8080/blog
    String localPath = request.getServletContext().getRealPath("/");
    // http://127.0.0.1:8080/blog/storage/excel/test.xls
    String finalPath = localPath.endsWith("/") ? (localPath + filePath) : (localPath + "/" + filePath);
    File file = new File(finalPath);
    if (file.exists()) {
      // 防止中文乱码, 设置UTF-8编码
      try {
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileShowName, "UTF-8"));
      } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
      }
      InputStream in = null;
      OutputStream out = null;
      try {
        in = new FileInputStream(finalPath);
        out = response.getOutputStream();
        int b;
        while ((b = in.read()) != -1)
          out.write(b);
      } catch (IOException e) {
        e.printStackTrace();
      } finally {
        try {
          if (in != null)
            in.close();
          if (out != null)
            out.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    } else {
      System.out.println("服务器文件已经不存在了!");
      return false;
    }
    return true;
  }
}

九. 获得UUID

import java.util.UUID;

/**
 * 获得UUID
 *
 * @author paulandcode
 * @since 2018年7月26日 下午3:00:24
 */
public class IDUtils {
  /**
   * UUID
   * @return
   */
  public static String getId() {
    String id = UUID.randomUUID().toString();
    id = id.replace("-", "");
    return id;
  }
}

十. 自定义异常类

/**
 * 自定义异常
 *
 * @author paulandcode
 * @since 2018年7月26日 下午4:05:28
 */
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;
  }
}

十一. 字符串首字母大写

/**
 * 字符串首字母大写
 *
 * @author paulandcode
 * @since 2018年7月26日 下午4:29:19
 */
public class StringUtils {
  /**
   * 字符串首字母大写
   */
  public static String captureName(String name) {
        char[] cs=name.toCharArray();
        cs[0]-=32;
        return String.valueOf(cs);
    }
}

十二. List乱序与按照汉字拼音排序

import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;

/**
 * List乱序与按照汉字拼音排序
 *
 * @author paulandcode
 * @since 2018年7月26日 下午3:10:55
 */
public class ListUtils {
  /**
   * List乱序
   * @param sourceList
   * @return
   */
  public static <V> List<V> randomList(List<V> sourceList) {  
      if (sourceList == null || sourceList.size() == 0) {  
          return sourceList;  
      }  
      List<V> random = new ArrayList<V>(sourceList.size());  
      do {  
          int index = Math.abs(new Random().nextInt(sourceList.size()));  
          random.add(sourceList.remove(index));  
      } while (sourceList.size() > 0);  
      return random;  
  }
  
  /**
   * List按照汉字拼音排序, 根据需要重写V的toString()方法
   * @param sourceList
   * @return
   */
  public static <V> List<V> sortList(List<V> sourceList) {  
      if (sourceList == null || sourceList.size() == 0) {  
          return sourceList;  
      }  
      List<V> sort = new ArrayList<V>(sourceList.size());
      sort.addAll(sourceList);
      Collections.sort(sort, new Comparator<V>(){
        @Override
            public int compare(V v0, V v1) {
              List<String> list = new ArrayList<String>(2);
              list.add(v0.toString());
              list.add(v1.toString());
              Collections.sort(list, Collator.getInstance(java.util.Locale.CHINA));
              return list.indexOf(v0.toString()) == 0 ? -1 : 1;
            }
        });
      return sort;  
  }
}

十三. Redis工具类

1. properties配置文件

# redis 配置文件
redis.hostName=127.0.0.1
redis.port=6379
redis.timeout=36000
redis.usePool=true 
redis.maxIdle=6
redis.minEvictableIdleTimeMillis=300000
redis.numTestsPerEvictionRun=3
redis.timeBetweenEvictionRunsMillis=60000

2. Spring添加配置文件

<!-- 配置redis -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
  <!-- <property name="maxIdle" value="6"></property> <property name="minEvictableIdleTimeMillis" 
    value="300000"></property> <property name="numTestsPerEvictionRun" value="3"></property> 
    <property name="timeBetweenEvictionRunsMillis" value="60000"></property> -->
  <property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}"></property>
  <property name="maxIdle" value="${redis.maxIdle}"></property>
  <property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}"></property>
  <property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}"></property>
</bean>
<bean id="jedisConnectionFactory"
  class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
  destroy-method="destroy">
  <property name="poolConfig" ref="jedisPoolConfig"></property>
  <property name="hostName" value="${redis.hostName}"></property>
  <property name="port" value="${redis.port}"></property>
  <property name="timeout" value="${redis.timeout}"></property>
  <property name="usePool" value="${redis.usePool}"></property>
</bean>
<bean id="jedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
  <property name="connectionFactory" ref="jedisConnectionFactory"/>
  <property name="keySerializer">
    <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
  </property>
  <property name="valueSerializer">
    <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
  </property>
</bean>

3. Maven依赖

<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-redis</artifactId>
  <version>1.6.2.RELEASE</version>
</dependency>
<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>2.9.0</version>
</dependency>

4. Redis工具类

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

/**
 * redis缓存存储与获取
 *
 * @author paulandcode
 * @since 2018年3月8日 下午2:56:46
 */
@Service
public class RedisCacheUtil {
  @Autowired
  @Qualifier("jedisTemplate")
  public RedisTemplate<Object, Object> redisTemplate;

  /**
   * 缓存基本的对象,Integer,String,实体类等
   * 
   * @param key
   * @param value
   */
  public <K, V> void setCacheObject(K key, V value) {
    redisTemplate.boundValueOps(key).set(value);
  }

  /**
   * 获得缓存的基本对象
   * 
   * @param key
   * @return
   */
  @SuppressWarnings("unchecked")
  public <K, V> V getCacheObject(K key) {
    return (V) redisTemplate.boundValueOps(key).get();
  }

  /**
   * 缓存List
   * 
   * @param key
   * @param dataList
   */
  public <K, V> void setCacheList(K key, List<V> dataList) {
    redisTemplate.delete(key);
    for (V v : dataList) {
      redisTemplate.boundListOps(key).rightPush(v);
    }
  }

  /**
   * 获得缓存的List
   * 
   * @param key
   * @return
   */
  @SuppressWarnings("unchecked")
  public <K, V> List<V> getCacheList(K key) {
    BoundListOperations<K, V> listOperation = (BoundListOperations<K, V>) redisTemplate.boundListOps(key);
    return listOperation.range(0, listOperation.size());
  }

  /**
   * 缓存Set
   * 
   * @param key
   * @param dataSet
   */
  @SuppressWarnings("unchecked")
  public <K, V> void setCacheSet(K key, Set<V> dataSet) {
    redisTemplate.delete(key);
    BoundSetOperations<K, V> setOperation = (BoundSetOperations<K, V>) redisTemplate.boundSetOps(key);
    Iterator<V> it = dataSet.iterator();
    while (it.hasNext()) {
      setOperation.add(it.next());
    }
  }

  /**
   * 获得缓存的Set
   * 
   * @param key
   * @return
   */
  @SuppressWarnings("unchecked")
  public <K, V> Set<V> getCacheSet(K key) {
    return (Set<V>) redisTemplate.boundSetOps(key).members();
  }

  /**
   * 缓存Map
   * 
   * @param key
   * @param dataMap
   */
  public <K, HK, HV> void setCacheMap(K key, Map<HK, HV> dataMap) {
    redisTemplate.delete(key);
    redisTemplate.boundHashOps(key).putAll(dataMap);
  }

  /**
   * 获得缓存的Map
   * 
   * @param key
   * @return
   */
  @SuppressWarnings("unchecked")
  public <K, HK, HV> Map<HK, HV> getCacheMap(K key) {
    return (Map<HK, HV>) redisTemplate.boundHashOps(key).entries();
  }

  /**
   * 根据key删除对应的缓存
   * 
   * @param key, 若key为String, key支持通配符
   */
  public <K> void deleteByKey(K key) {
    redisTemplate.delete(redisTemplate.keys(key));
  }
}

十四. 判断是否是中文

/**
 * 判断是否是中文.
 *
 * @author paulandcode
 * @since 2018年7月26日 下午4:29:19
 */
public class CharUtils {
  /**
   * 
   * 判断中文汉字和符号是否是中文.
   * @param strName 字符串
   * @return 字符串是否是中文
   */
  public static boolean isChinese(String strName) {
    char[] ch = strName.toCharArray();
    for (int i = 0; i < ch.length; i++) {
      char c = ch[i];
      if (isChinese(c)) {
        return true;
      }
    }
    return false;
  }

  /**
   * 
   * 根据Unicode编码判断中文汉字和符号是否是中文.
   * @param c 字符
   * @return 字符是否是中文
   */
  private static boolean isChinese(char c) {
    Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
    if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
        || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
        || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
        || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
        || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
        || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
        || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
      return true;
    }
    return false;
  }
}

十五. 异常拦截处理

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authz.AuthorizationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;

/**
 * 异常拦截处理
 *
 * @author paulandcode
 * @since 2018年7月26日 下午4:15:52
 */
@Component
public class RRExceptionHandler implements HandlerExceptionResolver {
  private Logger logger = LoggerFactory.getLogger(getClass());
  
  @Override
  public ModelAndView resolveException(HttpServletRequest request,
      HttpServletResponse response, Object handler, Exception ex) {
    R r = new R();
    try {
      response.setContentType("application/json;charset=utf-8");
      response.setCharacterEncoding("utf-8");

      
      if (ex instanceof RRException) {
        r.put("code", ((RRException) ex).getCode());
        r.put("msg", ((RRException) ex).getMessage());
        r.put("tip", ((RRException) ex).getMessage());
      }else if(ex instanceof DuplicateKeyException){
        r = R.error("数据库中已存在该记录");
      }else if(ex instanceof AuthorizationException){
        r = R.error("没有权限,请联系管理员授权").put("tip", "没有权限,请联系管理员授权").put("content", null);
      }else{
        r = R.error();
      }
      
      //记录异常日志
      logger.error(ex.getMessage(), ex);
      
      String json = JSON.toJSONString(r);
      response.getWriter().print(json);
    } catch (Exception e) {
      logger.error("RRExceptionHandler 异常处理失败", e);
      e.printStackTrace();
    }
    return new ModelAndView();
  }
}

十六. Cookie工具类

import java.io.UnsupportedEncodingException;  
import java.net.URLDecoder;  
import java.net.URLEncoder;  
import javax.servlet.http.Cookie;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;

/**
 * Cookie工具类
 *
 * @author paulandcode
 * @since 2018年7月26日 下午4:15:52
 */
public class CookieUtils {
   /** 
     * 得到Cookie的值, 不编码 
     *  
     * @param request 
     * @param cookieName 
     * @return 
     */  
    public static String getCookieValue(HttpServletRequest request, String cookieName) {  
        return getCookieValue(request, cookieName, false);  
    }  
  
    /** 
     * 得到Cookie的值
     *  
     * @param request 
     * @param cookieName 
     * @return 
     */  
    public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {  
        Cookie[] cookieList = request.getCookies();  
        if (cookieList == null || cookieName == null) {  
            return null;  
        }  
        String retValue = null;  
        try {  
            for (int i = 0; i < cookieList.length; i++) {  
                if (cookieList[i].getName().equals(cookieName)) {  
                    if (isDecoder) {  
                        retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");  
                    } else {  
                        retValue = cookieList[i].getValue();  
                    }  
                    break;  
                }  
            }  
        } catch (UnsupportedEncodingException e) {  
            e.printStackTrace();  
        }  
        return retValue;  
    }  
  
    /** 
     * 得到Cookie的值
     *  
     * @param request 
     * @param cookieName 
     * @return 
     */  
    public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {  
        Cookie[] cookieList = request.getCookies();  
        if (cookieList == null || cookieName == null) {  
            return null;  
        }  
        String retValue = null;  
        try {  
            for (int i = 0; i < cookieList.length; i++) {  
                if (cookieList[i].getName().equals(cookieName)) {  
                    retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);  
                    break;  
                }  
            }  
        } catch (UnsupportedEncodingException e) {  
             e.printStackTrace();  
        }  
        return retValue;  
    }  
  
    /**
     *   
     * 设置Cookie的值 不设置生效时间默认浏览器关闭即失效,也不编码.
     * @param request
     * @param response
     * @param cookieName
     * @param cookieValue
     */
    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,  
            String cookieValue) {  
        setCookie(request, response, cookieName, cookieValue, -1);  
    }  
  
    /**
     *   
     * 设置Cookie的值 在指定时间内生效,但不编码.
     * @param request
     * @param response
     * @param cookieName
     * @param cookieValue
     * @param cookieMaxage cookie生效的最大秒数 
     */
    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,  
            String cookieValue, int cookieMaxage) {  
        setCookie(request, response, cookieName, cookieValue, cookieMaxage, false);  
    }  
  
    /**
     *   
     * 设置Cookie的值 不设置生效时间,但编码.
     * @param request
     * @param response
     * @param cookieName
     * @param cookieValue
     * @param isEncode
     */
    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,  
            String cookieValue, boolean isEncode) {  
        setCookie(request, response, cookieName, cookieValue, -1, isEncode);  
    }  
  
    /**
     *   
     * 设置Cookie的值 在指定时间内生效, 编码参数.
     * @param request
     * @param response
     * @param cookieName
     * @param cookieValue
     * @param cookieMaxage cookie生效的最大秒数 
     * @param isEncode 是否编码
     */
    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,  
            String cookieValue, int cookieMaxage, boolean isEncode) {  
        doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, isEncode);  
    }  
  
    /** 
     * 设置Cookie的值 在指定时间内生效, 编码参数(指定编码) 
     */  
    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,  
            String cookieValue, int cookieMaxage, String encodeString) {  
        doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, encodeString);  
    }  
  
    /**
     *   
     * 删除Cookie.
     * @param request
     * @param response
     * @param cookieName
     */
    public static void deleteCookie(HttpServletRequest request, HttpServletResponse response,  
            String cookieName) {  
        doSetCookie(request, response, cookieName, "", -1, false);  
    }  
  
    /** 
     * 设置Cookie的值,并使其在指定时间内生效 
     *  
     * @param cookieMaxage cookie生效的最大秒数 
     */  
    private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,  
            String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {  
        try {  
            if (cookieValue == null) {  
                cookieValue = "";  
            } else if (isEncode) {  
                cookieValue = URLEncoder.encode(cookieValue, "utf-8");  
            }  
            Cookie cookie = new Cookie(cookieName, cookieValue);  
            if (cookieMaxage > 0)  
                cookie.setMaxAge(cookieMaxage);  
            if (null != request) {// 设置域名的cookie  
                String domainName = getDomainName(request);  
                System.out.println(domainName);  
                if (!"localhost".equals(domainName)) {  
                    //cookie.setDomain(domainName);  
                }  
            }  
            cookie.setPath("/");  
            response.addCookie(cookie);  
        } catch (Exception e) {  
             e.printStackTrace();  
        }  
    }  
  
    /** 
     * 设置Cookie的值,并使其在指定时间内生效 
     *  
     * @param cookieMaxage cookie生效的最大秒数 
     */  
    private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,  
            String cookieName, String cookieValue, int cookieMaxage, String encodeString) {  
        try {  
            if (cookieValue == null) {  
                cookieValue = "";  
            } else {  
                cookieValue = URLEncoder.encode(cookieValue, encodeString);  
            }  
            Cookie cookie = new Cookie(cookieName, cookieValue);  
            if (cookieMaxage > 0)  
                cookie.setMaxAge(cookieMaxage);  
            if (null != request) {// 设置域名的cookie  
                String domainName = getDomainName(request);  
                System.out.println(domainName);  
                if (!"localhost".equals(domainName)) {  
                    //本地测试的时候不要写.实际发布时在打开  
                    //cookie.setDomain(domainName);  
                }  
            }  
            cookie.setPath("/");  
            response.addCookie(cookie);  
        } catch (Exception e) {  
             e.printStackTrace();  
        }  
    }  
  
    /** 
     * 得到cookie的域名 
     */  
    private static final String getDomainName(HttpServletRequest request) {  
        String domainName = null;  
  
        String serverName = request.getRequestURL().toString();  
        if (serverName == null || serverName.equals("")) {  
            domainName = "";  
        } else {  
            final int end = serverName.lastIndexOf("/");  
            serverName = serverName.substring(0, end);  
            final String[] domains = serverName.split("\\.");  
            int len = domains.length;  
            if (len > 3) {  
                // www.xxx.com.cn  
                domainName = "." + domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];  
            } else if (len <= 3 && len > 1) {  
                // xxx.com or xxx.cn  
                domainName = "." + domains[len - 2] + "." + domains[len - 1];  
            } else {  
                domainName = serverName;  
            }  
        }  
  
        if (domainName != null && domainName.indexOf(":") > 0) {  
            String[] ary = domainName.split("\\:");  
            domainName = ary[0];  
        }  
        return domainName;  
    } 
}

十七. 日期处理

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 日期处理
 * 
 * @author paulandcode
 * @email paulandcode@gmail.com
 * @date 2017年5月18日 下午13:27:13
 */
public class DateUtils {
  public final static String DATE_PATTERN = "yyyy-MM-dd";
  public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

  /**
   * 
   * 默认按照"yyyy-MM-dd"格式化日期.
   * @param date
   * @return
   */
  public static String format(Date date) {
    return format(date, DATE_PATTERN);
  }

  /**
   * 
   * 按照指定的日期格式来格式化日期.
   * @param date
   * @param pattern 日期格式
   * @return
   */
  public static String format(Date date, String pattern) {
    if (date != null) {
      SimpleDateFormat df = new SimpleDateFormat(pattern);
      return df.format(date);
    }
    return null;
  }

  /**
   * 返回给定日期所在月的所有日期集合
   * 
   * @param date
   * @return
   */
  public static List<Date> getAllDatesOfMonth(Date date) {
    List<Date> list = new ArrayList<Date>();
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    cal.set(Calendar.DATE, 1);
    int month = cal.get(Calendar.MONTH);
    while (cal.get(Calendar.MONTH) == month) {
      list.add(cal.getTime());
      cal.add(Calendar.DATE, 1);
    }
    return list;
  }

  /**
   * 判断两个日期是否是同一天
   * 
   * @param date1
   * @param date2
   * @return
   */
  public static boolean isSameDate(Date date1, Date date2) {
    Calendar cal1 = Calendar.getInstance();
    cal1.setTime(date1);
    Calendar cal2 = Calendar.getInstance();
    cal2.setTime(date2);
    boolean isSameYear = cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR);
    boolean isSameMonth = isSameYear && cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH);
    boolean isSameDate = isSameMonth && cal1.get(Calendar.DAY_OF_MONTH) == cal2.get(Calendar.DAY_OF_MONTH);
    return isSameDate;
  }

  /**
   * 
   * 计算两个日期之间相差多少天
   * 
   * @param date1
   * @param date2
   * @return
   * @throws ParseException
   */
  public static int getDateSpace(Date date1, Date date2) {
    Calendar calst = Calendar.getInstance();
    Calendar caled = Calendar.getInstance();
    calst.setTime(date1);
    caled.setTime(date2);

    // 设置时间为0时
    calst.set(Calendar.HOUR_OF_DAY, 0);
    calst.set(Calendar.MINUTE, 0);
    calst.set(Calendar.SECOND, 0);
    caled.set(Calendar.HOUR_OF_DAY, 0);
    caled.set(Calendar.MINUTE, 0);
    caled.set(Calendar.SECOND, 0);
    // 得到两个日期相差的天数
    return ((int) (caled.getTime().getTime() / 1000) - (int) (calst.getTime().getTime() / 1000)) / 3600 / 24;
  }
}

十八. HttpClient工具类(通过Java后台进行Http访问)

1. Maven导包

<dependency>  
    <groupId>org.apache.httpcomponents</groupId>  
    <artifactId>httpclient</artifactId>  
    <version>4.3.1</version>  
</dependency>  
<dependency>  
    <groupId>org.apache.httpcomponents</groupId>  
    <artifactId>httpcore</artifactId>  
    <version>4.3.1</version>  
</dependency>  
<dependency>  
    <groupId>org.apache.httpcomponents</groupId>  
    <artifactId>httpmime</artifactId>  
    <version>4.3.1</version>  
</dependency>

2. Java代码

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.CharsetUtils;
import org.apache.http.util.EntityUtils;

/**
 * HttpClient工具类
 *
 * @author paulandcode
 * @since 2018年7月26日 下午2:35:09
 */
public class HttpClientUtils {
  /**
   * 成功状态码
   */
  private static final int SUCCESS = 200;

  /**
   * HttpClient连接SSL,需要导入证书的方法 若SSL需要导入信任的证书,使用该方法
   * 
   * @param url
   */
  public static void ssl(String url) {
    CloseableHttpClient httpclient = null;
    try {
      KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
      FileInputStream instream = new FileInputStream(new File("E:\\tomcat.keystore"));
      try {
        // 加载keyStore d:\\tomcat.keystore
        trustStore.load(instream, "123456".toCharArray());
      } catch (CertificateException e) {
        e.printStackTrace();
      } finally {
        try {
          instream.close();
        } catch (Exception ignore) {
        }
      }
      // 相信自己的CA和所有自签名的证书
      SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy())
          .build();
      // 只允许使用TLSv1协议
      SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" },
          null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
      httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
      // 创建http请求(get方式)
      HttpGet httpget = new HttpGet(url);
      System.out.println("executing request" + httpget.getRequestLine());
      CloseableHttpResponse response = httpclient.execute(httpget);
      try {
        HttpEntity entity = response.getEntity();
        System.out.println("----------------------------------------");
        System.out.println(response.getStatusLine());
        if (entity != null) {
          System.out.println("Response content length: " + entity.getContentLength());
          System.out.println(EntityUtils.toString(entity));
          EntityUtils.consume(entity);
        }
      } finally {
        response.close();
      }
    } catch (ParseException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } catch (KeyManagementException e) {
      e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    } catch (KeyStoreException e) {
      e.printStackTrace();
    } finally {
      if (httpclient != null) {
        try {
          httpclient.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }

  /**
   * 不需要导入证书,SSL信任所有证书,使用该方法
   * 
   * @return
   */
  public static CloseableHttpClient createSSLClientDefault() {
    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);
      return HttpClients.custom().setSSLSocketFactory(sslsf).build();

    } catch (KeyManagementException e) {

      e.printStackTrace();

    } catch (NoSuchAlgorithmException e) {

      e.printStackTrace();

    } catch (KeyStoreException e) {

      e.printStackTrace();

    }
    return HttpClients.createDefault();

  }

  /**
   * HttpClient连接SSL,不需要导入证书 信任所有证书,跳过证书验证
   * 
   * @param url
   */
  public static void ssl2(String url) {
    CloseableHttpClient httpclient = null;
    try {

      httpclient = createSSLClientDefault();
      // 创建http请求(get方式)
      HttpGet httpget = new HttpGet(url);
      System.out.println("executing request" + httpget.getRequestLine());
      CloseableHttpResponse response = httpclient.execute(httpget);
      try {
        HttpEntity entity = response.getEntity();
        System.out.println("----------------------------------------");
        System.out.println(response.getStatusLine());
        if (entity != null) {
          System.out.println("Response content length: " + entity.getContentLength());
          System.out.println(EntityUtils.toString(entity));
          EntityUtils.consume(entity);
        }
      } finally {
        response.close();
      }
    } catch (ParseException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (httpclient != null) {
        try {
          httpclient.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }

  /**
   * 关闭HttpClient的客户端和响应
   *
   * @param client 客户端
   * @param response 响应
   * @return void
   */
  private static void closeClientAndResponse(CloseableHttpClient client, CloseableHttpResponse response) {
      try {
          if (response != null) {
              response.close();
          }
          if (client != null) {
              client.close();
          }
      } catch (IOException e) {
          e.printStackTrace();
      }
  }

  /**
   * HttpClient模拟浏览器进行Get请求
   *
   * @param url 请求路径, 示例: http://localhost:8080/api/testget
   * @param params 请求参数
   * @return java.util.Map<java.lang.String,java.lang.String>
   */
  public static Map<String, String> doGet(String url, Map<String, String> params) {
      Map<String, String> result = new HashMap<>(2);
      result.put("code", "200");
      CloseableHttpClient client = null;
      CloseableHttpResponse response = null;
      try {
          //创建一个httpclient对象
          client = HttpClients.createDefault();
          //创建URIBuilder
          URIBuilder uri = new URIBuilder(url);
          //设置参数
          if (params != null) {
              Set<Map.Entry<String, String>> entries = params.entrySet();
              for (Map.Entry<String, String> entry : entries) {
                  uri.addParameter(entry.getKey(), entry.getValue());
              }
          }
          //创建httpGet对象
          HttpGet hg = new HttpGet(uri.build());
          //设置请求的报文头部的编码
          hg.setHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"));
          //设置期望服务端返回的编码
          hg.setHeader(new BasicHeader("Accept", "application/json;charset=utf-8"));
          //请求服务
          response = client.execute(hg);
          //获取响应码
          int statusCode = response.getStatusLine().getStatusCode();
          if (statusCode == SUCCESS) {
              // 通过EntityUtils的一个工具方法获取返回内容
              String resStr = EntityUtils.toString(response.getEntity(), "utf-8");
              result.put("data", resStr);
          } else {
              result.put("code", statusCode + "");
          }
      } catch (URISyntaxException | IOException e) {
          e.printStackTrace();
      } finally {
          //关闭response和client
          closeClientAndResponse(client, response);
      }
      return result;
  }

  /**
   * HttpClient模拟浏览器进行Post请求
   *
   * @param url 请求路径, 示例: http://localhost:8080/api/testget
   * @param params 请求参数
   * @return java.util.Map<java.lang.String,java.lang.String>
   */
  public static Map<String, String> doPost(String url, Map<String, String> params){
      Map<String, String> result = new HashMap<>(2);
      result.put("code", "200");
      CloseableHttpClient client = null;
      CloseableHttpResponse response = null;
      try {
          //创建一个httpclient对象
          client = HttpClients.createDefault();
          //创建一个post对象
          HttpPost post = new HttpPost(url);
          //创建一个Entity,模拟表单数据
          List<NameValuePair> formList = new ArrayList<>();
          //添加表单数据
          if (params != null) {
              Set<Map.Entry<String, String>> entries = params.entrySet();
              for (Map.Entry<String, String> entry : entries) {
                  formList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
              }
          }
          //包装成一个Entity对象
          StringEntity entity = new UrlEncodedFormEntity(formList, "utf-8");
          //设置请求的内容
          post.setEntity(entity);
          //设置请求的报文头部的编码
          post.setHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"));
          //设置期望服务端返回的编码
          post.setHeader(new BasicHeader("Accept", "application/json;charset=utf-8"));
          //执行post请求
          response = client.execute(post);
          //获取响应码
          int statusCode = response.getStatusLine().getStatusCode();
          if (statusCode == SUCCESS) {
              //获取数据
              String resStr = EntityUtils.toString(response.getEntity(), "utf-8");
              result.put("data", resStr);
          } else {
              result.put("code", statusCode + "");
          }
      } catch (IOException e) {
          e.printStackTrace();
      } finally {
          //关闭response和client
          closeClientAndResponse(client, response);
      }
      return result;
  }

  /**
   * 上传文件
   */
  public static void upload(String url) {
    CloseableHttpClient httpclient = HttpClients.createDefault();
    try {
      HttpPost httppost = new HttpPost(url);
      FileBody bin = new FileBody(new File("C:\\Users\\zhangwenchao\\Desktop\\jinzhongzi.jpg"));
      // StringBody name = new StringBody("这个一测试",
      // ContentType.TEXT_PLAIN);
      HttpEntity reqEntity = MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
          .addPart("uploadFile", bin).setCharset(CharsetUtils.get("UTF-8")).build();
      httppost.setEntity(reqEntity);
      System.out.println("executing request: " + httppost.getRequestLine());
      CloseableHttpResponse response = httpclient.execute(httppost);

      // httppost = new
      // HttpPost(response.getLastHeader("location").getValue());
      // response = httpclient.execute(httppost);
      try {
        System.out.println("----------------------------------------");
        System.out.println(response.getStatusLine());
        HttpEntity resEntity = response.getEntity();
        if (resEntity != null) {
          // 响应长度
          System.out.println("Response content length: " + resEntity.getContentLength());
          // 打印响应内容
          System.out.println("Response content: " + EntityUtils.toString(resEntity));
        }
        // 销毁
        EntityUtils.consume(resEntity);
      } finally {
        response.close();
      }
    } catch (ClientProtocolException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        httpclient.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  /**
   * 文件下载
   */
  public static void download(String url) {
    // 生成一个httpclient对象
    CloseableHttpClient httpclient = HttpClients.createDefault();
    try {
      HttpGet httpget = new HttpGet(url);
      CloseableHttpResponse response = httpclient.execute(httpget);
      HttpEntity resEntity = response.getEntity();
      if (resEntity != null) {
        // 响应长度
        System.out.println("Response content length: " + resEntity.getContentLength());
        InputStream in = resEntity.getContent();
        String fileName = url.substring(url.lastIndexOf("/"));
        File file = new File("E:\\" + fileName);
        try {
          FileOutputStream fout = new FileOutputStream(file);
          int l = -1;
          byte[] tmp = new byte[1024];
          while ((l = in.read(tmp)) != -1) {
            fout.write(tmp, 0, l);
            // 注意这里如果用OutputStream.write(buff)的话,图片会失真,大家可以试试
          }
          fout.flush();
          fout.close();
        } finally {
          // 关闭低层流。
          in.close();
        }
      }
    } catch (ClientProtocolException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        httpclient.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
}

十九. 分页工具类

import java.io.Serializable;
import java.util.List;

/**
 * 分页工具类
 * 
 * @author paulandcode
 * @email paulandcode@gmail.com
 * @date 2017年5月18日 下午13:27:13
 */
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 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;
  } 
}

二十. SQL查询工具类

1. SQL过滤

import org.apache.commons.lang.StringUtils;

/**
 * SQL过滤
 *
 * @author paulandcode
 * @since 2018年7月26日 下午4:29:19
 */
public class SQLFilter {
  /**
   * 
   * SQL注入过滤.
   * @param str 待验证的字符串
   * @return 过滤后字符串
   */
    public static String sqlInject(String str){
        if(StringUtils.isBlank(str)){
            return str;
        }
        //去掉'|"|;|\字符
        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", "alert", "drop"};

        //判断是否包含非法字符
        for(String keyword : keywords){
            if(str.contains(keyword)){
                throw new RuntimeException("包含非法字符");
            }
        }

        return str;
    }
}

2. SQL查询

import com.paulandcode.utils.SQLFilter;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * SQL查询.
 *
 * @author paulandcode
 * @since 2018年7月26日 下午4:29:19
 */
public class Q extends LinkedHashMap<String, Object> {
  private static final long serialVersionUID = 1L;
  //当前页码
    private int page;
    //每页条数
    private int limit;

    /**
     * 
     * 构造函数.
     * @param params
     */
    public Q(Map<String, Object> params){
        this.putAll(params);
        String sidx = "";
        String order = "";
        if(params.get("page")!=null) {
          this.page = Integer.parseInt(params.get("page").toString());
        }
        if(params.get("limit")!=null) {
          this.limit = Integer.parseInt(params.get("limit").toString());
        }
        if(params.get("sidx")!=null) {
          sidx = params.get("sidx").toString();
        }
        if(params.get("order")!=null) {
          order = params.get("order").toString();
        }
        //分页参数
        this.put("offset", (page - 1) * limit);
        this.put("page", page);
        this.put("limit", limit);
        if(params.get("limit")==null) {
          this.put("limit", null);
        }

        //防止SQL注入(因为sidx、order是通过拼接SQL实现排序的,会有SQL注入风险)
        // sidx为排序字段, 以英文逗号隔开
        this.put("sidx", SQLFilter.sqlInject(sidx));
        // order为排序方式, DESC或ASC
        this.put("order", SQLFilter.sqlInject(order));
    }

    /**
     * 
     * 构造函数.
     */
    public Q() {
        this.put("page", page);
        this.put("limit", null);
        this.put("sidx", "");
        this.put("order", "");
    }

    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public int getLimit() {
        return limit;
    }

    public void setLimit(int limit) {
        this.limit = limit;
    }
}

3. mapper文件中查询列表可以这么写

<select id="queryList" parameterType="map" resultType="com.paulandcode.entity.Test">
  SELECT
    id,
    name
  FROM test
  <choose>
  <when test="sidx.trim() != '' and sidx.trim() != ''">
    ORDER BY ${sidx} ${order}
  </when>
  <otherwise>
    ORDER BY id DESC
  </otherwise>
  </choose>
  <if test="offset != null and limit != null">
    LIMIT #{offset}, #{limit}
  </if>
</select>

二十一. Shiro工具类

1. Maven导包

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.3.2</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.3.2</version>
</dependency>
<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-ehcache</artifactId>
  <version>1.3.2</version>
</dependency>

2. 工具类

import com.paulandcode.entity.SysUserEntity;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;

/**
 * Shiro工具类
 *
 * @author paulandcode
 * @since 2018年7月26日 下午4:29:19
 */
public class ShiroUtils {
  /**
   * 
   * 获得ShiroSession.
   * @return
   */
  public static Session getSession() {
    return SecurityUtils.getSubject().getSession();
  }

  /**
   * 
   * 获得Subject.
   * @return
   */
  public static Subject getSubject() {
    return SecurityUtils.getSubject();
  }

  /**
   * 
   * 获得Princpal, 此处的SysUserEntity是自定义UserRealm中的doGetAuthenticationInfo方法中设置的.
   * @return
   */
  public static SysUserEntity getUserEntity() {
    return (SysUserEntity)SecurityUtils.getSubject().getPrincipal();
  }

  /**
   * 
   * 获得用户id.
   * @return
   */
  public static Long getUserId() {
    return getUserEntity().getUserId();
  }
  
  /**
   * 
   * ShiroSession中放置某个键值对
   * @param key
   * @param value
   */
  public static void setSessionAttribute(Object key, Object value) {
    getSession().setAttribute(key, value);
  }

  /**
   * 
   * 获得ShiroSession中某个键值对
   * @param key
   * @return
   */
  public static Object getSessionAttribute(Object key) {
    return getSession().getAttribute(key);
  }

  /**
   * 
   * 是否已经登录.
   * @return
   */
  public static boolean isLogin() {
    return SecurityUtils.getSubject().getPrincipal() != null;
  }

  /**
   * 
   * 退出登录.
   */
  public static void logout() {
    SecurityUtils.getSubject().logout();
  }
  
  /**
   * 
   * 获得验证码, 获得一次后, 从ShiroSession中移除, 无法再次获得.
   * @param key
   * @return
   */
  public static String getKaptcha(String key) {
    String kaptcha = getSessionAttribute(key).toString();
    getSession().removeAttribute(key);
    return kaptcha;
  }
}

二十二. SpringContext工具类

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * SpringContext 工具类
 *
 * @author paulandcode
 * @since 2018年7月26日 下午4:29:19
 */
@Component
public class SpringContextUtils implements ApplicationContextAware {
    public static ApplicationContext applicationContext; 

    /**
     *
     * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        SpringContextUtils.applicationContext = applicationContext;
    }

    /**
     * 
     * 获得Bean.
     * @param name Bean的名称
     * @return
     */
    public static Object getBean(String name) {
        return applicationContext.getBean(name);
    }

    /**
     * 
     * 获得Bean.
     * @param name Bean的名称
     * @param requiredType 类型
     * @return
     */
    public static <T> T getBean(String name, Class<T> requiredType) {
        return applicationContext.getBean(name, requiredType);
    }

    /**
     * 
     * 是否包含某个Bean.
     * @param name Bean的名称
     * @return
     */
    public static boolean containsBean(String name) {
        return applicationContext.containsBean(name);
    }

    /**
     * 
     * Bean是否是单例.
     * @param name Bean的名称
     * @return
     */
    public static boolean isSingleton(String name) {
        return applicationContext.isSingleton(name);
    }

    /**
     * 
     * Bean的类型.
     * @param name Bean的名称
     * @return
     */
    public static Class<? extends Object> getType(String name) {
        return applicationContext.getType(name);
    }
}

二十三. Properties载入工具类

1. 工具类如下

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Properties;

/**
 * properties载入工具类
 * 
 * @author paulandcode
 * @email paulandcode@gmail.com
 * @date 2017年5月18日 下午13:27:13
 */
public class PropertiesLoader {
  private final Properties properties;

  public PropertiesLoader(String... resourcePaths) {
    properties = loadProperties(resourcePaths);
  }

  /**
   * 载入多个properties文件
   * 
   * @param resourcePaths
   * @return
   */
  private Properties loadProperties(String[] resourcePaths) {
    Properties props = new Properties();
    for (String location : resourcePaths) {
      InputStreamReader is = null;
      try {
        is = new InputStreamReader(PropertiesLoader.class.getClassLoader().getResourceAsStream(location),
            "UTF-8");
        props.load(is);
      } catch (Exception e) {

      } finally {
        try {
          is.close();
        } catch (IOException e) {
        }
      }
    }
    return props;
  }

  /**
   *  获得字符串参数
   * 
   * @param key
   * @return
   */
  public String getConfig(String key) {
    if (properties.containsKey(key)) {
      return properties.getProperty(key);
    }
    return "";
  }
  
  /**
   * 
   * 获得数字参数 
   * @param key
   * @return
   */
  public int getIntConfig(String key) {
    return Integer.parseInt(getConfig(key));
  }
}

2. 使用

public static PropertiesLoader loader = new PropertiesLoader("config/config.properties");

public void test() {
    String content = loader.getConfig("content");
}

二十四. Java执行Bat命令(或其他命令)

下面代码中的"Bat Finished! "是为了标记Bat执行结束, 可以在Bat文件的最后加入"echo Bat Finished! "来标记Bat执行结束. "Bat Success! "是为了标记Bat执行成功, "Bat Fail! "标记Bat执行失败, 可以将Bat文件进行相应的echo输出达到这样的效果. 这样做的目的是为了让java知道Bat是否成功执行结束, 若程序无需知道是否执行结束, 则Process process = processBuilder.start();这一句代码之后的其他代码可以去掉.

package com.ribeen.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

/**
 * 执行bat命令
 *
 * @author paulandcode paulandcode@gmail.com
 * @date 2018/10/9 14:59
 */
public class BatUtils {
    /**
     * 执行kettle命令
     *
     * @param batPath     bat文件路径, 如: E:/test/test.bat
     * @param args     参数, 最多可以有9个参数, 从左到右代表1到9, 在Bat文件中用1%到9%表示参数
     * @return boolean 执行成功或失败
     */
    public static boolean doBat(String batPath, String... args) {
        boolean result = false;
        String[] command;
        if (args == null || args.length == 0) {
            command = new String[]{batPath};
        } else {
            command = new String[args.length + 1];
            command[0] = batPath;
            System.arraycopy(args, 0, command, 1, args.length);
        }
        ProcessBuilder processBuilder = new ProcessBuilder(command);
        processBuilder.redirectErrorStream(true);
        try {
            Process process = processBuilder.start();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream(),
                    StandardCharsets.UTF_8));
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                System.out.println(line);
                // 如果命令执行结束
                if (line.contains("Bat Finished! ")) {
                    // 执行结束后再执行一行, 表示执行成功或者失败
                    line = bufferedReader.readLine();
                    System.out.println(line);
                    if (line.contains("Bat Success! ")) {
                        result = true;
                    } else if (line.contains("Bat Fail! ")){
                        // 若执行失败, 则默认result为false
                    }
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
}

二十五. 不使用Request获得Web项目的全路径

String path = Test.class.getResource("").getFile();

假如Test.class类文件在blog项目的com/paulandcode/utils目录下, 则上面的path值为:

/D:/Tomcat/webapps/blog/WEB-INF/classes/com/paulandcode/utils/

注意: 得到的值前后都有个斜杠

二十六. 下划线与驼峰相互转换

package com.product.utils;

import java.util.HashMap;
import java.util.Map;

/**
 * 下划线与驼峰相互转换
 *
 * @author paulandcode paulandcode@gmail.com
 * @date 2018/10/4 14:21
 */
public class HumpUtils {
    private static final char UNDERLINE = '_';
    
    /**
     * 数组由下划线转换为驼峰
     *
     * @param arr 带有下划线的数组
     * @return java.util.Map<java.lang.String,V>
     */
    public static String[] arrUnderlineToHump(String[] arr) {
        if (arr == null) {
            return null;
        }
        String[] newArr = new String[arr.length];
        for (int i = 0; i < arr.length; i++) {
            newArr[i] = toHump(arr[i]);
        }
        return newArr;
    }

    /**
     * 数组由驼峰转换为下划线
     *
     * @param arr 带有下划线的数组
     * @return java.util.Map<java.lang.String,V>
     */
    public static String[] arrHumpToUnderline(String[] arr) {
        if (arr == null) {
            return null;
        }
        String[] newArr = new String[arr.length];
        for (int i = 0; i < arr.length; i++) {
            newArr[i] = toUnderline(arr[i]);
        }
        return newArr;
    }

    /**
     * 将Map中的key由下划线转换为驼峰
     *
     * @param map 带有下划线的map
     * @return java.util.Map<java.lang.String,V>
     */
    public static <V> Map<String, V> mapKeyUnderlineToHump(Map<String, V> map) {
        if (map == null) {
            return null;
        }
        Map<String, V> newMap = new HashMap<>(map.size());
        for (Map.Entry<String, V> entry : map.entrySet()) {
            String key = entry.getKey();
            String newKey = toHump(key);
            newMap.put(newKey, entry.getValue());
        }
        return newMap;
    }

    /**
     * 将Map中的key由驼峰转换为下划线
     *
     * @param map 带有驼峰的map
     * @return java.util.Map<java.lang.String,V>
     */
    public static <V> Map<String, V> mapKeyHumpToUnderline(Map<String, V> map) {
        if (map == null) {
            return null;
        }
        Map<String, V> newMap = new HashMap<>(map.size());
        for (Map.Entry<String, V> entry : map.entrySet()) {
            String key = entry.getKey();
            String newKey = toUnderline(key);
            newMap.put(newKey, entry.getValue());
        }
        return newMap;
    }

    /**
     * 下划线转驼峰
     *
     * @param colName 字符串
     * @return java.lang.String
     */
    public static String toHump(String colName) {
        if (colName == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        String[] str = colName.toLowerCase().split(String.valueOf(UNDERLINE));
        for (String s : str) {
            if (s.length() == 1) {
                sb.append(s.toUpperCase());
                continue;
            }
            if (s.length() > 1) {
                sb.append(s.substring(0, 1).toUpperCase());
                sb.append(s.substring(1));
            }
        }
        String result = sb.toString();
        return result.substring(0, 1).toLowerCase() + result.substring(1);
    }

    /**
     * 驼峰转下划线
     *
     * @param colName 字符串
     * @return java.lang.String
     */
    private static String toUnderline(String colName) {
        if (colName == null) {
            return null;
        }
        String result = colName.replaceAll("[A-Z]", String.valueOf(UNDERLINE) + "$0");
        return result.toLowerCase();
    }
}

二十七. Web响应信息工具类

package com.paulandcode.common;

import java.util.HashMap;
import java.util.Map;

/**
 * Web响应信息
 * 前后端通信时一般0或200为正常, 1或500以及其他为异常
 * 数据库中字段的值一般0为false, 1为true
 *
 * @author paulandcode paulandcode@gmail.com
 * @since 2019/3/27 17:23
 */
public class R extends HashMap<String, Object> {
    private static final long serialVersionUID = -7035368021961298846L;

    /**
     * 构造函数, 默认成功.
     */
    private R() {
        put("code", 0);
    }

    /**
     * 响应未知异常.
     *
     * @return com.paulandcode.common.R
     */
    public static R err() {
        return err(1, "未知异常, 请联系管理员! ");
    }

    /**
     * 响应自定义异常信息.
     *
     * @param msg 异常信息
     * @return com.paulandcode.common.R
     */
    public static R err(String msg) {
        return err(1, msg);
    }

    /**
     * 响应自定义异常信息和状态码.
     *
     * @param code 状态码
     * @param msg  异常信息
     * @return com.paulandcode.common.R
     */
    public static R err(int code, String msg) {
        R r = new R();
        r.put("code", code);
        r.put("msg", msg);
        return r;
    }

    /**
     * 响应成功并自定义信息.
     *
     * @param msg 成功信息
     * @return com.paulandcode.common.R
     */
    public static R msg(String msg) {
        R r = new R();
        r.put("msg", msg);
        return r;
    }

    /**
     * 响应成功.
     *
     * @return com.paulandcode.common.R
     */
    public static R ok() {
        return new R();
    }

    /**
     * 响应成功并自定义信息.
     *
     * @param data 成功数据
     * @return com.paulandcode.common.R
     */
    public static R ok(Object data) {
        return ok().data(data);
    }

    /**
     * 响应成功并加入一些键值对.
     *
     * @param map 键值对
     * @return com.paulandcode.common.R
     */
    public static R ok(Map<String, Object> map) {
        R r = new R();
        r.putAll(map);
        return r;
    }

    /**
     * 响应信息移除指定键值对.
     *
     * @param key 键
     * @return com.paulandcode.common.R
     */
    public R remove(String key) {
        super.remove(key);
        return this;
    }

    /**
     * 响应中加入一个键值对.
     *
     * @param key   键
     * @param value 值
     * @return com.paulandcode.common.R
     */
    @Override
    public R put(String key, Object value) {
        super.put(key, value);
        return this;
    }

    /**
     * 放入响应数据
     *
     * @param data 响应数据
     * @return com.paulandcode.common.R
     */
    public R data(Object data) {
        return put("data", data);
    }

    /**
     * 放入数据总数
     *
     * @param count 总数
     * @return com.paulandcode.common.R
     */
    public R count(int count) {
        return put("count", count);
    }
}
上一篇:TO B,阿里先上船


下一篇:百度智能云新架构掀开面纱:知识中台成为差异化竞争优势