项目工具类

Java基础

浏览数:152

2019-8-16

一、前言

    在工作中,难免遇到各种各样的问题,每个人似乎都有一套自己的解决方案。而我,又不想每次解决完问题就把东西扔了,捡了芝麻,丢了西瓜,什么时候才能进步勒?学习要靠积累,毕竟量变才能引起质变嘛。所以写了这篇博文,不定时更新自己项目中遇到的问题、踩过的那些坑……

二、项目

1、文件流

Java 将两张图片合成一张图片


/**
     * 图片合并
     */
    public String joinImage(String url1, String url2) {

        try {
            InputStream is1 = getImgConn(url1);
            InputStream is2 = getImgConn(url2);

            BufferedImage image1 = ImageIO.read(is1);
            BufferedImage image2 = ImageIO.read(is2);
            BufferedImage combined = new BufferedImage(image1.getWidth() * 2, image1.getHeight(), BufferedImage.TYPE_INT_RGB);
            Graphics g = combined.getGraphics();
            g.drawImage(image1, 0, 0, null);
            g.drawImage(image2, image1.getWidth(), 0, null);
            String imgURL=System.currentTimeMillis()+".jpg";
            ImageIO.write(combined, "JPG", new File("/home/wwwroot/picFiles",imgURL));
            return "/home/wwwroot/picFiles/"+imgURL;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    //读文件
    private  InputStream getImgConn(String url){
        try {
            URL url1 = new URL(url);
            URLConnection urlConnection = url1.openConnection();
            InputStream is1 = urlConnection.getInputStream();
            //先读入内存
            ByteArrayOutputStream buf = new ByteArrayOutputStream(8192);
            byte[] b = new byte[1024];
            int len;
            while ((len = is1.read(b)) != -1) {
                buf.write(b, 0, len);
            }
            is1=new ByteArrayInputStream(buf.toByteArray());
            return is1;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

图片是 http 协议的服务器上的文件

    /**
     * 图片合并
     */
    public static String joinImage(File file1, File file2) {
        BufferedImage image1 = null;
        BufferedImage image2 = null;
        try {
            image1 = ImageIO.read(file1);
            image2 = ImageIO.read(file2);
            BufferedImage combined = new BufferedImage(image1.getWidth() * 2, image1.getHeight(), BufferedImage.TYPE_INT_RGB);
            Graphics g = combined.getGraphics();
            g.drawImage(image1, 0, 0, null);
            g.drawImage(image2, image1.getWidth(), 0, null);
            String imgURL=System.currentTimeMillis()+".jpg";
            ImageIO.write(combined, "JPG", new File("/home/wwwroot/picFiles",imgURL));
            return "/home/wwwroot/picFiles/"+imgURL;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

图片是本地文件

Java 图片像素、尺寸校验


@Slf4j
public class ImagesFormatUtil {

    /**
     * 图片的像素判断
     *
     * @param file        文件
     * @param imageWidth  图片宽度
     * @param imageHeight 图片高度
     * @return true:上传图片宽度和高度都小于等于规定最大值
     */
    public static Boolean checkImageElement(File file, int imageWidth, int imageHeight) {
        if (!file.exists()) {
            return false;
        }
        BufferedImage bufferedImage;
        try {
            bufferedImage = ImageIO.read(file);
            int width = bufferedImage.getWidth();
            int height = bufferedImage.getHeight();
            if (height == imageHeight && width == imageWidth) {
                return true;
            }
        } catch (IOException e) {
            log.error("ImageIO Read IOException:{}", file.getName(), e);
        }
        return false;
    }

    /**
     * 校验图片比例
     *
     * @param file        图片
     * @param imageWidth  宽
     * @param imageHeight 高
     * @return true:符合要求
     * @throws IOException
     */
    public static boolean checkImageScale(File file, int imageWidth, int imageHeight) {
        if (!file.exists()) {
            return false;
        }
        BufferedImage bufferedImage;
        try {
            bufferedImage = ImageIO.read(file);
            int width = bufferedImage.getWidth();
            int height = bufferedImage.getHeight();
            if (imageHeight != 0 && height != 0) {
                int scale1 = imageHeight / imageWidth;
                int scale2 = height / width;
                if (scale1 == scale2) {
                    return true;
                }
            }
        } catch (IOException e) {
            log.error("ImageIO Read IOException:{}", file.getName(), e);
        }
        return false;
    }
}

图片像素、尺寸校验

Java 下载 http 图片到本地


 /**
     *
     * @param url 图片地址 http://....jpg
     * @param file 目标地址
     * @return false 失败 true 成功
     */
    public Boolean downloadSource(String url,String file){
        InputStream inputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            URL url1 = new URL(url);
            URLConnection urlConnection = url1.openConnection();
            urlConnection.setReadTimeout(5 * 1000);
            inputStream = urlConnection.getInputStream();
            //先读入内存
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(8192);
            byte[] bytes = new byte[1024];
            int len;
            while ((len = inputStream.read(bytes)) != -1){
                byteArrayOutputStream.write(bytes,0,len);
            }
            fileOutputStream = new FileOutputStream(new File(file));
            fileOutputStream.write(byteArrayOutputStream.toByteArray());
            return true;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                fileOutputStream.flush();
                fileOutputStream.close();
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

Java 删除文件目录


    /**
     * 删除文件目录,必须先删除文件目录下的文件
     * @param path 要删除的文件目录
     */
    public static void deleteDir(String path) {
        File dir = new File(path);
        if (dir.exists()) {
            File[] tmp = dir.listFiles();
            for (int i = 0; i < tmp.length; i++) {
                if (tmp[i].isDirectory()) {
                    deleteDir(path + "/" + tmp[i].getName());
                } else {
                    tmp[i].delete();
                }
            }
            dir.delete();
        }
    }

删除文件目录

FTP工具类 


public class FtpClient {
    private static final Logger logger = LoggerFactory.getLogger(FtpClient.class);

    //PORT(主动)方式的连接过程是:客户端向服务器的FTP端口(默认是21)发送连接请求,服务器接受连接,建立一条命令链路当需要传送数据时,
    //客户端在命令链路上用PORT命令告诉服务器:我打开了XXXX端口,你过来连接我于是服务器从20端口向客户端的XXXX端口发送连接请求,建立一条数据链路来传送数据
    public static final Integer MODE_PORT = 1;//主动

    //PASV(被动)方式的连接过程是:客户端向服务器的FTP端口(默认是21)发送连接请求,服务器接受连接,建立一条命令链路当需要传送数据时,
    //服务器在命令链路上用PASV命令告诉客户端:我打开了XXXX端口,你过来连接我于是客户端向服务器的XXXX端口发送连接请求,建立一条数据链路来传送数据
    public static final Integer MODE_PASV = 2;//被动


    private String host;
    private Integer port = 21; //默认端口是21
    private String user;
    private String password;
    private boolean ftps = false; //默认使用ftp传输
    private Integer connectMode = MODE_PORT;//默认为主动

    /**
     * 构造函数
     *
     * @param ftpHost     ftp 地址
     * @param user        用户名
     * @param password    密码
     * @param ftps        是否使用ftps
     * @param connectMode 请求方式  FtpClient.MODE_PORT 主动    FtpClient.MODE_PASV 被动
     */
    public FtpClient(String ftpHost, Integer port, String user, String password, boolean ftps, Integer connectMode) {
        this.host = ftpHost;
        this.port = port;
        this.user = user;
        this.password = password;
        this.ftps = ftps;
        this.connectMode = connectMode;
    }

    public FtpClient(String ftpHost, String user, String password, boolean ftps) {
        this.host = ftpHost;
        this.user = user;
        this.password = password;
        this.ftps = ftps;
    }

    public FtpClient(String ftpHost, String user, String password) {
        this.host = ftpHost;
        this.user = user;
        this.password = password;
    }

    /**
     * 认证账号密码
     *
     * @return
     */
    private FTPClient authentication() throws IOException {
        FTPClient ftpClient;
        if (ftps) {
            ftpClient = new FTPSClient();
        } else {
            ftpClient = new FTPClient();
        }
        logger.info(host + "----" + port);
        ftpClient.connect(host, port);
        boolean loginSuccess = ftpClient.login(user, password);
        if (connectMode.equals(MODE_PASV)) {
            ftpClient.enterLocalPassiveMode();//pasv模式
        }
        if (!loginSuccess) {
            logger.error("ftp loginFail:" + ftpClient.getReplyCode());
        }
        return ftpClient;
    }


    private void createDir(String uploadPath) {

    }


    /**
     * @param @param is
     * @param @param targetName
     * @param @param uploadPath
     * @Title: upload
     * @Description: 上传
     */
    public Boolean upload(InputStream is, String targetName, String uploadPath) {
        boolean success = false;
        FTPClient ftpClient = null;
        try {
            ftpClient = authentication();
            //设置上传目录,上传目录必须存在
            boolean changeWorkingDirectory = ftpClient.changeWorkingDirectory(new String(uploadPath.toString().getBytes("GBK"), "iso-8859-1"));
            logger.info("设置上传目录是否成功:" + changeWorkingDirectory);
            if (changeWorkingDirectory) {
                //设置文件类型(二进制)
                ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
                ftpClient.setBufferSize(1024);
                ftpClient.setControlEncoding("GBK");
                success = ftpClient.storeFile(targetName, is);
            }
            logger.info("服务端回馈:" + success + "---" + ftpClient.getReplyString());
        } catch (IOException e) {
            logger.error("ftp upload err", e);
        } finally {
            IOUtils.closeQuietly(is);
            try {
                if (ftpClient != null && ftpClient.isConnected()) {
                    ftpClient.disconnect();
                }
            } catch (IOException e) {
                logger.error("close ftp err", e);
            }
        }
        return success;
    }

    /**
     * @param @param is
     * @param @param targetName
     * @param @param uploadPath
     * @Title: upload
     * @Description: 上传
     */
    public Boolean upload(File file, String targetName, String uploadPath) throws IllegalArgumentException, FileNotFoundException {
        return upload(new FileInputStream(file), targetName, uploadPath);
    }


    /**
     * @param remotePath ftp远程服务器上的路径
     * @param fileName   要下载的文件名
     * @param localPath  要保存的本地路径
     * @return
     */
    public Boolean downLoad(String remotePath, String fileName, String localPath) {
        boolean success = false;
        FTPClient ftpClient = null;
        try {
            ftpClient = authentication();
            ftpClient.changeWorkingDirectory(new String(remotePath.toString().getBytes("GBK"), "iso-8859-1"));
            File file = new File(localPath + File.separatorChar + fileName);
            OutputStream outputStream = new FileOutputStream(file);
            success = ftpClient.retrieveFile(fileName, outputStream);
            outputStream.close();
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (ftpClient != null && ftpClient.isConnected()) {
                    ftpClient.disconnect();
                }
            } catch (IOException e) {
                logger.error("close ftp err", e);
            }
        }
        return success;
    }

}

commons-net.jar 包中的FTPClient(还没解决文件目录创建问题)

 读取 ZIP 文件


    @RequestMapping(value = "/uploadPictures", method = RequestMethod.POST)
    @ResponseBody
    public AjaxList uploadPictures(@RequestPart("pictures") MultipartFile pictures, HttpServletRequest request) throws IOException {
        ZipInputStream zipInputStream = new ZipInputStream(pictures.getInputStream());
        BufferedInputStream bufferedInputStream = new BufferedInputStream(zipInputStream);
        ZipEntry entry;
        byte[] file;
        while ((entry = zipInputStream.getNextEntry()) != null) {
            String pictureName = StringUtil.substringAfter(entry.getName(), "/");
            if (StringUtil.isNotEmpty(pictureName)) {
                file = new byte[(int) entry.getSize()];
                bufferedInputStream.read(file, 0, (int) entry.getSize());
                MultipartFile image = new MockMultipartFile("file", pictureName, "text/plain", file);
                // 上传图片
            }
        }
        return null;
    }

csv 文件操作


public class CsvClient {


    /**
     * CSV 文件写入
     *
     * @param content  文件内容
     * @param file 写入的文件目录
     */
    public static void csvWriter(List<List<Object>> content, File file) {
        FileWriter fileWriter = null;
        CSVPrinter csvPrinter = null;
        try {
            CSVFormat csvFormat = CSVFormat.DEFAULT;
            fileWriter = new FileWriter(file, true);
            csvPrinter = new CSVPrinter(fileWriter, csvFormat);
            //处理内容
            if (!CollectionUtils.isEmpty(content)) {
                csvPrinter.printRecords(content);
            }

            csvPrinter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (csvPrinter != null) {
                    csvPrinter.close();
                }
                if (fileWriter != null) {
                    fileWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

2、HTTP

通过经纬度获得高德地图返回的具体地址、查询IP地址所在地、查询手机号归属地


public class AddressUtils {

    /**
     * 得到ip的归属地
     *
     * @param content        请求的参数 格式为:ip=192.168.0.1
     * @param encodingString 服务器端请求编码。如GBK,UTF-8等
     * @return
     */
    public static String getLocByIp(String content, String encodingString) {
        String urlStr = "http://ip.taobao.com/service/getIpInfo.php";
        String returnStr = getResult(urlStr, content, encodingString);
        if (returnStr != null) {
            String[] temp = returnStr.split(",");
            if (temp.length < 3) {
                //无效IP,局域网测试
                return "0";
            }
            try {
                Map map = new ObjectMapper().readValue(returnStr, Map.class);
                HashMap data = (HashMap) map.get("data");
                //国家
                String country = String.valueOf(data.get("country"));
                //区域
                String area = String.valueOf(data.get("area"));
                //省
                String region = String.valueOf(data.get("region"));
                //城市
                String city = String.valueOf(data.get("city"));
                //运营商
                String isp = String.valueOf(data.get("isp"));

                return country + " " + area + " " + region + " " + city + " " + isp;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 得到手机归属地(待优化)
     *
     * @param tel 手机号
     * @return
     */
    public static String getLocByTel(String tel) {
        String url = "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=" + tel;
        String result = getResult(url, "", "gbk");
        if (!StringUtils.isEmpty(result)) {
            String b = result.replace("__GetZoneResult_ = ", "");
            String c = b.replace("'", "\"");
            String d = c.replace("{", "{\"");
            String e = d.replace(",", ",\"");
            String f = e.replace(":", "\":");
            String g = f.replace("\t", "");
            System.out.println(g);
            try {
                Map map = new ObjectMapper().readValue(g, Map.class);
                return String.valueOf(map.get("carrier"));
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 获取经纬度的确切位置
     *
     * @param lat  经度
     * @param lon  维度
     * @param type type 001 (100代表道路,010代表POI,001代表门址,111可以同时显示前三项)
     * @return
     */
    public static String getLocByLonAndLat(String lat, String lon, String type) {
        String url = "http://gc.ditu.aliyun.com/regeocoding?l=" + lat + "," + lon + "&type=" + type;
        ;
        String result = getResult(url, "", "utf-8");
        if (!StringUtils.isEmpty(result)) {
            try {
                Map map = new ObjectMapper().readValue(result, Map.class);
                List addrList = (ArrayList) map.get("addrList");
                Map addrMap = (HashMap) addrList.get(0);
                String admName = String.valueOf(addrMap.get("admName"));
                return admName;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;

    }

    /**
     * @param urlStr   请求的地址
     * @param content  请求的参数 格式为:ip=192.168.0.1
     * @param encoding 服务器端请求编码。如GBK,UTF-8等
     * @return
     */
    public static String getResult(String urlStr, String content, String encoding) {
        HttpURLConnection connection = null;
        try {
            URL url = new URL(urlStr);
            connection = (HttpURLConnection) url.openConnection();
            connection.setConnectTimeout(2000);//设置连接超时时间,单位毫秒
            connection.setReadTimeout(2000);// 设置读取数据超时时间,单位毫秒
            connection.setDoOutput(true);// 是否打开输出流
            connection.setDoInput(true);// 是否打开输入流
            connection.setRequestMethod("POST");// 提交方法POST|GET
            connection.setUseCaches(false);// 是否缓存true|false
            connection.connect();// 打开连接端口
            DataOutputStream out = new DataOutputStream(connection.getOutputStream());// 打开输出流往对端服务器写数据
            out.writeBytes(content);// 写数据,也就是提交你的表单 name=xxx&pwd=xxx
            out.flush();// 刷新
            out.close();// 关闭输出流
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), encoding));
            StringBuffer buffer = new StringBuffer();
            String line;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
            reader.close();
            return buffer.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();// 关闭连接
            }
        }
        return null;
    }
}

HttpClient 执行http请求工具类


public class NetUtil {
    public static CloseableHttpClient httpClient = HttpClientBuilder.create().build();

    /**
     * get请求获取String类型数据
     *
     * @param url 请求链接
     * @return
     */
    public static String get(String url) {
        HttpGet httpGet = new HttpGet(url);
        try {
            HttpResponse httpResponse = httpClient.execute(httpGet);
            return executeHttpResponse(httpResponse);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            httpGet.releaseConnection();
        }
        return "";
    }

    /**
     * post方式请求数据
     *
     * @param url  请求链接
     * @param data post 数据体
     * @return
     */
    public static String postWithForm(String url, Map<String, String> data) {
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> valuePairs = new ArrayList<>();
        if (null != data) {
            for (String key : data.keySet()) {
                valuePairs.add(new BasicNameValuePair(key, data.get(key)));
            }
        }
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(valuePairs));
            HttpResponse httpResponse = httpClient.execute(httpPost);
            return executeHttpResponse(httpResponse);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            httpPost.releaseConnection();
        }
        return "";
    }


    public static String postWithJSON(String url, String jsonString) {
        HttpPost httpPost = new HttpPost(url);
        StringEntity entity = new StringEntity(jsonString, "utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        try {
            HttpResponse httpResponse = httpClient.execute(httpPost);
            return executeHttpResponse(httpResponse);
        } catch (IOException e) {
        } finally {
            httpPost.releaseConnection();
        }
        return "";
    }


    private static String executeHttpResponse(HttpResponse httpResponse) {
        StringBuffer stringBuffer = new StringBuffer();
        HttpEntity entity = httpResponse.getEntity();
        InputStreamReader reader = null;
        try {
            reader = new InputStreamReader(entity.getContent(), "utf-8");
            char[] charbuffer;
            while (0 < reader.read(charbuffer = new char[10])) {
                stringBuffer.append(charbuffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return stringBuffer.toString();
    }
}

3、反射

反射工具类


public class ReflectUtils {
    private static final String CLASS_NAME = "className";

    public ReflectUtils() {
    }

    private static Object getFieldValue(boolean parent, Object instance, String fieldName) throws ReflectiveOperationException {
        Class<?> clazz = parent ? instance.getClass().getSuperclass() : instance.getClass();
        if ("className".equals(fieldName)) {
            return clazz.getName();
        } else {
            Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(instance);
        }
    }

    public static Object getFieldValue(Object instance, String fieldName) throws ReflectiveOperationException {
        return getFieldValue(false, instance, fieldName);
    }

    public static Object getParentFieldValue(Object instance, String fieldName) throws ReflectiveOperationException {
        return getFieldValue(true, instance, fieldName);
    }

    private static boolean containsField(boolean parent, Object instance, String fieldName) throws ReflectiveOperationException {
        Class<?> clazz = parent ? instance.getClass().getSuperclass() : instance.getClass();
        Field[] fields = clazz.getDeclaredFields();
        Field[] var5 = fields;
        int var6 = fields.length;

        for(int var7 = 0; var7 < var6; ++var7) {
            Field field = var5[var7];
            if (fieldName.equals(field.getName())) {
                return true;
            }
        }

        return false;
    }

    public static boolean containsField(Object instance, String fieldName) throws ReflectiveOperationException {
        return containsField(false, instance, fieldName);
    }

    public static boolean containsParentField(Object instance, String fieldName) throws ReflectiveOperationException {
        return containsField(true, instance, fieldName);
    }

    private static Object invokeMethod(boolean parent, Object instance, String methodName, Object... args) throws ReflectiveOperationException {
        Class<?> clazz = parent ? instance.getClass().getSuperclass() : instance.getClass();
        Class<?>[] parameterTypes = new Class[args.length];

        for(int i = 0; i < args.length; ++i) {
            parameterTypes[i] = args[i].getClass();
        }

        Method method = clazz.getDeclaredMethod(methodName, parameterTypes);
        method.setAccessible(true);
        return method.invoke(instance, args);
    }

    public static Object invokeMethod(Object instance, String methodName, Object... args) throws ReflectiveOperationException {
        return invokeMethod(false, instance, methodName, args);
    }

    public static Object invokeParentMethod(Object instance, String methodName, Object... args) throws ReflectiveOperationException {
        return invokeMethod(true, instance, methodName, args);
    }

    public static Object invokeSuperMethod(int levelCount, Object instance, String methodName, Object... args) throws ReflectiveOperationException {
        Method method = null;
        Class<?> clazz = instance.getClass();

        for(int i = 0; i < levelCount; ++i) {
            Method[] methods = clazz.getDeclaredMethods();
            Method[] var8 = methods;
            int var9 = methods.length;

            for(int var10 = 0; var10 < var9; ++var10) {
                Method m = var8[var10];
                if (methodName.equals(m.getName())) {
                    method = m;
                    break;
                }
            }

            if (method != null) {
                break;
            }

            clazz = clazz.getSuperclass();
        }

        if (method == null) {
            throw new NoSuchMethodException("can not find method named [" + methodName + "] in " + levelCount + "level of instance");
        } else {
            method.setAccessible(true);
            return method.invoke(instance, args);
        }
    }

    public static Class getGenericType(Object instance) {
        ParameterizedType parameterizedType = (ParameterizedType)instance.getClass().getGenericSuperclass();
        Type[] types = parameterizedType.getActualTypeArguments();
        return types.length > 0 ? (Class)types[0] : null;
    }
}

 

    public static List<Map<String, Object>> invokeRequest(final Object... args) {
        return new SecurityManager() {
            List<Map<String, Object>> invoke() {
                //获取执行对象
                Object instance = getContextInstance(getClassContext());
                if (instance != null) {
                    List<Map<String, Object>> paramsList;
                    try {
                        paramsList = (List<Map<String, Object>>) ReflectUtils.invokeMethod(instance, "buildParams", args);
                        //request - propertiesFileName
                        String propertiesFileName = (String) reflectFieldValue(instance, "STATIC_DATA_FILE_NAME");
                        if (paramsList.size() > 0) {
                            Properties properties = PropertyUtils.loadClassPathProperties("supervision/supervision_common.properties");
                            if (StringUtils.isNotEmpty(propertiesFileName)) {
                                properties.putAll(PropertyUtils.loadClassPathProperties(propertiesFileName));
                            }
                            int size = paramsList.size();
                            for (int i = 0; i < size; i++) {
                                initRecordMap(paramsList.get(i), properties);
                                if (ReflectUtils.containsField(instance, "UPDATE_SQL")) {
                                    String updateSql = (String) reflectFieldValue(instance, "UPDATE_SQL");
                                    JdbcTemplate jdbcTemplate = SpringContextHolder.getBean(JdbcTemplate.class);
                                    jdbcTemplate.update(updateSql, paramsList.get(i).get("symbol"));
                                }
                            }
                            return paramsList;
                        }

                        //logger
                        Logger instanceLogger = (Logger) reflectFieldValue(instance, "logger");
                        instanceLogger.info("【无需要提交数据】");
                    } catch (ReflectiveOperationException e) {
                        e.printStackTrace();
                    }
                }
                return null;
            }
        }.invoke();
    }

    private static Object getContextInstance(Class[] classContext) {
        for (Class clazz : classContext) {
            String clazzName = clazz.getName();
            //当前容器类不是工具时,就是执行类,返回此执行类
            if (!clazzName.contains("SupervisionUtils")) {
                return SpringContextHolder.getBean(clazz);
            }
        }
        return null;
    }

    private static Object reflectFieldValue(Object instance, String fieldName) {
        try {
            return ReflectUtils.getFieldValue(instance, fieldName);
        } catch (ReflectiveOperationException e) {
            logger.info("no such field : " + fieldName);
        }
        return "";
    }

反射应用

得到Request的请求参数


    protected Map<String, Object> getUpdateMap(HttpServletRequest request) {
        Map<String, Object> resultMap = new HashMap<>(256);
        Map<String, String[]> parameterMap = request.getParameterMap();
        for (String key : parameterMap.keySet()) {
            resultMap.put(key,  parameterMap.get(key)[0].trim());
        }
        SysUserDto sysUserDto =  SessionUtil.getUserAdmin(request);
        setUpdateMapParameter(resultMap,"appid", sysUserDto.getAppid());
        setUpdateMapParameter(resultMap,"agentUuid", sysUserDto.getAgentUuid());
        setUpdateMapParameter(resultMap,"companyUuid", sysUserDto.getCompanyUuid());
        setUpdateMapParameter(resultMap,"updatedAccount", sysUserDto.getUserAccount());
        setUpdateMapParameter(resultMap,"updatedBy", sysUserDto.getUuid());
        return resultMap;
    }

利用反射封装Request 请求成POJO类


    /**
     * 获取表单实例
     * @param model POJO模型
     * @param <T> 返回的实例
     * @return 表单实体(一般为特定的POJO或者数据库表POJO)
     */
    protected <T> T getModel(HttpServletRequest request, Class<T> model) {
        Field[] fields = getAllFields(model);
        String value;
        Method method;
        T t;
        try {
            t = model.newInstance();
        } catch (Exception e) {
            logger.error("创建模型类实例失败!!!", e);
            throw new RuntimeException(e);
        }

        SysUserDto sysUserDto = SessionUtil.getUserAdmin(request);

        for (Field field : fields) {
            int modifiers = field.getModifiers();
            //static在类所处模块在初次运行时进行初始化工作,且只操作一次。,而final在定义的时候必须定义值
            if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) {
                continue;
            }
            value = getParameter(request, field.getName());
            //当得不到这个key的value时候,考虑是否成员变量有初始值
            if (StringUtil.isEmpty(value)) {
                if (field.getType() == String.class) {
                    try {
                        method = model.getMethod("get" + StringUtil.firstCharToUpper(field.getName()));
                        Object invokeValue = method.invoke(t);
                        if (invokeValue != null) {
                            value = invokeValue.toString();
                        }
                    } catch (Exception e) {
                        if (field.getType() == Boolean.class || field.getType() == boolean.class) {
                            try {
                                String fieldName = field.getName();
                                method = model.getMethod("get" + StringUtil.firstCharToUpper(fieldName.startsWith("is") ? fieldName.replace("is", "") : fieldName));
                                Object invokeValue = method.invoke(t);
                                if (invokeValue != null) {
                                    value = invokeValue.toString();
                                }
                            } catch (Exception e1) {
                                logger.warn(e1.getMessage());
                            }
                        } else {
                            logger.warn(e.getMessage());
                        }
                    }
                }
            }

            logger.debug(field.getName() + " --> " + value);
            //当得到这个key的value时候,要将这个值set给变量
            if (StringUtil.isNotEmpty(value)) {
                invokeMethod(model, t, value, field.getName(), field.getType());
            }

            //增加默认字段的赋值 -- yun
            if(StringUtil.isNotEmpty(sysUserDto.getAppid()) && "appid".equals(field.getName())){
                setValue(model,t,field.getName(),sysUserDto.getAppid());
            }
            if(StringUtil.isNotEmpty(sysUserDto.getCompanyUuid()) && "companyUuid".equals(field.getName())){
                setValue(model,t,field.getName(),sysUserDto.getCompanyUuid());
            }
            if(StringUtil.isNotEmpty(sysUserDto.getAgentUuid()) && "agentUuid".equals(field.getName())){
                setValue(model,t,field.getName(),sysUserDto.getAgentUuid());
            }

            //修改人赋值
            if("updater".equals(field.getName())){
                setValue(model,t,field.getName(),sysUserDto.getUuid());
            }
            if("updatedBy".equals(field.getName())){
                setValue(model,t,field.getName(),sysUserDto.getUuid());
            }
        }
        return t;
    }

    //yun
    private void setValue(Class clazz, Object t, String fieldName, String value){
        Method method;
        try {
            method = clazz.getDeclaredMethod("set" + StringUtil.firstCharToUpper(fieldName), String.class);
            method.invoke(t, value);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

/**
     * 根据Key获取Request中的参数值
     * @param key Request中的Key值
     * @return 返回与Key值对应的Value值
     */
    protected String getParameter(HttpServletRequest request, String key) {
        String[] results = request.getParameterValues(key);
        if (results == null) {
            return "";
        } else if (results.length == 1) {
            return results[0];
        } else {
            StringBuilder sb = new StringBuilder();
            for (String str : results) {
                if (StringUtil.isNotEmpty(str)) {
                    sb.append(str).append(",");
                }
            }
            String result = sb.toString();
            if (result.endsWith(",")) {
                result = result.substring(0, result.length() - 1);
            }
            return result;
        }
    }


    /**
     * 获取类类型的所有Field包括父类中的Field
     * @param clazz 类类型
     * @return 返回类类型的所有Field包括父类中的Field
     */
    public Field[] getAllFields(Class clazz) {
        Map<String, Field> map = new HashMap<String, Field>();
        for (Field field : clazz.getDeclaredFields()) {
            map.put(field.getName(), field);
        }
        while (clazz.getSuperclass() != null) {
            clazz = clazz.getSuperclass();
            if (clazz == Object.class) {
                break;
            }

            for (Field field : clazz.getDeclaredFields()) {
                if (!map.containsKey(field.getName())) {
                    map.put(field.getName(), field);
                }
            }
        }
        return map.values().toArray(new Field[map.size()]);
    }

    /**
     * 封装表单数据
     * @param modelClass POJO模型
     * @param object POJO模型实例对象
     * @param value 各表单的值
     * @param fieldName POJO字段名
     * @param fieldType 字段类型
     * @param <T>
     */
    private <T> void invokeMethod(Class<T> modelClass, T object, String value, String fieldName, Class fieldType) {
        Method method = null;
        try {
            method = modelClass.getMethod("set" + StringUtil.firstCharToUpper(fieldName), fieldType);
        } catch (NoSuchMethodException e) {
            if(fieldType == Boolean.class || fieldType == boolean.class) {
                try {
                    method = modelClass.getMethod("set" + StringUtil.firstCharToUpper(fieldName.startsWith("is") ? fieldName.replace("is", "") : fieldName), fieldType);
                } catch (NoSuchMethodException e1) {
                    logger.warn(e1.getMessage());
                }
            } else {
                logger.warn(e.getMessage());
            }
        }
        try {
            if (null != method) {
                if(fieldType == String.class){
                    method.invoke(object, value);
                } else if (fieldType == double.class || fieldType == Double.class) {
                    try {
                        method.invoke(object, Double.parseDouble(value));
                    } catch (NumberFormatException e) {
                        e.printStackTrace();
                    }
                } else if (fieldType == int.class || fieldType == Integer.class) {
                    try {
                        method.invoke(object, Integer.parseInt(value));
                    } catch (NumberFormatException e) {
                        e.printStackTrace();
                    }
                }  else if (fieldType == Boolean.class || fieldType == boolean.class) {
                    try {
                        method.invoke(object, Boolean.parseBoolean(value));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else if (fieldType == Date.class) {
                    try {
                        SimpleDateFormat sdf = (value.length() == 10 ? new SimpleDateFormat("yyyy-MM-dd") : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
                        method.invoke(object, sdf.parse(value));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else if (fieldType == BigDecimal.class) {
                    try {
                        method.invoke(object, new BigDecimal(value));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 4、工具类

        properties 读取工具类     


public class PropertyUtils {
    private static final Logger logger = LoggerFactory.getLogger(PropertyUtils.class);
    private static final Pattern PATTERN = Pattern.compile("\\$\\{([^\\}]+)\\}");

    public PropertyUtils() {
    }

    public static String get(Properties properties, String key) {
        String value = properties.getProperty(key);
        if (value == null) {
            logger.warn("get null value by key " + key + " from this properties !");
            return null;
        } else {
            Matcher matcher = PATTERN.matcher(value);
            StringBuffer buffer = new StringBuffer();

            while(matcher.find()) {
                String matcherKey = matcher.group(1);
                String matcherValue = properties.getProperty(matcherKey);
                if (matcherValue != null) {
                    matcher.appendReplacement(buffer, matcherValue);
                }
            }

            matcher.appendTail(buffer);
            return buffer.toString();
        }
    }

    public static Properties loadResourcesProperties(String fileName) {
        Properties properties = new Properties();

        try {
            String path = PathConstants.PROJECT_PATH + "\\src\\main\\resources" + "\\" + fileName;
            logger.info("Load properties file from absolute path : " + path);
            properties.load(new InputStreamReader(new FileInputStream(path), StandardCharsets.UTF_8));
        } catch (IOException var3) {
            var3.printStackTrace();
        }

        return properties;
    }

    public static Properties loadClassPathProperties(String fileName, Class anchorClass) {
        Properties properties = new Properties();

        try {
            String path = "/" + fileName;
            logger.info("Load properties file from relative path " + (anchorClass == null ? "" : "refer to " + anchorClass.getName() + ".class") + " : " + path);
            Class clazz = anchorClass == null ? PropertyUtils.class : anchorClass;
            InputStream inputStream = clazz.getResourceAsStream(path);
            if (inputStream == null) {
                logger.error("Can not found properties file : [" + path + "]");
                return properties;
            }

            properties.load(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
        } catch (IOException var6) {
            var6.printStackTrace();
        }

        return properties;
    }

    public static Properties loadClassPathProperties(String fileName) {
        return loadClassPathProperties(fileName, (Class)null);
    }

    public static Properties extend(Properties targetProperties, Properties... extendProperties) {
        Properties[] var2 = extendProperties;
        int var3 = extendProperties.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            Properties properties = var2[var4];
            targetProperties.putAll(properties);
        }

        return targetProperties;
    }

    public static String configDefaultProperty(Properties properties, String propertyName, String defaultValue) {
        if (properties.containsKey(propertyName)) {
            return properties.getProperty(propertyName);
        } else {
            logger.info("Can not get [" + propertyName + "], use default value [" + defaultValue + "] to config");
            return defaultValue;
        }
    }
}


public class ConfigPropertiesUtil {

    private static Logger logger = LogManager.getLogger(PropertiesUtil.class);

    private static String configPath = "/config.properties";
    private static Properties configProperties;

    public ConfigPropertiesUtil() {
    }

    public static String getConfigInfo(String key) {
        return configProperties == null ? null : configProperties.getProperty(key);
    }

    public static Properties loadProperties(String path) {
        logger.info("加载资源[" + path + "] ...");
        Properties prop = null;
        try {
            prop = PropertiesLoaderUtils.loadAllProperties(path);
        } catch (IOException e) {
            logger.error("加载资源[" + path + "]失败");
            logger.error(e.getMessage());
            e.printStackTrace();
        }
        return prop;
    }

    static {
        configProperties = loadProperties(configPath);
    }

}

        mongodb 连接工具类


public class MongoDBUtils {
    private static final Logger logger = LoggerFactory.getLogger(MongoDBUtils.class);
    private static MongoClient mongoClient;
    private static MongoDatabase mongoDatabase;

    public MongoDBUtils() {
    }

    private static MongoClient getMongoClient() {
        if(mongoClient == null) {
            Properties properties = PropertyUtils.loadClassPathProperties("mongodb.properties");
            String ip = properties.getProperty("mongodb.ip");
            String port = properties.getProperty("mongodb.port");
            String dbName = properties.getProperty("mongodb.dbName");
            String username = properties.getProperty("mongodb.username");
            String password = properties.getProperty("mongodb.password");
            MongoCredential credential = MongoCredential.createCredential(username, dbName, password.toCharArray());
            ServerAddress serverAddress = new ServerAddress(ip, Integer.valueOf(port).intValue());
            if(StringUtils.isNotEmpty(ip).booleanValue() && StringUtils.isNotEmpty(port).booleanValue() && StringUtils.isNotEmpty(dbName).booleanValue()) {
                mongoClient = new MongoClient(serverAddress, Collections.singletonList(credential), (new Builder()).connectionsPerHost(300).connectTimeout(15000).maxWaitTime(5000).socketTimeout(0).threadsAllowedToBlockForConnectionMultiplier(5000).writeConcern(WriteConcern.ACKNOWLEDGED).build());
            } else {
                logger.debug("can not get mongodb connection config");
            }
        }

        return mongoClient;
    }

    private static MongoDatabase getMongoDatabase() {
        if(mongoDatabase == null) {
            Properties properties = PropertyUtils.loadClassPathProperties("mongodb.properties");
            String dbName = properties.getProperty("mongodb.dbName");
            mongoDatabase = getMongoClient().getDatabase(dbName);
        }

        return mongoDatabase;
    }

    public static MongoCollection<Document> getCollection(String collName) {
        return getMongoDatabase().getCollection(collName);
    }
}

连接工具类

        MongoCollection<Document> collections = MongoUtils.getCollection("driverLocation");
        for (Document document : collections.find(Filters.gte("uploadTime", getDateBeforeSeconds(beforeSeconds)))) {
            list.add(document);
        }

使用

Double类型精确到6位数,不满6位数的补1


    public static Double formatDouble(Double d){
        if (d==0){
            return d;
        }else {
            String dStr2=d.toString();
            String substringAfter = StringUtils.substringAfter(d.toString(), ".");
            if (substringAfter.length()<6){
                for (int i=substringAfter.length();i<6;i++){
                    dStr2+='1';
                }
                return Double.parseDouble(dStr2);
            }
            DecimalFormat decimalFormat=new DecimalFormat(".######");
            String dStr = decimalFormat.format(d);
            return Double.parseDouble(dStr);
        }
    }

Spring 工具


@Component
public class SpringContextHolder implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    public SpringContextHolder() {
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        applicationContext = applicationContext;
    }

    public static Object getBean(String id) throws BeansException {
        return applicationContext.getBean(id);
    }

    public static <T> T getBean(Class<T> clz) throws BeansException {
        return applicationContext.getBean(clz);
    }

    public static String[] getBeanNames() {
        return applicationContext.getBeanDefinitionNames();
    }

    public static boolean containsBean(String id) {
        return applicationContext.containsBean(id);
    }

    public static boolean isSingleton(String id) throws NoSuchBeanDefinitionException {
        return applicationContext.isSingleton(id);
    }

    public static Class getType(String id) throws NoSuchBeanDefinitionException {
        return applicationContext.getType(id);
    }

    public static String[] getAliases(String id) throws NoSuchBeanDefinitionException {
        return applicationContext.getAliases(id);
    }
}

Map 集合的反向遍历


    private void checkSize(Map<Long, Object> utilization) {
        if (utilization.size() > MapConstants.CACHE_MAX_NUMBER) {
            ArrayList<Map.Entry<Long, Object>> entries = new ArrayList<>(utilization.entrySet());
            ListIterator<Map.Entry<Long, Object>> listIterator = entries.listIterator();
            Map.Entry<Long, Object> previous = listIterator.previous();
            MapConstants.CPUUTILIZATION.remove(previous);
            checkSize(utilization);
        }
    }

6、加密

AES加密工具类


public class AESUtil {

    public final static String DEFAULT_KEY = "1234567812345678";

    // 加密
    public static String encryptAES(String sSrc, String sKey) throws Exception {
        if (sKey == null) {
            System.out.print("Key为空null");
            return null;
        }
        // 判断Key是否为16位
        if (sKey.length() != 16) {
            System.out.print("Key长度不是16位");
            return null;
        }
        byte[] raw = sKey.getBytes("UTF-8");
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式"
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(sSrc.getBytes("UTF-8"));
        return new BASE64Encoder().encode(encrypted);//此处使用BASE64做转码功能,同时能起到2次加密的作用。
    }

    // 解密
    public static String decryptAES(String sSrc, String sKey) throws Exception {
        try {
            // 判断Key是否正确
            if (sKey == null) {
                System.out.print("Key为空null");
                return null;
            }
            // 判断Key是否为16位
            if (sKey.length() != 16) {
                System.out.print("Key长度不是16位");
                return null;
            }
            byte[] raw = sKey.getBytes("UTF-8");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(sSrc);//先用base64解密
            try {
                byte[] original = cipher.doFinal(encrypted1);
                String originalString = new String(original,"UTF-8");
                return originalString;
            } catch (Exception e) {
                System.out.println(e.toString());
                return null;
            }
        } catch (Exception ex) {
            System.out.println(ex.toString());
            return null;
        }
    }
}

Base64三种加密方式


/*---1---*/
        /*早期在Java上做Base64的编码与解码,会使用到JDK里sun.misc套件下的BASE64Encoder和BASE64Decoder这两个类别*/
        /*这个sun.mis c套件所提供的Base64功能,编码和解码的效率并不太好,而且在以后的Java版本可能就不被支援了,不建议使用。*/
        final BASE64Encoder encoder = new BASE64Encoder();
        final BASE64Decoder decoder = new BASE64Decoder();
        final String text = "字串文字";
        final byte[] textByte = text.getBytes("UTF-8");
        //编码
        final String encodedText = encoder.encode(textByte);
        System.out.println(encodedText);
        //解码
        System.out.println(new String(decoder.decodeBuffer(encodedText), "UTF-8"));

        /*---2---*/
        /*Apache Commons Codec有提供Base64的编码与解码功能,会使用到org.apache.commons.codec.binary套件下的Base64类别*/
        /*以上的程式码看起来又比早期用sun.mis c套件还要更精简,效能实际执行起来也快了不少。缺点是需要引用Apache Commons Codec*/
        final Base64 base64 = new Base64();
        final String text = "字串文字";
        final byte[] textByte = text.getBytes("UTF-8");
        //编码
        final String encodedText = base64.encodeToString(textByte);
        System.out.println(encodedText);
        //解码
        System.out.println(new String(base64.decode(encodedText), "UTF-8"));

        /*---3---*/
        /*Java 8的java.util套件中,新增了Base64的类别,可以用来处理Base64的编码与解码*/
        /*与sun.mis c套件和Apache Commons Codec所提供的Base64编解码器来比较的话,Java 8提供的Base64拥有更好的效能。实际测试编码与解码速度的话,Java 8提供的Base64,要比sun.mis c套件提供的还要快至少11倍,比Apache Commons Codec提供的还要快至少3倍*/
        final Base64.Decoder decoder = Base64.getDecoder();
        final Base64.Encoder encoder = Base64.getEncoder();
        final String text = "字串文字";
        final byte[] textByte = text.getBytes("UTF-8");
        //编码
        final String encodedText = encoder.encodeToString(textByte);
        System.out.println(encodedText);
       //解码
        System.out.println(new String(decoder.decode(encodedText), "UTF-8"));

7、类型转换

       Map 执行toString 后 怎么转换回Map


    public static Map<String,Object> mapStringToMap(String str){
        str=str.substring(1, str.length()-1);
        String[] strs=str.split(",");
        Map<String,Object> map = new HashMap<String, Object>();
        for (String string : strs) {
            String key=string.split("=")[0];
            String value=string.split("=")[1];
            map.put(key, value);
        }
        return map;
    }

Jackson 组件操作JSON类型


public static String toJSONString(Object t) {
        try {
            return (new ObjectMapper()).writeValueAsString(t);
        } catch (JsonProcessingException var2) {
            var2.printStackTrace();
            return null;
        }
    }

    public static <T> T readJSONString(String str, Class<T> clazz) {
        try {
            return (new ObjectMapper()).readValue(str, clazz);
        } catch (IOException var3) {
            var3.printStackTrace();
            return null;
        }
    }

 8、日志输出归档

lo4j.xml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//log4j/log4j Configuration//EN" "log4j.dtd">
<log4j:configuration>
    <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name='ConversionPattern' value='[%d]-[%p]-[Thread: %t]-[%C.%M():%L]: %m%n' />
        </layout>
    </appender>

    <appender name="debugFile" class="org.apache.log4j.RollingFileAppender">
        <param name="file" value="/usr/local/yycx/logs/admin/debug.log" />
        <param name="append" value="true" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name='ConversionPattern' value='[%d]-[%p]-[Thread: %t]-[%C.%M():%L]: %m%n' />
        </layout>
        <filter class="org.apache.log4j.varia.LevelRangeFilter">
            <param name="levelMin" value="DEBUG"/>
            <param name="levelMax" value="DEBUG"/>
        </filter>
    </appender>

    <appender name="infoFile" class="org.apache.log4j.RollingFileAppender">
        <param name="file" value="/usr/local/yycx/logs/admin/info.log" />
        <param name="append" value="true" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name='ConversionPattern' value='[%d]-[%p]-[Thread: %t]-[%C.%M():%L]: %m%n' />
        </layout>
        <filter class="org.apache.log4j.varia.LevelRangeFilter">
            <param name="LevelMin" value="INFO"/>
            <param name="LevelMax" value="INFO"/>
        </filter>
    </appender>

    <appender name="errorFile" class="org.apache.log4j.RollingFileAppender">
        <param name="file" value="/usr/local/yycx/logs/admin/error.log" />
        <param name="append" value="true" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name='ConversionPattern' value='[%d]-[%p]-[Thread: %t]-[%C.%M():%L]: %m%n' />
        </layout>
        <filter class="org.apache.log4j.varia.LevelRangeFilter">
            <param name="LevelMin" value="ERROR"/>
            <param name="LevelMax" value="ERROR"/>
        </filter>
    </appender>

    <root>
        <level value="error"/>
        <appender-ref ref="console"/>
        <appender-ref ref="infoFile"/>
        <appender-ref ref="debugFile"/>
        <appender-ref ref="errorFile"/>
    </root>
</log4j:configuration>

logback.xml


<?xml version="1.0" encoding="UTF-8"?>
<!-- 说明:
    1、日志级别及文件 日志记录采用分级记录,级别与日志文件名相对应,不同级别的日志信息记录到不同的日志文件中 例如:error级别记录
       到log_error_xxx.log或log_error.log(该文件为当前记录的日志文件),而log_error_xxx.log为归档日志,日志文件按日期记录,
       同一天内,若日志文件大小等于或大于100M,则按0、1、2...顺序分别命名 例如log-level-2013-12-21.0.log其它级别的日志也是如此。
    2、文件路径 可在 <property name="LOG_PATH" value="/var/jmcui"/> 中配置自己想要的文件路径
    3、Appender FILEERROR对应error级别,文件名以log-error-xxx.log形式命名 ,FILEWARN对应warn级别,文件名以log-warn-xxx.log
       形式命名 FILEINFO对应info级别,文件名以log-info-xxx.log形式命名,FILEDEBUG对应debug级别,文件名以log-debug-xxx.log形
       式命名 stdout将日志信息输出到控制上,为方便开发测试使用 -->
<configuration>

    <property name="LOG_PATH" value="/var/jmcui"/>
    <!-- 日志记录器,日期滚动记录 -->
    <appender name="FILEERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${LOG_PATH}/log_error.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件
                 路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。而2013-12-21的日志文件在由fileNamePattern指
                 定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
            <fileNamePattern>${LOG_PATH}/log-error-%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <!-- 除按日志记录之外,还配置了日志文件不能超过100M,若超过100M,日志文件会以索引0开始, 命名日志文件,例如log-error-2013-12-21.0.log -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!-- 追加方式记录日志 -->
        <append>true</append>
        <!-- 日志文件的格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%-5p [%d][%mdc{mdc_userId}] %C:%L - %m %n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志文件只记录error级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>error</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="FILEWARN"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/log_warn.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/log-warn-%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <append>true</append>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%-5p [%d][%mdc{mdc_userId}] %C:%L - %m %n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="FILEINFO"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/log_info.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/log-info-%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <append>true</append>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%-5p [%d][%mdc{mdc_userId}] %C:%L - %m %n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>


    <appender name="FILEDEBUG"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/log_debug.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/log-debug-%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <append>true</append>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%-5p [%d][%mdc{mdc_userId}] %C:%L - %m %n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <Target>System.out</Target>
        <encoder>
            <pattern>%-5p [%d][%mdc{mdc_userId}] %C:%L - %m %n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
    </appender>

    <appender name="FILTER_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>${LOG_PATH}/log_filter.log</File>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} : %m%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/log_filter.%d{yyyy-MM-dd}</fileNamePattern>
        </rollingPolicy>
    </appender>

    <logger name="FILTER_INFO_LOGGER" additivity="false" level="INFO">
        <appender-ref ref="FILTER_INFO"/>
    </logger>


    <appender name="INTEREST_BEARING_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>${LOG_PATH}/log_interest_bearing.log</File>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} : %m%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/log_interest_bearing.%d{yyyy-MM-dd}</fileNamePattern>
        </rollingPolicy>
    </appender>

    <logger name="INTEREST_BEARING_LOGGER" additivity="true" level="INFO">
        <appender-ref ref="INTEREST_BEARING_INFO"/>
    </logger>


    <!-- 为单独的包配置日志级别,若root的级别大于此级别, 此处级别也会输出 应用场景:生产环境一般不会将日志级别设置为trace或debug,但是为详细的记录SQL语句的情况,
        可将hibernate的级别设置为debug,如此一来,日志文件中就会出现hibernate的debug级别日志, 而其它包则会按root的级别输出日志 -->
    <logger name="org.springframework" level="DEBUG"/>
    <logger name="com.ibatis" level="DEBUG"/>
    <logger name="com.ibatis.common.jdbc.SimpleDataSource" level="DEBUG"/>
    <logger name="com.ibatis.common.jdbc.ScriptRunner" level="DEBUG"/>
    <logger name="com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate" level="DEBUG"/>
    <logger name="java.sql.Connection" level="DEBUG"/>
    <logger name="java.sql.Statement" level="DEBUG"/>
    <logger name="java.sql.PreparedStatement" level="DEBUG"/>


    <!-- 生产环境,将此级别配置为适合的级别,以名日志文件太多或影响程序性能 -->
    <root level="INFO">
        <appender-ref ref="FILEDEBUG"/>
        <appender-ref ref="FILEINFO"/>
        <appender-ref ref="FILEWARN"/>
        <appender-ref ref="FILEERROR"/>
        <!-- 生产环境将请stdout去掉 -->
        <appender-ref ref="stdout"/>
    </root>
</configuration>

9、缓存

 基于 ConcurrentHashMap 的内存缓存


public class CacheBean {

    /**
     * 缓存对象
     */
    private Object CacheValue;
    /**
     * 过期时间
     */
    private Long expiration;

    public CacheBean() {

    }

    public CacheBean(Object cacheValue, Long expiration) {
        CacheValue = cacheValue;
        this.expiration = expiration;
    }

    public Object getCacheValue() {
        return CacheValue;
    }

    public void setCacheValue(Object cacheValue) {
        CacheValue = cacheValue;
    }

    public Long getExpiration() {
        return expiration;
    }

    public void setExpiration(Long expiration) {
        this.expiration = expiration;
    }
}

CacheBean.java —— 缓存对象

public class CleanCacheTimeOutThread implements Runnable {

    @Override
    public void run() {
        CacheUtils.setCleanThreadRun();
        while (true) {
            System.out.println("cache clean thread run ");
            CacheUtils.deleteTimeOut();
            try {
                Thread.sleep(CacheUtils.ONE_MINUTE);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

CleanCacheTimeOutThread.java —— 清理过期 key 线程

public class CacheUtils {


    /**
     * 清理缓存时间
     */
    public static Long ONE_MINUTE = 1 * 60 * 1000L;

    private static final Logger LOGGER = LoggerFactory.getLogger(CacheUtils.class);

    /**
     * 缓存最大个数
     */
    private static final Integer CACHE_MAX_NUMBER = 100;
    /**
     * 当前缓存个数
     */
    private static Integer CURRENT_SIZE = 0;
    /**
     * 缓存对象
     */
    private static final Map<String, CacheBean> CACHE_OBJECT_MAP = new ConcurrentHashMap<>();
    /**
     * 这个记录了缓存使用的最后一次的记录,最近使用的在最前面
     */
    private static final List<String> CACHE_USE_LOG_LIST = new LinkedList<>();
    /**
     * 清理过期缓存是否在运行
     */
    private static Boolean CLEAN_THREAD_IS_RUN = false;

    /**
     * 清理线程的
     */
    private static ExecutorService executor = Executors.newSingleThreadExecutor();


    /**
     * 设置缓存
     *
     * @param key   缓存key
     * @param value 缓存value
     * @param time  缓存时长(毫秒),-1 表示不过期
     */
    public static void set(String key, Object value, long time) {
        Long expiration = null;
        if (time <= 0L) {
            if (time == -1L) {
                expiration = -1L;
            } else {
                return;
            }
        }
        checkSize();
        saveCacheUseLog(key);
        CURRENT_SIZE = CURRENT_SIZE + 1;
        if (expiration == null) {
            expiration = System.currentTimeMillis() + time;
        }
        CacheBean cacheBean = new CacheBean(value, expiration);
        CACHE_OBJECT_MAP.put(key, cacheBean);
        LOGGER.info("cache set key :" + key);
    }

    public static void set(String key, Object value) {
        set(key, value, -1L);
    }

    /**
     * 获取缓存
     */
    public static Object get(String key) {
        startCleanThread();
        if (exists(key)) {
            saveCacheUseLog(key);
            return CACHE_OBJECT_MAP.get(key).getCacheValue();
        }
        return null;
    }

    public static boolean exists(String key) {
        CacheBean cacheBean = CACHE_OBJECT_MAP.get(key);
        if (cacheBean == null) {
            return false;
        } else {
            Long expiration = cacheBean.getExpiration();
            if (expiration == -1L) {
                return true;
            }
            if (expiration < System.currentTimeMillis()) {
                return false;
            }
        }
        return true;
    }

    /**
     * 删除所有缓存
     */
    public static void clear() {
        LOGGER.info("have clean all key !");
        CACHE_OBJECT_MAP.clear();
        CURRENT_SIZE = 0;
    }

    /**
     * 删除某个缓存
     */
    public static void deleteCache(String key) {
        Object cacheValue = CACHE_OBJECT_MAP.remove(key);
        if (cacheValue != null) {
            LOGGER.info("cache have delete key :" + key);
            CURRENT_SIZE = CURRENT_SIZE - 1;
        }
    }

    /**
     * 删除最近最久未使用的缓存
     */
    private static void deleteLRU() {
        LOGGER.info("cache delete Least recently used run!");
        String deleteKey = CACHE_USE_LOG_LIST.remove(CACHE_USE_LOG_LIST.size() - 1);
        deleteCache(deleteKey);
    }

    /**
     * 删除过期的缓存
     */
    static void deleteTimeOut() {
        LOGGER.info("cache delete time out run!");
        List<String> deleteKeyList = new LinkedList<>();
        for (Map.Entry<String, CacheBean> entry : CACHE_OBJECT_MAP.entrySet()) {
            Long expiration = entry.getValue().getExpiration();
            if (expiration < System.currentTimeMillis() && expiration != -1L) {
                deleteKeyList.add(entry.getKey());
            }
        }

        for (String deleteKey : deleteKeyList) {
            deleteCache(deleteKey);
        }
        LOGGER.info("cache delete cache count is :" + deleteKeyList.size());

    }

    /**
     * 检查大小
     * 当当前大小如果已经达到最大大小
     * 首先删除过期缓存,如果过期缓存删除过后还是达到最大缓存数目
     * 删除最久未使用缓存
     */
    private static void checkSize() {
        if (CURRENT_SIZE >= CACHE_MAX_NUMBER) {
            deleteTimeOut();
        }
        if (CURRENT_SIZE >= CACHE_MAX_NUMBER) {
            deleteLRU();
        }
    }

    /**
     * 保存缓存的使用记录
     */
    private static synchronized void saveCacheUseLog(String cacheKey) {
        CACHE_USE_LOG_LIST.remove(cacheKey);
        CACHE_USE_LOG_LIST.add(0, cacheKey);
    }

    /**
     * 设置清理线程的运行状态为正在运行
     */
    static void setCleanThreadRun() {
        CLEAN_THREAD_IS_RUN = true;
    }

    /**
     * 开启清理过期缓存的线程
     */
    private static void startCleanThread() {
        if (!CLEAN_THREAD_IS_RUN) {
            executor.submit(new CleanCacheTimeOutThread());
        }
    }

    public static void showUtilsInfo() {
        System.out.println("clean time out cache is run :" + CLEAN_THREAD_IS_RUN);
        System.out.println("cache max count is :" + CACHE_MAX_NUMBER);
        System.out.println("cache current count is :" + CURRENT_SIZE);
        System.out.println("cache object map is :" + CACHE_OBJECT_MAP.toString());
        System.out.println("cache use log list is :" + CACHE_USE_LOG_LIST.toString());

    }

}

CacheUtils.java

10、SQL使用技巧

查找此刻进行中的订单数量大于0的司机列表(司机表和订单表一对多)


SELECT d.* 
FROM yy_driver d
LEFT JOIN yy_order o on d.uuid = o.actual_driver_uuid
WHERE d.type = 9
GROUP BY d.uuid
HAVING COUNT(case when o.main_status = 2 THEN 1 ELSE null end) > 0 

作者:JMCui