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

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听