Spring源代码分析(13)---BLOB和CLOB操作(不是大就了不起)

2024-04-27 11:18

本文主要是介绍Spring源代码分析(13)---BLOB和CLOB操作(不是大就了不起),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们在项目中,经常碰到图片存储,文章存储的问题,在这类问题的解决方案中,我们经常是采用把这类大数据对象保存在文件系统中,但是这又带来了一系列问题,图片存储在文件系统中,很不安全,很多情况都是能够被人所copy,破坏等等,那么,我们可以选择将其保存在数据库中,主流数据库都已经基本实现了 Blob,Clob等数据字段类型,但是,因为JDBC没有一个Blob,Clob的具体类型实现,每种数据库对这种类型存储机制都不相同,因此,大大的降低了我们的系统在数据库的迁移性,那么这一些Spring来帮助我们解决这个该死的强耦合,大,并不是就了不起!


首先:

applicationContext.xml:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
  5.     <bean  id="dataSource"
  6.         class="org.apache.commons.dbcp.BasicDataSource">
  7.         <property name="driverClassName"
  8.             value="com.mysql.jdbc.Driver">
  9.         </property>
  10.         <property name="url" value="jdbc:mysql://127.0.0.1:3306/test"></property>
  11.         <property name="username" value="root"></property>
  12.     </bean>
  13.     <!-- 用户获取Oracle源连接 -->
  14.     <bean id="nativeJdbcExtrector" name="nativeJdbcExtrector"
  15.         class="org.springframework.jdbc.support.nativejdbc.C3P0NativeJdbcExtractor"
  16.         abstract="false" lazy-init="default" autowire="default"
  17.         dependency-check="default">
  18.     </bean>
  19.     <!-- Oracle大对象处理器 -->
  20.     <bean id="oracleLobHandler" name="oracleLobHandler"
  21.         class="org.springframework.jdbc.support.lob.OracleLobHandler"
  22.         abstract="false" lazy-init="default" autowire="default"
  23.         dependency-check="default">
  24.         <property name="nativeJdbcExtractor">
  25.             <ref bean="nativeJdbcExtractor"></ref>
  26.         </property>
  27.     </bean>
  28.     <bean id="defaultLobhandler" name="defaultLobhandler"
  29.         class="org.springframework.jdbc.support.lob.DefaultLobHandler"
  30.         abstract="false" lazy-init="default" autowire="default"
  31.         dependency-check="default">
  32.     </bean>
  33.     <bean id="lobDao" name="lobDao" class="LobDaoSupport"
  34.         abstract="false" lazy-init="default" autowire="default"
  35.         dependency-check="default">
  36.         <property name="lobHandler">
  37.             <ref bean="oracleLobHandler"></ref>
  38.         </property>
  39.     </bean>
  40. </beans>

代码:
  1. package org.syna.demo;
  2. import org.springframework.jdbc.support.lob.LobHandler;
  3. public interface Lober {
  4.     /**
  5.      * 设置大对象处理器
  6.      * @param handler
  7.      */
  8.     public void setLobHandler(LobHandler handler);
  9.     
  10. }
  1. package org.syna.demo;
  2. import java.util.List;
  3. public interface ImageReader {
  4.     
  5.     /**
  6.      * 获取存储在数据库中的图片的描述,其类型为Clob
  7.      * @param imageID
  8.      * @return
  9.      */
  10.     public List getImageDescription();
  11.     
  12.     /**
  13.      * 获取存储在数据库中的图片的输入流,其类型类Blob
  14.      * @param imageID
  15.      * @return
  16.      */
  17.     public List getImage();
  18. }

  1. package org.syna.demo;
  2. import java.sql.ResultSet;
  3. import java.sql.SQLException;
  4. import java.util.List;
  5. import org.springframework.jdbc.core.RowMapper;
  6. import org.springframework.jdbc.core.support.JdbcDaoSupport;
  7. import org.springframework.jdbc.support.lob.LobHandler;
  8. public class LobDaoSupport extends JdbcDaoSupport implements ImageReader, Lober {
  9.     private LobHandler lobHandler;
  10.     public void setLobHandler(LobHandler handler) {
  11.         this.lobHandler = handler;
  12.     }
  13.     public List getImage() {
  14.         return this.getJdbcTemplate().query("select Iamge from Images ",
  15.                 new RowMapper() {
  16.                     public Object mapRow(ResultSet rs, int rowNum)
  17.                             throws SQLException {
  18.                         return lobHandler.getBlobAsBytes(rs, 1);
  19.                     }
  20.                 });
  21.     }
  22.     public List getImageDescription() {
  23.         return this.getJdbcTemplate().query("select descripton from images",
  24.                 new RowMapper() {
  25.                     public Object mapRow(ResultSet rs, int rowNum)
  26.                             throws SQLException {
  27.                         String description = lobHandler.getClobAsString(rs, 1);
  28.                         return description;
  29.                     }
  30.                 });
  31.     }
  32.     private LobHandler handler;
  33. }
我们首先来看一下LobHandler都能做写什么?

  1. public interface LobHandler {
  2.        //将Blob对象转换为byte数组;
  3.     byte[] getBlobAsBytes(ResultSet rs, String columnName) throws SQLException;

  4.     
  5.     byte[] getBlobAsBytes(ResultSet rs, int columnIndex) throws SQLException;

  6.     //将Blob对象转换为流
  7.     InputStream getBlobAsBinaryStream(ResultSet rs, String columnName) throws SQLException;

  8.     
  9.     InputStream getBlobAsBinaryStream(ResultSet rs, int columnIndex) throws SQLException;

  10.     //将Clob转换为字符串
  11.     String getClobAsString(ResultSet rs, String columnName) throws SQLException;

  12.     
  13.     String getClobAsString(ResultSet rs, int columnIndex) throws SQLException;
  14.         //将Clob转为流
  15.     InputStream getClobAsAsciiStream(ResultSet rs, String columnName) throws SQLException;

  16.     
  17.     InputStream getClobAsAsciiStream(ResultSet rs, int columnIndex) throws SQLException;

  18.     Reader getClobAsCharacterStream(ResultSet rs, String columnName) throws SQLException;

  19.     /
  20.     Reader getClobAsCharacterStream(ResultSet rs, int columnIndex) throws SQLException;

  21.     //得到一个Lob对象的工厂,他能够生产出Blob和Clob,
  22.         //等会会进行详细分析;
  23.     LobCreator getLobCreator();

  24. }

我们来看一下OracleLobHandler的具体实现:
 
  1. public class OracleLobHandler extends AbstractLobHandler {
  2.         //Oracle大对象类的具体实现,经常我们就是在这里与数据库造成耦 //合,因为Mysql也有自己的实现;
  3.     private static final String BLOB_CLASS_NAME = "oracle.sql.BLOB";
  4.     private static final String CLOB_CLASS_NAME = "oracle.sql.CLOB";
  5.     private static final String DURATION_SESSION_FIELD_NAME = "DURATION_SESSION";
  6.     private static final String MODE_READWRITE_FIELD_NAME = "MODE_READWRITE";
  7.     protected final Log logger = LogFactory.getLog(getClass());
  8.         //一个JDBC本地抽取器;对代理连接等等作出抽取;
  9.     private NativeJdbcExtractor nativeJdbcExtractor;
  10.     private Boolean cache = Boolean.TRUE;
  11.     private Class blobClass;
  12.     private Class clobClass;
  13.     private final Map durationSessionConstants = new HashMap(2);
  14.     private final Map modeReadWriteConstants = new HashMap(2);
  15.     //在这里我们可以设置成为Oracle的抽取器;
  16.     public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) {
  17.         this.nativeJdbcExtractor = nativeJdbcExtractor;
  18.     }
  19.     
  20.     public void setCache(boolean cache) {
  21.         this.cache = new Boolean(cache);
  22.     }
  23.     //初始化驱动类的大对象;
  24.     protected synchronized void initOracleDriverClasses(Connection con) {
  25.         if (this.blobClass == null) {
  26.             try {
  27.                 // Initialize oracle.sql.BLOB class
  28.                 this.blobClass = con.getClass().getClassLoader().loadClass(BLOB_CLASS_NAME);
  29.                 this.durationSessionConstants.put(
  30.                         this.blobClass, new Integer(this.blobClass.getField(DURATION_SESSION_FIELD_NAME).getInt(null)));
  31.                 this.modeReadWriteConstants.put(
  32.                         this.blobClass, new Integer(this.blobClass.getField(MODE_READWRITE_FIELD_NAME).getInt(null)));
  33.                 // Initialize oracle.sql.CLOB class
  34.                 this.clobClass = con.getClass().getClassLoader().loadClass(CLOB_CLASS_NAME);
  35.                 this.durationSessionConstants.put(
  36.                         this.clobClass, new Integer(this.clobClass.getField(DURATION_SESSION_FIELD_NAME).getInt(null)));
  37.                 this.modeReadWriteConstants.put(
  38.                         this.clobClass, new Integer(this.clobClass.getField(MODE_READWRITE_FIELD_NAME).getInt(null)));
  39.             }
  40.             catch (Exception ex) {
  41.                 throw new InvalidDataAccessApiUsageException(
  42.                         "Couldn't initialize OracleLobHandler because Oracle driver classes are not available. " +
  43.                         "Note that OracleLobHandler requires Oracle JDBC driver 9i or higher!", ex);
  44.             }
  45.         }
  46.     }
  47.         //委托给Blob接口;  
  48.     public byte[] getBlobAsBytes(ResultSet rs, int columnIndex) throws SQLException {
  49.         logger.debug("Returning Oracle BLOB as bytes");
  50.         Blob blob = rs.getBlob(columnIndex);
  51.         return (blob != null ? blob.getBytes(1, (int) blob.length()) : null);
  52.     }
  53.     public InputStream getBlobAsBinaryStream(ResultSet rs, int columnIndex) throws SQLException {
  54.         logger.debug("Returning Oracle BLOB as binary stream");
  55.         Blob blob = rs.getBlob(columnIndex);
  56.         return (blob != null ? blob.getBinaryStream() : null);
  57.     }
  58.     public String getClobAsString(ResultSet rs, int columnIndex) throws SQLException {
  59.         logger.debug("Returning Oracle CLOB as string");
  60.         Clob clob = rs.getClob(columnIndex);
  61.         return (clob != null ? clob.getSubString(1, (int) clob.length()) : null);
  62.     }
  63.     public InputStream getClobAsAsciiStream(ResultSet rs, int columnIndex) throws SQLException {
  64.         logger.debug("Returning Oracle CLOB as ASCII stream");
  65.         Clob clob = rs.getClob(columnIndex);
  66.         return (clob != null ? clob.getAsciiStream() : null);
  67.     }
  68.     public Reader getClobAsCharacterStream(ResultSet rs, int columnIndex) throws SQLException {
  69.         logger.debug("Returning Oracle CLOB as character stream");
  70.         Clob clob = rs.getClob(columnIndex);
  71.         return (clob != null ? clob.getCharacterStream() : null);
  72.     }
  73.     public LobCreator getLobCreator() {
  74.         return new OracleLobCreator();
  75.     }
  76.        //内部类,具体的Lob工厂,能够生成Oracle的Lob对象;
  77.     protected class OracleLobCreator implements LobCreator {
  78.         private final List createdLobs = new LinkedList();
  79.         public void setBlobAsBytes(PreparedStatement ps, int paramIndex, final byte[] content)
  80.                 throws SQLException {
  81.             if (content != null) {
  82.                 Blob blob = (Blob) createLob(ps, falsenew LobCallback() {
  83.                     public void populateLob(Object lob) throws Exception {
  84.                         Method methodToInvoke = lob.getClass().getMethod("getBinaryOutputStream"new Class[0]);
  85.                         OutputStream out = (OutputStream) methodToInvoke.invoke(lob, (Object[]) null);
  86.                         FileCopyUtils.copy(content, out);
  87.                     }
  88.                 });
  89.                 ps.setBlob(paramIndex, blob);
  90.                 if (logger.isDebugEnabled()) {
  91.                     logger.debug("Set bytes for Oracle BLOB with length " + blob.length());
  92.                 }
  93.             }
  94.             else {
  95.                 ps.setBlob(paramIndex, null);
  96.                 logger.debug("Set Oracle BLOB to null");
  97.             }
  98.         }
  99.         public void setBlobAsBinaryStream(
  100.                 PreparedStatement ps, int paramIndex, final InputStream binaryStream, int contentLength)
  101.                 throws SQLException {
  102.             if (binaryStream != null) {
  103.                 Blob blob = (Blob) createLob(ps, falsenew LobCallback() {
  104.                     public void populateLob(Object lob) throws Exception {
  105.                         ///生成一个空的Blob对象以后,用getBinaryOutputStream得到一个输出流,从一个二进制输入流中将流输出到Blob对象中;前后调用的Open和Close方法就是关闭流的操作;
  106.                         Method methodToInvoke = lob.getClass().getMethod("getBinaryOutputStream", (Class[]) null);
  107.                         OutputStream out = (OutputStream) methodToInvoke.invoke(lob, (Object[]) null);
  108.                         FileCopyUtils.copy(binaryStream, out);
  109.                     }
  110.                 });
  111.                 ps.setBlob(paramIndex, blob);
  112.                 if (logger.isDebugEnabled()) {
  113.                     logger.debug("Set binary stream for Oracle BLOB with length " + blob.length());
  114.                 }
  115.             }
  116.             else {
  117.                 ps.setBlob(paramIndex, null);
  118.                 logger.debug("Set Oracle BLOB to null");
  119.             }
  120.         }
  121.         public void setClobAsString(PreparedStatement ps, int paramIndex, final String content)
  122.             throws SQLException {
  123.             if (content != null) {
  124.                 Clob clob = (Clob) createLob(ps, truenew LobCallback() {
  125.                     public void populateLob(Object lob) throws Exception {
  126.                         Method methodToInvoke = lob.getClass().getMethod("getCharacterOutputStream", (Class[]) null);
  127.                         Writer writer = (Writer) methodToInvoke.invoke(lob, (Object[]) null);
  128.                         FileCopyUtils.copy(content, writer);
  129.                     }
  130.                 });
  131.                 ps.setClob(paramIndex, clob);
  132.                 if (logger.isDebugEnabled()) {
  133.                     logger.debug("Set string for Oracle CLOB with length " + clob.length());
  134.                 }
  135.             }
  136.             else {
  137.                 ps.setClob(paramIndex, null);
  138.                 logger.debug("Set Oracle CLOB to null");
  139.             }
  140.         }
  141.         public void setClobAsAsciiStream(
  142.                 PreparedStatement ps, int paramIndex, final InputStream asciiStream, int contentLength)
  143.             throws SQLException {
  144.             if (asciiStream != null) {
  145.                 Clob clob = (Clob) createLob(ps, truenew LobCallback() {
  146.                     public void populateLob(Object lob) throws Exception {
  147.                         Method methodToInvoke = lob.getClass().getMethod("getAsciiOutputStream", (Class[]) null);
  148.                         OutputStream out = (OutputStream) methodToInvoke.invoke(lob, (Object[]) null);
  149.                         FileCopyUtils.copy(asciiStream, out);
  150.                     }
  151.                 });
  152.                 ps.setClob(paramIndex, clob);
  153.                 if (logger.isDebugEnabled()) {
  154.                     logger.debug("Set ASCII stream for Oracle CLOB with length " + clob.length());
  155.                 }
  156.             }
  157.             else {
  158.                 ps.setClob(paramIndex, null);
  159.                 logger.debug("Set Oracle CLOB to null");
  160.             }
  161.         }
  162.         public void setClobAsCharacterStream(
  163.                 PreparedStatement ps, int paramIndex, final Reader characterStream, int contentLength)
  164.             throws SQLException {
  165.             if (characterStream != null) {
  166.                 Clob clob = (Clob) createLob(ps, truenew LobCallback() {
  167.                     public void populateLob(Object lob) throws Exception {
  168.                         Method methodToInvoke = lob.getClass().getMethod("getCharacterOutputStream", (Class[]) null);
  169.                         Writer writer = (Writer) methodToInvoke.invoke(lob, (Object[]) null);
  170.                         FileCopyUtils.copy(characterStream, writer);
  171.                     }
  172.                 });
  173.                 ps.setClob(paramIndex, clob);
  174.                 if (logger.isDebugEnabled()) {
  175.                     logger.debug("Set character stream for Oracle CLOB with length " + clob.length());
  176.                 }
  177.             }
  178.             else {
  179.                 ps.setClob(paramIndex, null);
  180.                 logger.debug("Set Oracle CLOB to null");
  181.             }
  182.         }
  183.         /**
  184.          * Create a LOB instance for the given PreparedStatement,
  185.          * populating it via the given callback.
  186.          */
  187.         protected Object createLob(PreparedStatement ps, boolean clob, LobCallback callback)
  188.                 throws SQLException {
  189.             Connection con = null;
  190.             try {
  191.                 con = getOracleConnection(ps);
  192.                 initOracleDriverClasses(con);
  193.                 Object lob = prepareLob(con, clob ? clobClass : blobClass);
  194.                 callback.populateLob(lob);
  195.                 ///lob.close();
  196.                 lob.getClass().getMethod("close", (Class[]) null).invoke(lob, (Object[]) null);
  197.                 //利用这个工厂所生产出来的连接会在工厂关闭时进行统一的freeTemporary方法调用;
  198.              this.createdLobs.add(lob);
  199.                 if (logger.isDebugEnabled()) {
  200.                     logger.debug("Created new Oracle " + (clob ? "CLOB" : "BLOB"));
  201.                 }
  202.                 return lob;
  203.             }
  204.             catch (SQLException ex) {
  205.                 throw ex;
  206.             }
  207.             catch (InvocationTargetException ex) {
  208.                 if (ex.getTargetException() instanceof SQLException) {
  209.                     throw (SQLException) ex.getTargetException();
  210.                 }
  211.                 else if (con != null && ex.getTargetException() instanceof ClassCastException) {
  212.                     throw new InvalidDataAccessApiUsageException(
  213.                             "OracleLobCreator needs to work on [oracle.jdbc.OracleConnection], not on [" +
  214.                             con.getClass().getName() + "]: specify a corresponding NativeJdbcExtractor",
  215.                             ex.getTargetException());
  216.                 }
  217.                 else {
  218.                     throw new DataAccessResourceFailureException("Could not create Oracle LOB",
  219.                             ex.getTargetException());
  220.                 }
  221.             }
  222.             catch (Exception ex) {
  223.                 throw new DataAccessResourceFailureException("Could not create Oracle LOB", ex);
  224.             }
  225.         }
  226.         /**
  227.          * 抽取连接.
  228.          */
  229.  
  230.         protected Connection getOracleConnection(PreparedStatement ps)
  231.                 throws SQLException, ClassNotFoundException {
  232.             return (nativeJdbcExtractor != null) ?
  233.                     nativeJdbcExtractor.getNativeConnectionFromStatement(ps) : ps.getConnection();
  234.         }
  235.         /**
  236.          * Create and open an oracle.sql.BLOB/CLOB instance via reflection.
  237.          */
  238.         protected Object prepareLob(Connection con, Class lobClass) throws Exception {
  239.             /*
  240.             BLOB blob = BLOB.createTemporary(con, false, BLOB.DURATION_SESSION);
  241.             blob.open(BLOB.MODE_READWRITE);
  242.             return blob;
  243.             */

  244.             Method createTemporary = lobClass.getMethod(
  245.                     "createTemporary"new Class[] {Connection.class, boolean.classint.class});
  246.             Object lob = createTemporary.invoke(
  247.                     nullnew Object[] {con, cache, durationSessionConstants.get(lobClass)});
  248.             Method open = lobClass.getMethod("open"new Class[] {int.class});
  249.             open.invoke(lob, new Object[] {modeReadWriteConstants.get(lobClass)});
  250.             return lob;
  251.         }
  252.         /**
  253.          * Free all temporary BLOBs and CLOBs created by this creator.
  254.          */
  255.         public void close() {
  256.             try {
  257.                 for (Iterator it = this.createdLobs.iterator(); it.hasNext();) {
  258.                     /*
  259.                     BLOB blob = (BLOB) it.next();
  260.                     blob.freeTemporary();
  261.                     */
  262.                     Object lob = it.next();
  263.                     Method freeTemporary = lob.getClass().getMethod("freeTemporary"new Class[0]);
  264.                     freeTemporary.invoke(lob, new Object[0]);
  265.                     it.remove();
  266.                 }
  267.             }
  268.             catch (InvocationTargetException ex) {
  269.                 logger.error("Could not free Oracle LOB", ex.getTargetException());
  270.             }
  271.             catch (Exception ex) {
  272.                 throw new DataAccessResourceFailureException("Could not free Oracle LOB", ex);
  273.             }
  274.         }
  275.     }
  276.     /**
  277.      * Internal callback interface for use with createLob.
  278.      */
  279.     protected static interface LobCallback {
  280.         /**
  281.          * Populate the given BLOB or CLOB instance with content.
  282.          * @throws Exception any exception including InvocationTargetException
  283.          */
  284.         void populateLob(Object lob) throws Exception;
  285.     }
  286. }
因为大对象有Blob和Clob两种,所以这里大大对象的生成都是通过反射来做的;基本实现方式都是这种;

  1.             BLOB blob = BLOB.createTemporary(con, false, BLOB.DURATION_SESSION);
  2.             blob.open(BLOB.MODE_READWRITE);
  3.             return blob;
Clob同理;

至于如何插入Blob,Clob对象,那么就跟我们开始看见的一样,必须用到LobCreater工厂生产出大对象;

  1. private void execute saveImage(String description,byte[] content,int id){
  2.         this.getJdbcTemplate().execute("insert into IMAGES(id,description,content)"new AbstractLobCreatingPreparedStatementCallback(this.lobHandler){
  3.             @Override
  4.             protected void setValues(PreparedStatement ps, LobCreator lobCreator)
  5.                     throws SQLException, DataAccessException {
  6.                ps.setInt(1, id);
  7.                lobCreator.setClobAsString(ps, 2, description);
  8.                lobCreator.setBlobAsBytes(ps, 3, content);
  9.             }
  10.         });
  11.     }
这个PreparedStatementCallback子类如下:
  1. public abstract class AbstractLobCreatingPreparedStatementCallback implements PreparedStatementCallback {
  2.     private final LobHandler lobHandler;
  3.     public AbstractLobCreatingPreparedStatementCallback(LobHandler lobHandler) {
  4.         this.lobHandler = lobHandler;
  5.     }
  6.     public final Object doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
  7.         LobCreator lobCreator = this.lobHandler.getLobCreator();
  8.         try {
  9.             setValues(ps, lobCreator);
  10.             return new Integer(ps.executeUpdate());
  11.         }
  12.         finally {
  13.             lobCreator.close();
  14.         }
  15.     }
  16.     
  17.     protected abstract void setValues(PreparedStatement ps, LobCreator lobCreator)
  18.             throws SQLException, DataAccessException;
  19. }
又是一次模板模式的应用;
这时,我们切换数据库的时候,不用再修改源代码,把Oracle.sql.BLOB修改成为om.mysql.jdbc.Blob了,我们只要修改注入到dao中的LobHandler就可以啦;


这篇关于Spring源代码分析(13)---BLOB和CLOB操作(不是大就了不起)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/940358

相关文章

Java NoClassDefFoundError运行时错误分析解决

《JavaNoClassDefFoundError运行时错误分析解决》在Java开发中,NoClassDefFoundError是一种常见的运行时错误,它通常表明Java虚拟机在尝试加载一个类时未能... 目录前言一、问题分析二、报错原因三、解决思路检查类路径配置检查依赖库检查类文件调试类加载器问题四、常见

Java注解之超越Javadoc的元数据利器详解

《Java注解之超越Javadoc的元数据利器详解》本文将深入探讨Java注解的定义、类型、内置注解、自定义注解、保留策略、实际应用场景及最佳实践,无论是初学者还是资深开发者,都能通过本文了解如何利用... 目录什么是注解?注解的类型内置注编程解自定义注解注解的保留策略实际用例最佳实践总结在 Java 编程

Java 实用工具类Spring 的 AnnotationUtils详解

《Java实用工具类Spring的AnnotationUtils详解》Spring框架提供了一个强大的注解工具类org.springframework.core.annotation.Annot... 目录前言一、AnnotationUtils 的常用方法二、常见应用场景三、与 JDK 原生注解 API 的

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及

Java中的StringBuilder之如何高效构建字符串

《Java中的StringBuilder之如何高效构建字符串》本文将深入浅出地介绍StringBuilder的使用方法、性能优势以及相关字符串处理技术,结合代码示例帮助读者更好地理解和应用,希望对大家... 目录关键点什么是 StringBuilder?为什么需要 StringBuilder?如何使用 St

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.

Python中pywin32 常用窗口操作的实现

《Python中pywin32常用窗口操作的实现》本文主要介绍了Python中pywin32常用窗口操作的实现,pywin32主要的作用是供Python开发者快速调用WindowsAPI的一个... 目录获取窗口句柄获取最前端窗口句柄获取指定坐标处的窗口根据窗口的完整标题匹配获取句柄根据窗口的类别匹配获取句

Maven中引入 springboot 相关依赖的方式(最新推荐)

《Maven中引入springboot相关依赖的方式(最新推荐)》:本文主要介绍Maven中引入springboot相关依赖的方式(最新推荐),本文给大家介绍的非常详细,对大家的学习或工作具有... 目录Maven中引入 springboot 相关依赖的方式1. 不使用版本管理(不推荐)2、使用版本管理(推

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows