[关闭]
@TedZhou 2020-10-15T16:39:15.000000Z 字数 16711 阅读 353

Springboot 开发必备的工具类

java spring


StringUtils.java

  1. import java.io.UnsupportedEncodingException;
  2. import java.net.URLDecoder;
  3. import java.net.URLEncoder;
  4. import java.security.MessageDigest;
  5. import java.util.Date;
  6. import java.util.Formatter;
  7. import java.util.UUID;
  8. import org.springframework.lang.Nullable;
  9. import org.springframework.util.DigestUtils;
  10. public class StringUtils extends org.springframework.util.StringUtils {
  11. public static boolean equals(@Nullable String str1, @Nullable String str2) {
  12. if (str1 == null || str2 == null) {
  13. return (str1 == null && str2 == null);
  14. }
  15. return str1.equals(str2);
  16. }
  17. public static boolean isBlank(@Nullable String string) {
  18. if (isEmpty(string)) {
  19. return true;
  20. }
  21. for (int i = 0; i < string.length(); i++) {
  22. if (!Character.isWhitespace(string.charAt(i))) {
  23. return false;
  24. }
  25. }
  26. return true;
  27. }
  28. public static boolean isNotBlank(@Nullable String string) {
  29. return !StringUtils.isBlank(string);
  30. }
  31. public static boolean isBlank(@Nullable Integer id) {
  32. return id == null || id == 0;
  33. }
  34. public static boolean isNotBlank(@Nullable Integer id) {
  35. return id != null && id != 0;
  36. }
  37. public static String[] split(@Nullable String string, @Nullable String delimiter, int limit) {
  38. if (isEmpty(string) || delimiter == null || limit == 1) {
  39. return new String[]{string};
  40. }
  41. return string.split(delimiter, limit);
  42. }
  43. /* @return uuid string(32) */
  44. public static String uuid() {
  45. return UUID.randomUUID().toString().replace("-", "");
  46. }
  47. private static final String[] chars = new String[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
  48. "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6",
  49. "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
  50. "S", "T", "U", "V", "W", "X", "Y", "Z" };
  51. /* gen short unique id(8 chars) */
  52. public static String unid8() {
  53. return StringUtils.unid8(null);
  54. }
  55. private static String unid8(String uuid32) {
  56. StringBuffer shortBuffer = new StringBuffer();
  57. if (StringUtils.isBlank(uuid32)) {
  58. uuid32 = StringUtils.uuid();
  59. }
  60. for (int i = 0; i < 8; i++) {
  61. String str = uuid32.substring(i * 4, i * 4 + 4);
  62. int x = Integer.parseInt(str, 16);
  63. shortBuffer.append(StringUtils.chars[x % 0x3E]);
  64. }
  65. return shortBuffer.toString();
  66. }
  67. /* gen unique id(20 chars) that has timestamp */
  68. public static String unid20() {
  69. long ts = new Date().getTime();
  70. return String.format("%d_%s", ts, StringUtils.unid8());
  71. }
  72. /* MD5, null as empty str. */
  73. public static String MD5(String str) {
  74. if (str == null) {
  75. str = "";
  76. }
  77. return DigestUtils.md5DigestAsHex(str.getBytes());
  78. }
  79. /* SHA-1, null as empty str. */
  80. public static String SHA1(String str) {
  81. if (str == null) {
  82. return "";
  83. }
  84. try {
  85. MessageDigest crypt = MessageDigest.getInstance("SHA-1");
  86. crypt.reset();
  87. crypt.update(str.getBytes("UTF-8"));
  88. return byteToHex(crypt.digest());
  89. } catch (Exception e) {
  90. e.printStackTrace();
  91. }
  92. return str;
  93. }
  94. private static String byteToHex(final byte[] hash) {
  95. Formatter formatter = new Formatter();
  96. for (byte b : hash) {
  97. formatter.format("%02x", b);
  98. }
  99. String result = formatter.toString();
  100. formatter.close();
  101. return result;
  102. }
  103. public static String urlDecode(String raw) {
  104. try {
  105. return URLDecoder.decode(raw, "UTF-8");
  106. } catch (UnsupportedEncodingException uee) {
  107. throw new IllegalStateException(uee); // can't happen
  108. }
  109. }
  110. public static String urlEncode(String str) {
  111. try {
  112. return URLEncoder.encode(str, "UTF-8");
  113. } catch (UnsupportedEncodingException uee) {
  114. throw new IllegalStateException(uee); // can't happen
  115. }
  116. }
  117. public static String urlEncode(String str, String en) {
  118. try {
  119. return URLEncoder.encode(str, en);
  120. } catch (UnsupportedEncodingException uee) {
  121. throw new IllegalStateException(uee); // can't happen
  122. }
  123. }
  124. public static String convert(String str, String from, String to) {
  125. try {
  126. str = new String(str.getBytes(from), to);
  127. } catch (UnsupportedEncodingException e) {
  128. e.printStackTrace();
  129. }
  130. return str;
  131. }
  132. }

NumberUtils.java

  1. import org.springframework.lang.Nullable;
  2. public class NumberUtils extends org.springframework.util.NumberUtils {
  3. public static <T extends Number> boolean equals(@Nullable T a, @Nullable T b) {
  4. if (a == null || b == null) {
  5. return (a == null && b == null);
  6. }
  7. return a.equals(b);
  8. }
  9. public static <T extends Number> T parse(String text, Class<T> targetClass, T defaultValue) {
  10. if (text == null || text.equals("")) {
  11. return defaultValue;
  12. }
  13. try {
  14. return NumberUtils.parseNumber(text, targetClass);
  15. }catch(Exception e){
  16. e.printStackTrace();
  17. }
  18. return defaultValue;
  19. }
  20. public static <T extends Number> T parse(String text, Class<T> targetClass) {
  21. return NumberUtils.parse(text, targetClass, null);
  22. }
  23. public static Integer parseInt(String text) {
  24. return NumberUtils.parse(text, Integer.class);
  25. }
  26. public static Long parseLong(String text) {
  27. return NumberUtils.parse(text, Long.class);
  28. }
  29. }

DateTimeUtils.java

  1. import java.text.SimpleDateFormat;
  2. import java.time.Instant;
  3. import java.time.LocalDateTime;
  4. import java.time.ZoneOffset;
  5. import java.time.chrono.ChronoLocalDateTime;
  6. import java.time.format.DateTimeFormatter;
  7. import java.util.Date;
  8. import java.util.Locale;
  9. import org.springframework.lang.Nullable;
  10. public class DateTimeUtils {
  11. public static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
  12. public static int compare(Date theDate, Date anotherDate) {
  13. if (theDate == null) {
  14. theDate = new Date();
  15. }
  16. if (anotherDate == null) {
  17. anotherDate = new Date();
  18. }
  19. return theDate.compareTo(anotherDate);
  20. }
  21. public static int compare(ChronoLocalDateTime<?> theDate, ChronoLocalDateTime<?> anotherDate) {
  22. if (theDate == null) {
  23. theDate = LocalDateTime.now();
  24. }
  25. if (anotherDate == null) {
  26. anotherDate = LocalDateTime.now();
  27. }
  28. return theDate.compareTo(anotherDate);
  29. }
  30. public static Date toDate(LocalDateTime localDateTime) {
  31. if (localDateTime == null) return null;
  32. return Date.from(localDateTime.toInstant(ZoneOffset.of("+8")));
  33. }
  34. public static LocalDateTime toLocalDateTime(Date date) {
  35. if (date == null) return null;
  36. return fromMilli(date.getTime());
  37. }
  38. public static Date parseDate(@Nullable String string) {
  39. SimpleDateFormat format = new SimpleDateFormat(DATETIME_PATTERN, Locale.CHINA);
  40. try {
  41. return format.parse(string);
  42. } catch (Exception e) {
  43. return null;
  44. }
  45. }
  46. public static LocalDateTime parseLocalDateTime(@Nullable String string) {
  47. DateTimeFormatter format = DateTimeFormatter.ofPattern(DATETIME_PATTERN, Locale.CHINA);
  48. try {
  49. return LocalDateTime.parse(string, format);
  50. } catch (Exception e) {
  51. return null;
  52. }
  53. }
  54. public static String formatDateTime(LocalDateTime dt) {
  55. if (dt == null) return null;
  56. DateTimeFormatter format = DateTimeFormatter.ofPattern(DATETIME_PATTERN, Locale.CHINA);
  57. return dt.format(format);
  58. }
  59. public static LocalDateTime fromSecond(long second, ZoneOffset offset) {
  60. if (offset == null) {
  61. offset = ZoneOffset.of("+8");
  62. }
  63. LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(second, 0, offset);
  64. return localDateTime;
  65. }
  66. public static LocalDateTime fromSecond(long second) {
  67. return DateTimeUtils.fromSecond(second, null);
  68. }
  69. public static LocalDateTime fromMilli(long ts, ZoneOffset offset) {
  70. if (offset == null) {
  71. offset = ZoneOffset.of("+8");
  72. }
  73. Instant instant = Instant.ofEpochMilli(ts);
  74. LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, offset);
  75. return localDateTime;
  76. }
  77. public static LocalDateTime fromMilli(long ts) {
  78. return DateTimeUtils.fromMilli(ts, null);
  79. }
  80. //返回世纪秒
  81. public static long secondsOf(ChronoLocalDateTime<?> ldt, ZoneOffset offset) {
  82. if (ldt == null) {
  83. return 0;
  84. }
  85. if (offset == null) {
  86. offset = ZoneOffset.of("+8");
  87. }
  88. long second = ldt.toEpochSecond(offset);
  89. return second;
  90. }
  91. public static long secondsOf(ChronoLocalDateTime<?> ldt) {
  92. return DateTimeUtils.secondsOf(ldt, null);
  93. }
  94. //返回世纪毫秒
  95. public static long micsecondsOf(ChronoLocalDateTime<?> ldt, ZoneOffset offset) {
  96. if (ldt == null) {
  97. return 0;
  98. }
  99. if (offset == null) {
  100. offset = ZoneOffset.of("+8");
  101. }
  102. long mic = ldt.toInstant(offset).toEpochMilli();
  103. return mic;
  104. }
  105. public static long micsecondsOf(ChronoLocalDateTime<?> ldt) {
  106. return DateTimeUtils.micsecondsOf(ldt, null);
  107. }
  108. }

JSON.java

  1. import java.io.IOException;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import com.fasterxml.jackson.core.JsonParseException;
  5. import com.fasterxml.jackson.core.JsonProcessingException;
  6. import com.fasterxml.jackson.core.type.TypeReference;
  7. import com.fasterxml.jackson.databind.JsonMappingException;
  8. import com.fasterxml.jackson.databind.ObjectMapper;
  9. import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
  10. public class JSON {
  11. @SuppressWarnings("unchecked")
  12. public static Map<String, Object> parse(String jsonStr) {
  13. Map<String, Object> map = new HashMap<>();
  14. try {
  15. map = (Map<String, Object>) JSON.parse(jsonStr, map.getClass());
  16. } catch (Exception e) {
  17. e.printStackTrace();
  18. map = null;
  19. }
  20. return map;
  21. }
  22. public static <T> T parse(String jsonStr, Class<T> toClass) {
  23. try {
  24. ObjectMapper mapper = new ObjectMapper();
  25. return mapper.readValue(jsonStr, toClass);
  26. } catch (JsonParseException e) {
  27. e.printStackTrace();
  28. } catch (JsonMappingException e) {
  29. e.printStackTrace();
  30. } catch (IOException e) {
  31. e.printStackTrace();
  32. }
  33. return null;
  34. }
  35. public static <T extends Object> T parse(String jsonStr, TypeReference<T> type) {
  36. try {
  37. ObjectMapper mapper = new ObjectMapper();
  38. mapper.registerModule(new JavaTimeModule());
  39. return mapper.readValue(jsonStr, type);
  40. } catch (JsonParseException e) {
  41. e.printStackTrace();
  42. } catch (JsonMappingException e) {
  43. e.printStackTrace();
  44. } catch (IOException e) {
  45. e.printStackTrace();
  46. }
  47. return null;
  48. }
  49. public static String stringify(Object obj) {
  50. try {
  51. ObjectMapper mapper = new ObjectMapper();
  52. //https://howtoprogram.xyz/2017/12/30/serialize-java-8-localdate-jackson/
  53. mapper.registerModule(new JavaTimeModule());
  54. //mapper.disable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS);
  55. return mapper.writeValueAsString(obj);
  56. } catch (JsonProcessingException e) {
  57. e.printStackTrace();
  58. }
  59. return null;
  60. }
  61. }

XmlUtils.java

  1. import java.io.IOException;
  2. import java.util.ArrayList;
  3. import java.util.Date;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. import com.fasterxml.jackson.core.JsonProcessingException;
  8. import com.fasterxml.jackson.databind.ObjectWriter;
  9. import com.fasterxml.jackson.dataformat.xml.XmlMapper;
  10. public class XmlUtils {
  11. @SuppressWarnings("unchecked")
  12. public static Map<String, String> parse(String xml){
  13. Map<String, String> map = new HashMap<>();
  14. return (Map<String, String>) XmlUtils.parse(xml, map.getClass());
  15. }
  16. public static <T> T parse(String xml, Class<T> toClass) {
  17. try {
  18. XmlMapper xmlMapper = new XmlMapper();
  19. return xmlMapper.readValue(xml, toClass);
  20. } catch (IOException e) {
  21. e.printStackTrace();
  22. }
  23. return null;
  24. }
  25. public static String stringify(Object obj, String root) {
  26. XmlMapper xmlMapper = new XmlMapper();
  27. try {
  28. ObjectWriter writer = xmlMapper.writer();
  29. if (root != null && !"".equals(root)) {
  30. writer = writer.withRootName(root);
  31. }
  32. return writer.writeValueAsString(obj);
  33. } catch (JsonProcessingException e) {
  34. e.printStackTrace();
  35. }
  36. return null;
  37. }
  38. }

BeanUtils.java

  1. import java.beans.PropertyDescriptor;
  2. import java.util.HashSet;
  3. import java.util.Set;
  4. import org.springframework.beans.BeanWrapper;
  5. import org.springframework.beans.BeanWrapperImpl;
  6. import org.springframework.util.StringUtils;
  7. public class BeanUtils extends org.springframework.beans.BeanUtils {
  8. /* copy source properties(not null) to target */
  9. public static void copyPropertiesNotNull(Object source, Object target) {
  10. String[] ignoreProperties = BeanUtils.getNullProperties(source);
  11. BeanUtils.copyProperties(source, target, ignoreProperties);
  12. }
  13. /* copy source properties(not empty) to target */
  14. public static void copyPropertiesNotEmpty(Object source, Object target) {
  15. String[] ignoreProperties = BeanUtils.getEmptyProperties(source);
  16. BeanUtils.copyProperties(source, target, ignoreProperties);
  17. }
  18. /* get object's null properties */
  19. public static String[] getNullProperties(Object obj) {
  20. BeanWrapper bean = new BeanWrapperImpl(obj);
  21. PropertyDescriptor[] descriptors = bean.getPropertyDescriptors();
  22. Set<String> properties = new HashSet<>();
  23. for (PropertyDescriptor property : descriptors) {
  24. String propertyName = property.getName();
  25. Object propertyValue = bean.getPropertyValue(propertyName);
  26. if (propertyValue == null) {
  27. properties.add(propertyName);
  28. }
  29. }
  30. return properties.toArray(new String[0]);
  31. }
  32. /* get object's empty properties */
  33. public static String[] getEmptyProperties(Object obj) {
  34. BeanWrapper bean = new BeanWrapperImpl(obj);
  35. PropertyDescriptor[] descriptors = bean.getPropertyDescriptors();
  36. Set<String> properties = new HashSet<>();
  37. for (PropertyDescriptor property : descriptors) {
  38. String propertyName = property.getName();
  39. Object propertyValue = bean.getPropertyValue(propertyName);
  40. if (StringUtils.isEmpty(propertyValue)) {
  41. properties.add(propertyName);
  42. }
  43. }
  44. return properties.toArray(new String[0]);
  45. }
  46. }

WebUtils.java

  1. import java.net.InetAddress;
  2. import java.net.UnknownHostException;
  3. import javax.servlet.http.HttpServletRequest;
  4. import javax.servlet.http.HttpServletResponse;
  5. import org.springframework.web.context.request.RequestAttributes;
  6. import org.springframework.web.context.request.RequestContextHolder;
  7. import org.springframework.web.context.request.ServletRequestAttributes;
  8. public class WebUtils extends org.springframework.web.util.WebUtils {
  9. /* 获取request对象 */
  10. public static HttpServletRequest getRequest() {
  11. RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
  12. if (requestAttributes == null) return null;
  13. return ((ServletRequestAttributes) requestAttributes).getRequest();
  14. }
  15. /* 获取Response对象 */
  16. public static HttpServletResponse getResponse() {
  17. RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
  18. if (requestAttributes == null) return null;
  19. return ((ServletRequestAttributes) requestAttributes).getResponse();
  20. }
  21. public static boolean isAjaxReq(HttpServletRequest req) {
  22. //使用request.header检测是否为AJAX请求
  23. String contentTypeHeader = req.getHeader("Content-Type");
  24. String acceptHeader = req.getHeader("Accept");
  25. String xRequestedWith = req.getHeader("X-Requested-With");
  26. return ((contentTypeHeader != null && contentTypeHeader.contains("application/json"))
  27. || (acceptHeader != null && acceptHeader.contains("application/json"))
  28. || (acceptHeader != null && !acceptHeader.contains("text/html"))
  29. || "XMLHttpRequest".equalsIgnoreCase(xRequestedWith));
  30. }
  31. // 根据网卡取本机配置的IP
  32. public static String getServerIpAddr() {
  33. try {
  34. InetAddress inet = InetAddress.getLocalHost();
  35. return inet.getHostAddress();
  36. } catch (UnknownHostException e) {
  37. e.printStackTrace();
  38. }
  39. return null;
  40. }
  41. public static String getWebBase() {//Web访问路径
  42. HttpServletRequest request = getRequest();
  43. if (request != null) {
  44. return String.format("%s://%s:%s%s/", request.getScheme(), request.getServerName(), request.getServerPort(), request.getContextPath());
  45. }
  46. return "";
  47. }
  48. }

QRCodeUtils.java

  1. import java.awt.BasicStroke;
  2. import java.awt.Color;
  3. import java.awt.Graphics2D;
  4. import java.awt.geom.RoundRectangle2D;
  5. import java.awt.image.BufferedImage;
  6. import java.io.ByteArrayOutputStream;
  7. import java.io.File;
  8. import java.io.IOException;
  9. import java.util.Hashtable;
  10. import javax.imageio.ImageIO;
  11. import com.google.zxing.BarcodeFormat;
  12. import com.google.zxing.EncodeHintType;
  13. import com.google.zxing.WriterException;
  14. import com.google.zxing.client.j2se.MatrixToImageWriter;
  15. import com.google.zxing.common.BitMatrix;
  16. import com.google.zxing.qrcode.QRCodeWriter;
  17. import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
  18. public class QRCodeUtils {
  19. private static final String FORMAT_PNG = "JPG";//"PNG";
  20. // 二维码尺寸
  21. private static final int QRCODE_SIZE = 300;
  22. private static final int BLACK = 0xFF000000;//用于设置图案的颜色
  23. private static final int WHITE = 0xFFFFFFFF; //用于背景色
  24. public static byte[] genQRCodeImageBytes(String str) {
  25. return QRCodeUtils.genQRCodeImageBytes(str, null, QRCODE_SIZE, QRCODE_SIZE);
  26. }
  27. public static byte[] genQRCodeImageBytes(String str, String logoPath) {
  28. return QRCodeUtils.genQRCodeImageBytes(str, logoPath, QRCODE_SIZE, QRCODE_SIZE);
  29. }
  30. public static byte[] genQRCodeImageBytes(String str, String logoPath, int width, int height) {
  31. byte[] qrcode = null;
  32. try {
  33. QRCodeWriter qrCodeWriter = new QRCodeWriter();
  34. Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
  35. hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
  36. hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
  37. BitMatrix bitMatrix = qrCodeWriter.encode(str, BarcodeFormat.QR_CODE, width, height, hints);
  38. ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream();
  39. if (StringUtils.isBlank(logoPath)) {
  40. MatrixToImageWriter.writeToStream(bitMatrix, FORMAT_PNG, pngOutputStream);
  41. } else {
  42. BufferedImage image = QRCodeUtils.toBufferedImage(bitMatrix);
  43. QRCodeUtils.addLogo(image, logoPath);
  44. ImageIO.write(image, FORMAT_PNG, pngOutputStream);
  45. }
  46. qrcode = pngOutputStream.toByteArray();
  47. } catch (WriterException e) {
  48. System.out.println("Could not generate QR Code, WriterException :: " + e.getMessage());
  49. e.printStackTrace();
  50. } catch (IOException e) {
  51. System.out.println("Could not generate QR Code, IOException :: " + e.getMessage());
  52. e.printStackTrace();
  53. }
  54. return qrcode;
  55. }
  56. private static BufferedImage toBufferedImage(BitMatrix matrix) {
  57. int width = matrix.getWidth();
  58. int height = matrix.getHeight();
  59. BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
  60. for (int x = 0; x < width; x++) {
  61. for (int y = 0; y < height; y++) {
  62. image.setRGB(x, y, (matrix.get(x, y) ? BLACK : WHITE));
  63. //image.setRGB(x, y, (matrix.get(x, y) ? Color.YELLOW.getRGB() : Color.CYAN.getRGB()));
  64. }
  65. }
  66. return image;
  67. }
  68. // 二维码加 logo
  69. private static BufferedImage addLogo(BufferedImage matrixImage, String logoPath) {
  70. int matrixWidth = matrixImage.getWidth();
  71. int matrixHeigh = matrixImage.getHeight();
  72. //读取二维码图片,并构建绘图对象
  73. Graphics2D g2 = matrixImage.createGraphics();
  74. BufferedImage logoImage;
  75. try {
  76. logoImage = ImageIO.read(new File(logoPath));//读取Logo图片
  77. // 开始绘制图片
  78. g2.drawImage(logoImage, matrixWidth / 5 * 2, matrixHeigh / 5 * 2, matrixWidth / 5, matrixHeigh / 5, null);// 绘制
  79. BasicStroke stroke = new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
  80. g2.setStroke(stroke);// 设置笔画对象
  81. RoundRectangle2D.Float round = new RoundRectangle2D.Float(matrixWidth / 5 * 2, matrixHeigh / 5 * 2, matrixWidth / 5, matrixHeigh / 5, 20, 20);//指定弧度的圆角矩形
  82. g2.setColor(Color.white);
  83. g2.draw(round);// 绘制圆弧矩形
  84. // 设置logo 有一道灰色边框
  85. BasicStroke stroke2 = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
  86. g2.setStroke(stroke2);// 设置笔画对象
  87. RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(matrixWidth / 5 * 2 + 2, matrixHeigh / 5 * 2 + 2, matrixWidth / 5 - 4, matrixHeigh / 5 - 4, 20, 20);
  88. g2.setColor(new Color(128, 128, 128));
  89. g2.draw(round2);// 绘制圆弧矩形
  90. } catch (IOException e) {
  91. e.printStackTrace();
  92. }
  93. g2.dispose();
  94. matrixImage.flush();
  95. return matrixImage;
  96. }
  97. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注