`
zhouxing
  • 浏览: 198728 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

集成Java内容仓库和Spring

阅读更多

作者 Costin Leau译者 胡键 发布于 2008年2月12日 下午11时13分

社区
Java
主题
门户/内容管理系统

保存各种信息对于应用程序来说非常平常,大多数时候它们是保存在关系数据库中。数据库处理规范数据类型十分在行,但是在处理如图像、文档等二进制数据时却不是那么得心应手。尽管可以用文件系统作为替代——而且它们还提供了更好的性能。但它们既没有提供用于搜索信息的查询语言,也没有提供表示关系或事务的概念。

在很多情况下,允许第三方访问这些存储数据(随着应用程序的不断扩展,这成为一个典型的需求)是一个漫长而复杂的过程(它们不会在一夜之间完成)。内部存储结构很容易影响API架构,以及信息检索与遍历的方式。

什么是JSR-170

幸运的是,被称为Java内容仓库(Java Content Repository,JCR)的JSR-170,试图以独立于具体实现的方式解决这些(以及其它)问题。即,不论底层资源(如,数据库,本地或虚拟文件系统)是什么,API都将相同。在数据存储之上,JCR提供诸如访问粒度控制、版本控制、内容事件、全文检索和过滤等内容服务。由Day Software领导的JSR-170背后的专家组令人印象深刻,包括内容管理系统(CMS)提供商Vignette、Hummingbird Ltd.、Stellent和通用Java驱动解决方案提供商,如BEA Systems、IBM和Oracle。该规范很可能成为内容管理和文档存储方面事实上的标准。

经过几乎2年半的努力,工作最终于2005年6月完成,在javax.jcr包中,API包含了大约50个类(主要是接口和异常)。2006年早些时候,发布了初始1.0版本的参考实现(JackRabbit)。

JSR-170概览

Java内容仓库建立在仓库(除了是“用于安全地保存货物的地点”的通常含义之外)概念之上,它提供了几个操作数据的特性。仓库使用“树结构”保存信息,如下图,树由节点和属性组成。圆圈代表节点,方框代表属性。1个节点有且只有1个父亲,有任意数目的孩子(子节点)和任意数目的属性。1个属性有且只有一个父亲(它是节点),它没有子节点,由一个名字和一个或多个值组成。属性值的类型可以是:布尔(Boolean)、日期(Date)、双精(Double),长整(Long),字符串(String)或流(Stream)。只有属性可以被用来存储信息,节点则被用来创建树内部的“路径”。在某种程度上,这棵树类似文件系统的结构,节点是目录,属性是实际的文件。

仓库的功能被划分为几个“兼容性”级别,每个级别提供一组特定的特性:

  1. 级别 1

    对于所有实现,级别1是必须的,它提供对仓库的访问,简而言之:
    • 对节点和属性的读访问。
    • 对属性值的读访问。
    • 输出到XML/SAX。
    • 支持XPATH语法的查询服务。
  2. 级别 2

    级别2提供功能:
    • 增加和移除节点和属性。
    • 对属性值的写操作。
    • 从XML/SAX输入数据。

    值得注意的是,JCR的实现并不要求达到级别2或者更高层次。因此与只读仓库一起工作也是完全符合规范的。

  3. 可选级别

    “可选”级别包含一些高级特性,它并不是读写仓库所必需的,但确是真正为JSR-170增色的部分。这个级别包括(除了其它之外):
    • 事务 —— 它使仓库有可能与JMS或JDBC资源一起工作。
    • 版本标定 —— 允许仓库记录节点的不同状态,以备日后检索。规范对于这个主题有相当的篇幅;该特性使得用JSR-170作为后端构建一个CVS的克隆成为可能。
    • 事件 —— 亦称观察,它允许仓库内发生的任何活动都会被通知给客户端。
    •  —— 可以冻结部分树的功能,它可以有效地返回一个只读的子树。

API回顾

使用JSR-170时,建议使用来自javax.jcr包的接口。这样,更换JCR实现时会容易些,不会有任何代码的变动。

API的核心类是Session,它代表客户端和仓库之间的连接,使用连接活跃其上的workspace名和所提供的credentials进行定义。Session包含读(级别1)和写(级别2)方法;使用底层仓库不支持的功能时将抛出异常。

这个包还包含了那些组成仓库的单元接口的定义:WorkspaceCredentialsNodePropertyItemNodeProperty的超类)和Valuejavax.jcr.query包负责处理查询,javax.jcr.nodetype包负责定义节点类型。剩余的包负责可选级别的功能,如javax.jcr.versionjavax.jcr.observationjavax.jcr.lock。一个有趣的包是javax.jcr.util,它包含一个ItemVisitor的实现,它源自GOF(四人帮,Gang of Four)撰写的著名的设计模式中的访问者模式(Visitor-pattern)接口。

JSR-170实现

GoogleSourceForge会列出好几页的JSR-170实现,但是它们中的大多数都处于alpha阶段,没有发布任何版本。以下是一个可以自由下载的项目列表,它们已经被作者使用过:

  • Jackrabbit
    它是JSR-170的参考实现,Apache基金的一部分,提供级别1,2和可选功能。在撰写本文时,它已经经过孵化阶段并有一个官方公开的发布版本,该版本被认为足够稳定,可以被用在产品环境。此外,Jackrabbit也被用来作为Day Software(JSR-170的领导者)的商业产品的基础。除了实现JSR-170中定义的所有特性,JackRabbit还加入了额外的功能(如SessionListenersCustomNode注册),以及一个有趣的捐献来的项目套件,它包括:JCA连接器、taglib、WebDAV接口、虚拟文件系统和JDBC后端。JackRabbit的许可证是Apache 2.0。
  • eXo JCR
    它是eXo platoform的一部分,包含规范要求的所有强制特性和几个可选特性。最近一次的版本发布(1.0RC7)是2006年6月22日,基于规范的最终草案2。eXo JCR支持JDBC兼容数据库,如MySQL、DB2或HSQL(它是缺省的)作为后端存储,它是双许可的(GPL和商用),最终版的发布日期尚未确定。
  • Jeceira
    与Jackrabbit和eXo JCR相比,它是相对较新的项目。它实现了级别1和2的一些需求,只在写操作时,支持来自可选级别的观察功能。不幸的是,这个项目处于未完成阶段,在过去的9个月没有新版本发布。然而它被Magnolia(一个流行的基于java的CMS,与作为JSR-170参考实现的Jackrabbit类似)使用。在最终版发布时,它计划包含所有级别的功能,发布时间目前尚不确定。Jeceira的许可证是Apache 2.0,使用HSQL数据库作为它的存储引擎。

JCR模块

Spring Modules的一部分,JCR模块的主要目标是:以一种类似Spring主分发包中ORM包的方式,简化使用JSR-170 API进行开发。特点如下:

  • JcrTemplate,允许执行JcrCallback和异常处理(将需检查的JCR异常转换成不需检查的Spring DAO异常)。这个模板实现了来自JCR Session的绝大部分方法,可以简单地作为替换物使用。此外该模板知道线程绑定的会话,这个会话可以跨几个方法使用,这在使用事务型仓库时非常有用。
  • RepositoryFactoryBean,它配置、启动和停止仓库实例。因为JSR-170并没有说明仓库配置的标准方式,需要注意实现在这个方面的不同。这个支持包含预定义的用于Jackrabbit和Jeceira的FactoryBean,以及一个可以很容易支持其它仓库的抽象基类。
  • SessionFactory,用来统一RepositoryCredentialsWorkspace接口,允许自动注册监听器和自定义名字空间。
  • Spring声明性事务为那些实现了(可选)事务特性的仓库提供了支持。
  • OpenSessionInView拦截器和过滤器允许每个线程跨不同组件使用同一会话。与JcrTemplate一起,检索、关闭和管理JCR会话的工作已经外部化,对于调用者完全透明。

本文将使用参考实现(Jackrabbit),由于JCR模块使用的是javax.jcr接口,因此改变实现根本就是一个配置的问题。让我们一步一步地来看看在Jackrabbit之上如何使用Java内容仓库,以及如何让Spring模块来帮助完成这一工作。

配置仓库和SessionFactory

<bean id="repository" class="org.springmodules.jcr.jackrabbit.RepositoryFactoryBean">
<!-- normal factory beans params -->
<property name="configuration" value="classpath:jackrabbit-repo.xml"/>
<property name="homeDir" ref="./tmp/repo"/>
</bean>

JCR支持提供RepositoryFactoryBean类配置Jackrabbit,它需要JackRabbit的配置文件和主目录。注意,RepositoryFactoryBean在使用本地文件系统时特别有用;对于服务器环境,仓库可能被注册在JNDI中,此时可以使用JndiObjectFactoryBean帮助类(Spring分发包的一部分)检索它:

<bean id="repository" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jcr/myRepository"/>
</bean>

或使用Spring 2.0的模式名字空间:

<jndi:lookup id="entityManagerFactory" jndi-name="jcr/myRepository"/>

为了简化与JCR的工作,模块增加了SessionFactory接口:

public interface SessionFactory {
public Session getSession() throws RepositoryException;
public SessionHolder getSessionHolder(Session session);
}

SessionFactory隐藏了实现内部的认证细节,因此一旦配置完成,使用同一证书的会话可以很容易的被检索出来。为了利用实现的特性(没有涵盖在规范中的),这个接口允许检索SessionHolder。它是一个JCR模块特定类,主要被用于事务和会话管理(通过一种可用于每个JCR实现的缺省、通用实现),但是它不支持可选特性或自定义特性(如JackrabbitSessionHolder,它支持Jackrabbit的事务基础结构)。JCR模块提供一种简易、透明的方式来发现SessionHolder实现(这些我将在以后详细提到),使之很容易地插入对JSR-170其它兼容库的支持。

SessionFactory的缺省实现是JcrSessionFactory,它要求一个进行工作的仓库和证书。

<!-— SessionFactory -->
<bean id="jcrSessionFactory" class="org.springmodules.jcr.JcrSessionFactory">
<property name="repository" ref="repository"/>
<property name="credentials">
<bean class="javax.jcr.SimpleCredentials">
<constructor-arg index="0" value="bogus"/>
<!-- create the credentials using a bean factory -->
<constructor-arg index="1">
<bean factory-bean="password" factory-method="toCharArray"/>
</constructor-arg>
</bean>
</property>
</bean>

<!-- create the password to return it as a char[] -->
<bean id="password" class="java.lang.String">
<constructor-arg index="0" value="pass"/>
</bean>

这个bean声明非常简单,唯一需要注意的地方是,密码被提供给SimpleCredential的构造函数:它只接受字符数组,使用Spring工厂声明作为一种变通。

JcrTemplate

JcrTemplate是JCR模块的核心类之一,它提供了与JCR会话一起工作的方便方法,将调用者从必须处理的打开和关闭会话、事务回滚(如果底层仓库提供)、以及处理其它特性中的异常等工作中解放出来:

<bean id="jcrTemplate" class="org.springmodules.jcr.JcrTemplate">
    <property name="sessionFactory" ref="jcrSessionFactory"/>
    <property name="allowCreate" value="true"/>
</bean>

模板定义非常简单,类似来自Spring框架的其它模板类,如HibernateTemplate

例子

既然仓库已经配置了,接下来看看“Spring化”的例子之一,它来自Jackrabbit的wiki页:

public Node importFile(final Node folderNode, final File file, final String mimeType, 
final String encoding) {

return (Node) execute(new JcrCallback() {
           
/**
* @see org.springmodules.jcr.JcrCallback#doInJcr(javax.jcr.Session)
*/
public Object doInJcr(Session session) throws
RepositoryException, IOException {
  
       
JcrConstants jcrConstants = new JcrConstants(session);
       
//create the file node - see section 6.7.22.6 of the spec
Node fileNode = folderNode.addNode(file.getName(),
jcrConstants.getNT_FILE());
 
//create the mandatory child node - jcr:content
Node resNode = fileNode.addNode(jcrConstants.getJCR_CONTENT(),
jcrConstants.getNT_RESOURCE());
   
     resNode.setProperty(jcrConstants.getJCR_MIMETYPE(), mimeType);
    resNode.setProperty(jcrConstants.getJCR_ENCODING(), encoding);
resNode.setProperty(jcrConstants.getJCR_DATA(), new FileInputStream(file));
Calendar lastModified = Calendar.getInstance();
lastModified.setTimeInMillis (file.lastModified ());
resNode.setProperty(jcrConstants.getJCR_LASTMODIFIED(), lastModified);
             
session.save();
             
return resNode;
}
});
}

主要区别是:代码被包装在一个JCR模板中,它将我们从不得不使用的try/catch语句块(因为IORepository的需检查异常)和处理会话(和事务,如果有的话)清除工作中解放出来。值得提及的是硬编码字符串,如“jcr:data”,是通过JcrConstants工具类解析出来的。它知道名字空间的前缀变化,并提供一种干净的方式处理JCR常数。正如你看到的,我只是使例子更加健壮,但是对于实际业务代码影响最小。

事务支持

使用JCR模块的一个好处就是能将Spring事务基础设施(包括声明性和编程性)应用于Java内容仓库。JSR 170将事务支持视为可选特性,并没有强制一个标准的方式来暴露事务钩子,因此每个实现可以选择不同的方法。在本文撰写时,只有Jackrabbit支持事务(在它的大部分操作中),它通过为每个JcrSession暴露一个javax.transaction.XAResource做到这一点。JCR模块提供LocalTransactionManager用于本地事务:

<bean id="jcrTransactionManager" class="org.springmodules.jcr.jackrabbit.LocalTransactionManager">
<property name="sessionFactory" ref="jcrSessionFactory"/>
</bean>

为了声明事务划分,我与上述事务管理器bean声明一起使用标准Spring类:

<!-- transaction proxy for Jcr services/facades -->
<bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="proxyTargetClass">
        <value>true</value>
     </property>

     <property name="transactionManager" ref="jcrTransactionManager"/>
     <property name="transactionAttributes">
     <props>
        <prop key="save*">PROPAGATION_REQUIRED</prop>
       <prop key="*">PROPAGATION_REQUIRED, readOnly</prop>
     </props>
     </property>
</bean>
<bean id="jcrService" parent="txProxyTemplate">
    <property name="target">
        <bean class="org.springmodules.examples.jcr.JcrService">
            <property name="template" ref="jcrTemplate"/>
        </bean>
    </property>
</bean>

如果要求一个JTA管理器,一个简单而优雅的解决办法是使用来自Jackrabbit捐献包的jca连接器。为了使用jca,你并不需要一个应用服务器,因为你可以用一个可插入的JCA容器,如Jencks。JCA容器的配置已经超出本文的范围,但是你可以参考JCR模块例子中使用Jencks的例子。

TransactionAwareRepository

对于要求普通JCR代码的应用程序,JCR模块允许用直接使用JCR API的代码,透明地使用事务驱动会话。 此时,可以使用TransactionAwareRepository,它有一个参数是JcrSessionFactory。这样,在使用Session.login()(它接收定义在JcrSessionFactory中的参数)创建任何新会话时,如果发现有线程绑定的会话,就将返回它。注意:如果使用事务,JCR会话就是事务性的,否则你必须手动设置属性allowNonTxRepository为true,配置如下,要不然将抛出一个异常:

<bean id="transactionRepository" class="org.springmodules.jcr.TransactionAwareRepository">
     <property name="allowNonTxRepository" value="true"/>
     <property name="targetFactory" ref="jcrSessionFactory"/>
</bean>

transactionRepository bean可以被用作一个普通的JCR仓库,不关心底层机制或线程绑定会话、事务性或非事务性(如果有事务,关闭会话时要提交事务)。

可选特性支持侦测

为了最大化代码重用,但仍然允许插入可选特性,如用于不同JCR实现的事务支持,JCR模块使用SessionHolder接口(前面已经提到),同时还有SessionHolderProviderSessionHolderProviderManager接口。用户一般不用与它们打交道,因为它们是框架内部使用的;但是,它们代表了JCR模块主要的扩展点。

SessionHolder类被内部不同组件使用,主要被事务管理器用来操作会话,SessionHolderProviderSessionHolderProviderManager处理sessionHolder创建的方式以及提供者是如何被个别使用的。缺省将使用ServiceSessionHolderProviderManager,它利用JDK 1.3 Service Provider的自动发现特性。管理器将在类路径中搜索META-INF/services/org.springmodules.jcr.SessionHolderProvider条目,它包含了SessionHolderProvider实现的完整限定名。Jackrabbit支持就是这样配置的,JCR模块的分发包中包含一个META-INF/services/org.springmodules.jcr.SessionHolderProvider(译注:原文有误,没有给出后面的文件名)文件,它只有一行:

org.springmodules.jcr.jackrabbit.support.JackRabbitSessionHolderProvider

缺省,SessionHolderProviderManagerJcrSessionFactory内部使用,因此在工厂启动时,任何客户化实现可以被获取,并与合适的仓库一起使用。但是,通过设置JcrSessionFactory中的SessionHolderProviderManager,可以很容易的切换到一个不同的发现策略。一个可替代的发现服务是ListSessionHolderProviderManager,它接收一组提供者列表,可以方便地使用自定义提供(如测试)。

<bean id="listProviderManager" class="org.springmodules.jcr.support.ListSessionHolderProviderManager">
     <property name="providers">
         <list>
            <bean class="org.mycompany.jcr.CustomHolderProvider"/>
            <bean class="org.springmodules.jcr.jackrabbit.support.JackRabbitSessionHolderProvider"/>
            <bean class="org.springmodules.jcr.support.GenericHolderProvider"/>
         </list>
     </property
</bean>

<bean id="jcrSessionFactory" class="org.springmodules.jcr.JcrSessionFactory">
        ...
    <property name="sessionHolderProviderManager" ref="listProviderManager"/>
</bean>

注意,每个仓库一个提供者。如果列表包含多个工作于同一仓库的提供者,顺序将非常重要,因为先匹配的先使用。

Java内容仓库的未来

尽管JSR-170已经于2005年5月完成,Java内容仓库的工作并没有终止。JSR-283,官方的后继者,将聚焦于功能增强,如联邦,remoting,客户端/服务器协议映射和扩展内容模型的能力。同时还存在着一些JSR之外的想法和项目:绑定/映射框架,它可以将java类转换为一个JCR树,反之亦然(类似ORM,后端用Java内容仓库替代数据库),建构于JCR之上的WebDAV服务器(参见Jackrabbit的捐献包),以及其他。已经出现了用于不同产品的JSR-170连接器,如Alfresco、BEA Portal Server和IBM Domino。

至于JCR模块,路线图包括用于几个实现的Acegi安全集成,支持Spring 2.0名字空间模式(它将减少XML的配置)和与其它JCR实现集成。很显然,JCR的看起来一片光明。

查看英文原文:Integrating Java Content Repository and Spring

分享到:
评论

相关推荐

    JAVA毕业设计之基于Spring Boot智能无人仓库管理(springboot+mysql)完整源码.zip

    基于Spring Boot的智能无人仓库管理系统是一个现代化的、高效的仓库管理解决方案。该系统利用了Spring Boot框架的快速开发特性,结合MySQL数据库,实现了一套完整的仓库管理功能。以下是对该系统的主要特点和功能的...

    基于react+javaspring+mysql的知识分享系统源码+数据库.zip

    服务器容器:tomcat7(已集成到java项目maven仓库,即载入即用); 数据库:mysql8 当前后台使用的帐号密码 tang-123456,如需修改i请修改mvc项目的db.properties文件参数 react版本:react18 nodeJs版本:node 16

    仓库管理系统,SpringBoot+Spring Data JPA+......zip

    安全性:内置的安全特性,如OAuth2和Spring Security,确保您的应用程序安全无虞。 微服务支持:SpringBoot是微服务架构的理想选择,可以帮助您构建模块化、可扩展的应用程序。 社区支持:全球的开发者社区意味着您...

    JAVA上百实例源码以及开源项目

     Java绘制图片火焰效果,源代码相关注释:前景和背景Image对象、Applet和绘制火焰的效果的Image对象、Applet和绘制火焰的效果的Graphics对象、火焰效果的线程、Applet的高度,图片到图片装载器、绘制火焰效果的X坐标...

    spring security 参考手册中文版

    37.5 Spring MVC和CSRF集成 271 37.5.1自动令牌包含 271 37.5.2解析CsrfToken 272 第七部分 Spring数据集成 273 38. Spring Data&Spring安全配置 273 39. @Query中的安全表达式 273 第八部分 附录 274 40.安全...

    JAVA上百实例源码以及开源项目源代码

     Java绘制图片火焰效果,源代码相关注释:前景和背景Image对象、Applet和绘制火焰的效果的Image对象、Applet和绘制火焰的效果的Graphics对象、火焰效果的线程、Applet的高度,图片到图片装载器、绘制火焰效果的X坐标...

    java项目开源源码,练手

    框架的发布版本,包括集成的CLI(命令行界面),可以在Spring仓库中手动下载和安装。 具有如下特性: ● 创建独立的Spring应用程序 ● 嵌入的Tomcat,无需部署WAR文件 ● 简化Maven配置 ● 自动配置Spring ● ...

    springboot154基于Spring Boot智能无人仓库管理_源代码_数据库.zip

    涵盖前端开发、后端开发、数据库集成等核心内容。通过阅读和实践该系统源代码,将掌握Web应用程序开发技能,了解前后端交互方式。 适用人群: 该项目适合具有一定编程基础、对技术有浓厚兴趣的开发者,以及大学生...

    轻松实现基于JPA的库SpringDataJPA.zip

    特性对建立基于Spring 和 JPA 的库的支持支持 Querydsl predicates 和安全类型的 JPA 查询Transparent auditing of domain classPagination 支持, 动态查询执行, 可以集成自定义数据访问代码在 @Query 注明查询引导...

    Spring in Action(第二版 中文高清版).part2

    5.5 Spring和Java持久API 5.5.1 使用JPA模板 5.5.2 创建一个实体管理器工厂 5.5.3 建立使用JPA的DAO 5.6 Spring和iBATIS 5.6.1 配置iBATIS客户模板 5.6.2 建立基于iBATIS的DAO 5.7 缓存 5.7.1 配置缓存...

    Spring in Action(第二版 中文高清版).part1

    5.5 Spring和Java持久API 5.5.1 使用JPA模板 5.5.2 创建一个实体管理器工厂 5.5.3 建立使用JPA的DAO 5.6 Spring和iBATIS 5.6.1 配置iBATIS客户模板 5.6.2 建立基于iBATIS的DAO 5.7 缓存 5.7.1 配置缓存...

    Java毕业设计-基于springboot开发的智能无人仓库管理-毕业论文(附毕设源代码).rar

    本资源为基于Spring Boot开发的智能无人仓库管理系统的毕业设计项目,包含了完整的毕业论文和源代码,是计算机科学与技术、软件工程等相关专业学生的宝贵参考资料。该项目不仅展现了Spring Boot框架在快速构建Web...

    spring-boot-starter-diamond:将diamond集成到springboot中使用,spring-boot-starte构件

    spring-boot-starter-diamond将diamond集成到springboot中使用,spring-boot-starte构件。spring-boot-starter-diamond,让你可以使用spring-boot的方式开发diamond程序。使diamond开发变得如此简单。让你可以使用...

    spring in action英文版

     10.3 集成JavaServer Faces  10.3.1 解析变量  10.3.2 发布请求已处理事件  10.4 集成WebWork  10.4.1 WebWork1  10.4.2 XWork/WebWork2  10.5 小结  第11章 保护Spring 应用程序  11.1 ...

    Spring in Action(第2版)中文版

    16.3.2集成spring和tapestry4 16.4协同使用spring和jsf 16.4.1解析jsf管理的属性 16.4.2解析springbean 16.4.3在jsf页面中使用springbean 16.4.4在jsf中暴露应用程序环境 16.5spring中带有dwr的支持ajax的应用...

    spring-cloud-ci-template:使用GitLab和Docker的Spring Cloud模板项目和CI

    内容Spring Cloud Hello World工程: 含Eureka,Feign/Hystrix,ZuulGitLab及持续集成配置Docker及本地Docker仓库预备环境CentOS7 Linux主机两台:主机A: GitLab及GitLab Runner环境,本文档中IP为192.168.1.211主机B...

    spring-batch:Spring Batch是一个框架,用于使用Spring和Java编写脱机和批处理应用程序

    它是一个编排工具,用于部署和执行基于数据集成的微服务,包括Spring Batch应用程序。 行为守则 请参阅我们。 报告安全漏洞 请参阅我们的。 从源头建造 使用Github主页上的URL克隆git仓库: $ git clone git@...

    Java微服务架构163课

    142 Redis 为数据添加缓存-Spring Boot 集成 Redis1 142 Redis 为数据添加缓存-Spring Boot 集成 Redis2 143 HBuilder 客户端-前端功能编码演示01(可略过) 144 HBuilder 客户端-前端功能编码演示02(可略过) ...

    java实战项目_ssm__mysql_小型超市仓库管理系统__(源码+数据库脚本+文档).zip

    涵盖前端开发、后端开发、数据库集成等核心内容。通过阅读和实践该系统源代码,将掌握Web应用程序开发技能,了解前后端交互方式。 适用人群: 该项目适合具有一定编程基础、对技术有浓厚兴趣的开发者,以及大学生...

Global site tag (gtag.js) - Google Analytics