一、前言
在工作中,难免遇到各种各样的问题,每个人似乎都有一套自己的解决方案。而我,又不想每次解决完问题就把东西扔了,捡了芝麻,丢了西瓜,什么时候才能进步勒?学习要靠积累,毕竟量变才能引起质变嘛。所以写了这篇博文,不定时更新自己项目中遇到的问题、踩过的那些坑......
二、项目
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; }
/** * 图片合并 */ 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 下载 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 = Logger.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;//默认为主动 /** * 缺省构造函数 */ public FtpClient() { } /** * 构造函数 * * @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; } /** * 判断参数合法性 */ private void checkParameter() { if (StringUtils.isEmpty(host)) { throw new IllegalArgumentException("host not allow be empty"); } if (StringUtils.isEmpty(user)) { throw new IllegalArgumentException("user not allow be empty"); } if (StringUtils.isEmpty(password)) { throw new IllegalArgumentException("password not allow be empty"); } } /** * 认证账号密码 * * @return */ private FTPClient authentication() throws IOException { checkParameter(); FTPClient ftpClient; if (ftps) { ftpClient = new FTPSClient(); } else { ftpClient = new FTPClient(); } 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")); 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; } }
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); } }
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、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