`
kang275284
  • 浏览: 165312 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

迁移到Spring

阅读更多
我是这个团体的后来者。该团体就是Spring framework团体。对于后来者来说,Spring是基于Apache 2.0许可证发布的基础架构代码库。其核心是反转控制容器,开发团队围绕该容器为JDBC样板代码和JMS代码、web MVC框架等创建模板。

  我之所以说自己是后来者,是因为,尽管Spring已非常成熟和公开,但我仍然花了一段时间来试用它。我的问题是,“Spring可以为我做什么?”为了找出答案,我将现有的参考应用程序换成了Spring组件。我认识到很早以前就应该开始使用Spring,现在应用程序的代码没有以前那么混乱,应该更易于调试和扩展,并且它更为清楚,因为借助Spring对应的内容,可以丢弃一些自定义的helper代码。

  在本文中,我将和大家共享我在尝试中得到的想法和发现。具体地讲,我将解释如何使用Spring组件替换参考应用程序的单例注册库(Singleton registry)、JDBC代码和web前端层。还将描述遇到的障碍和我的解决方法。

  要阅读本文,您不必是Spring专家,但是我在后面的内容中提供了Spring资源的链接

  样例代码使用Sun的JDK 1.5.0_07 for Linux,在Spring 1.2.x中进行了测试。

原(旧)代码

  我不想对实际的生产应用程序进行试验,因此从我编写的另一篇文章中摘出了一个测试应用程序。它是一个简单的Java web应用程序,以两个servlet页面控制器作为入口点。这些servlet通过数据访问对象(DAO)与数据库交互,而该DAO从本地DataSource获取数据库链接。相关对象调用单例注册库来相互查找。具体而言:

  • SimpleDAO:向数据库传输信息对象或从中传输信息对象
  • DbUtil:用于处理JDBC ResultSet、Connection等内容的方便例程
  • ObjectRegistry:单例注册库,对象通过它进行相互查找
  • SetupDataSourceContextListener:设置JDBC DataSource
  • SetupDBContextListener:准备(嵌入式)数据库
  • GetDataServlet:用于显示数据的页面控制器
  • PutDataServlet:用于存储数据的页面控制器

  这是一个非常简单的web应用程序,但它是独立的(self-contained)并且能展现出大型N-层应用程序的行为。从这种超小规模的试验观察到的结果可以应用于实际的转换项目。

更改内部结构:对象注册库

  仔细观察的第一个类是ObjectRegistry,它是相关对象之间的粘合层:

package pool_test.util ;public class ObjectRegistry {  private static ObjectRegistry _instance =    new ObjectRegistry() ;  public static ObjectRegistry getInstance(){    return( _instance ) ;  }  private Map _singletons ;  public void put(    final String key , final Object obj  ){    _singletons.put( key , obj ) ;  }    public Object get( final String key ){    return( _singletons.get( key ) ) ;  }}

  ObjectRegistry实际上是String:Object对的大规模映射。可以在该注册库的某个位置存储一个对象(put()),然后从另一个位置获取该对象(get())。使用注册库削弱了对象的依赖关系,因为获取对象的代码只需了解其常规类型(接口或超类)和查找键。具体的实现、实例化和配置由调用put()来存储该对象的代码实现。

  这可以正常工作,我曾经看到过这在更大规模的项目中正常工作,但它绝非完美。put()丢失或位置错误可以导致空指针错误或堆栈溢出。还必须跟踪对象在注册库中的存储顺序,以确保不会尝试获取不存在的对象。在小型应用程序中,可以使用ContextListener(本文中我也是如此)来处理实例化顺序,但是在较大的应用程序中,需要更多工作才能避免出现问题。

  旧的单例注册库的另一个问题在于:显式的put()操作是Java调用。这意味着对存储对象实现的任何更改(比如说,您希望为测试存根转入您的数据库支持的DAO)都需要重新编译。一次错误的签入,我的实际生产应用程序使用了该DAO存根。同样,这在较大的应用程序中也难以跟踪,因为它在代码中隐藏得很深。

  只需一小段Spring代码即可解决这些缺点。下面是新的注册库:

package pool_test.util ;import org.springframework....ApplicationContext ;import org.springframework.   ...ClasspathXMLApplicationContext ;public class ObjectRegistry {  private ApplicationContext _singletons ;    private ObjectRegistry(){    _singletons =      new ClassPathXmlApplicationContext(        new String[] { "spring-objectregistry.xml" }      );          }  public Object get( final String key ){    return( _singletons.getBean( key ) ) ;  }}

  请注意,我使用Spring ApplicationContext替换了以前的Map。与Map类似,ApplicationContext用于存储对象,并允许您根据名称获取这些对象。相比之下,ApplicationContext从XML文件中读取所有对象定义,而该XML文件负责实现具体配置。更改spring-objectregistry.xml中的定义,要求重新启动应用程序,但是不需要完全重新编译。

  考虑下面这段摘自spring-objectregistry.xml的内容:

<bean  id="ObjectPool"  class="org.apache...GenericObjectPool"  singleton="true">  <-- omitted for brevity --></bean><bean  id="DataSource"  class="org.apache...PoolingDataSource"  singleton="true">  <property name="pool">    <ref local="ObjectPool" />  </property></bean><bean  id="DAO"  class="pool_test.data.jdbc.SimpleDAO"  singleton="true">  <property name="dataSource">    <ref local="DataSource"/>  </property>             </bean>

  XML元素对应于Reflection调用:外部的<bean/>元素定义了一个对象,内部的<property/>元素对该对象调用mutator方法。例如,对于id为DAO的bean,Spring首先实例化一个SimpleDAO类型的对象,然后对其调用setDataSource()。setDataSource()的参数是bean DataSource,在这个文件前面的内容中定义了该bean。

  Spring在幕后配置DataSource,并将其指派给此DAO。其他Spring管理的对象只需通过bean名称(“DAO”)即可引用该DAO,这样,它们不必了解其实现中的更改(此处为“SimpleDAO”)。

  既然Spring管理这些对象,ObjectRegistry对于客户端代码就是只读的。我可以从ObjectRegistry类中删除put()方法,同样可以删除其他类中的显式put()调用。例如,SetupDataSourceContextListener现在只需使用其初始连接来填充该池。

  现在web.xml部署描述符中也只有一些必需内容了。例如,一些上下文参数指向JDBC之类的本地属性文件。Spring现在收集使用这些属性文件的对象,自己为其赋值。

  Spring还负责在spring-objectregistry.xml中跟踪这些对象之间的依赖关系。以前我在代码中自己处理这些事务。现在,随着在该应用程序中使用的依赖注入越来越多,Spring将确保在客户端代码尝试使用这些引用对象之前,以正确的顺序创建这些对象。这意味着除了整理代码以外,Spring还承担了一些簿记工作。

  有人可能会说,“纯”IoC方法可以消除对显式的、可调用ObjectRegistry的需求,而让Spring在运行时管理对象关系。这将作为将来的重构考虑。这会在将来造成一点小问题,但是现在我仍然需要注册库。

更改数据层:Spring JDBC

  配置自定义DataSource是XML可以完美实现的工作。Spring还提供了DAO基类,用于消除JDBC样板代码。这意味着Spring framework负责管理连接和关闭ResultSet和PreparedStatement。剩下的是我的应用程序特有的代码。

  新的DAO拥有与其祖先相同的接口:

package pool_test.data.jdbc ;public class SimpleDAO {  public void setupTable() ;  public void putData() ;  public Collection getData() ;  public void destroyTable() ;}

  实际上它是不同的事物。尽管旧的DAO版本拥有很多内联JDBC代码,但新版本将这个麻烦的工作委托给Spring:

package pool_test.data.jdbc ;public class SimpleDAO extends JdbcDaoSupport {  private GetDataWorker _getDataWorker ;  private PutDataWorker _putDataWorker ;  private CreateTableWorker _createTableWorker ;  private DestroyTableWorker _destroyTableWorker ;  // constructor is now empty  protected void initDao() throws Exception {        super.initDao() ;        _getDataWorker =      new GetDataWorker( getDataSource() ) ;    _putDataWorker =      new PutDataWorker( getDataSource() ) ;    _createTableWorker =      new CreateTableWorker( getDataSource() ) ;    _destroyTableWorker =      new DestroyTableWorker( getDataSource() ) ;    return ;      } // initDao()  public void setupTable() {    _createTableWorker.update() ;  }  public Collection getData() {    return( _getDataWorker.execute() ) ;  }  // ... destroyTable() and getData()  //   follow similar conventions ...}

  第一项变化是父类:SimpleDAO现在扩展Spring的JdbcDaoSupport,JdbcDaoSupport有几个用于处理数据库工作的方法和内部类。其中第一个方法是setDataSource(),它为该对象指派一个JDBC DataSource。子类调用getDataSource()来获取该对象。

  initDao()是从JdbcDaoSupport继承的另一个方法。父类调用该方法为其子类提供运行任何一次性初始化代码的机会。此处,SimpleDAO为其成员变量赋值。

  成员变量也是新的:转移到Spring JDBC意味着将的SimpleDAO的功能(获取和存储数据)转变成专门的内部类(如GetDataWorker和PutDataWorker)。每个DAO操作均有一个内部类。例如,存储数据由PutDataWorker负责:

package pool_test.data.jdbc ;import org.springframework ... SqlUpdate ;public class SimpleDAO { ...   private class PutDataWorker extends SqlUpdate {         public PutDataWorker( final DataSource ds ){             super( ds , SQL_PUT_DATA ) ;           declareParameter(             new SqlParameter( Types.VARCHAR ) ) ;       declareParameter(             new SqlParameter( Types.INTEGER ) ) ;     }     // a real app would load the SQL statements     //   from an external source...     private static final String SQL_PUT_DATA =       "INSERT INTO info VALUES( ? , ? )" ;   }   ...}

  PutDataWorker扩展了SqlUpdate,而SqlUpdate是Spring模板类,用于处理SQL INSERT和UPDATE调用的复杂工作。declareParameter()调用告知Spring该SQL语句使用的数据类型,分别是一个字符串和一个数字。

  注意,PutDataWorker类是一个非常简单的类。它调用super()向其父类传递DataSource和SQL语句,并调用declareParameter()来描述该查询。SqlUpdate处理实际与JDBC相关对象的交互工作,并关闭连接。SimpleDAO.putData()也同样被简化了:

public class SimpleDAO {  public void putData() {    for( ... ){      // ... "nameParam" and "numberParam" are      // local loop variables ...      Object[] params = {        nameParam , // variable is a Java String         numberParam // some Java numeric type      } ;      _putDataWorker.update( params ) ;    }  }}

  putData()使用一些无意义的数据填充该数据库。注意,该方法委托给其工作类。具体而言,委托给其工作类继承的方法。SqlUpdate.update()负责获取数据,并关闭JDBC Connection和相应的Statement对象。这意味着我可以丢弃很多自定义JDBC代码,甚至整个类:旧的DbUtil拥有方便的方法,用于关闭Connection、Statement和ResultSet。

  SqlUpdate对更新调用所作的工作,Spring的MappingSqlQuery对查询也作同样处理。注意,GetDataWorker中的方法mapRow():

package pool_test.data.jdbc ;import org.springframework ... MappingSqlQuery ;// inside class SimpleDAO ...private class GetDataWorker  extends MappingSqlQuery {  // ...constructor similar to PutDataWorker...    protected Object mapRow( final ResultSet rs ,       final int rowNum ) throws SQLException  {            final SimpleDTO result = new SimpleDTO(        rs.getString( "names" ) ,        rs.getInt( "numbers" )      ) ;      return( result ) ;         } // mapRow()}

  该方法负责将表格式的ResultSet数据转换成可工作的SimpleDTO对象,一次一行。Spring对结果集中的每行数据均调用这个方法。尽管GetDataWorker.mapRow()与ResultSet交互,但是它不另外负责close(),或检查是否还有一些行需要处理

更改Web层:SpringMVC

  既然已经使基础架构和数据代码Spring化,下面该处理web层了。此处的中心类是Spring MVC的Controller接口。

package org.springframework ...interface Controller {  public ModelAndView handleRequest(    HttpServletRequest request ,    HttpServletResponse response  ) throws Exception ;        }

  入口点handleRequest()的签名与Struts Action类甚至与自制的页面控制器相似:该框架提供了servlet请求和响应对象,该控制器实现返回了一些业务逻辑的结果(模型),以及用于指导如何显示这些内容的指示器(视图)。ModelAndView模型是将在视图层操作的业务对象或其他对象的Map。在样例代码中,视图是JSP,但Spring MVC还支持Velocity模板和XSLT。

  样例应用程序的servlet页面控制器非常简单,以至于无法表现Spring MVC的强大功能。因此,更新的页面控制器无法与大多数课本示例相比。

  旧的页面控制器在从servlet向JSP传递Map对象时使用类似的策略。因此,我没有为此对JSP进行任何更改。也不必使用任何Spring特有的标签库。

  在新的基于Spring的控制器中仍然需要做一些工作,尽管:它们调用ObjectRegistry来查找DAO。在纯Spring世界中,应该在web特有的XML配置文件(此处为WEB-INF/SpringMVC-servlet.xml)中将DAO指派给控制器。

  这听起来很简单,是不是?我向web.xml添加了该对象注册库的Spring配置文件spring-objectregistry.xml,如下所示:

<context-param>  <param-name>    contextConfigLocation  </param-name>  <param-value>    classpath*:spring-objectregistry.xml  </param-value><context-param>

  现在,在WEB-INF/SpringMVC-servlet.xml中就能看到spring-objectregistry.xml中指定的对象。

  这么作会造成另一个问题:MVC层将文件spring-objectregistry.xml和SpringMVC-servlet.xml加载到一个ApplicationContext中。对象注册库将spring-objectregistry.xml加载到不同的ApplicationContext中。这两个ApplicationContext存在于自己的世界中,默认情况下,无法看到对方的bean定义。

  同样,spring-objectregistry.xml中定义的对象也将被加载两次:一次由MVC层加载,另一次由对象注册库加载。然后spring-objectregistry.xml中的“单例对象”实际上不再是单例的。在样例代码中,这些都是无状态的对象。但是在较大的应用程序中,一些单例对象可能会有状态。如果不一次性加载这些对象,并且仅加载一次,就会遇到同步问题。如果这类对象要执行一些一次性的资源密集型操作,应用程序的性能就会降低。

  我的第一反应是重构ObjectRegistry之类的不必要代码。这项工作很简单,但这是一个学习练习。要模拟较大的项目(其中删除注册库不再是一次就能完成的工作),我决定坚持这样作,并找出如何才能使这两个世界工作。

  简而言之,我需要使用某种方式将ObjectRegistry(spring-objectregistry.xml)的对象公开成web层(WEB-INF/SpringMVC-servlet.xml)使用的对象。Spring的解决方案是BeanFactoryLocator,它是ApplicationContext的注册库。我可以告知对象注册库和MVC层都从BeanFactoryLocator中加载公用对象。

  首先,必须更改ObjectRegistry,使其不再显式地加载spring-objectregistry.xml:

import org.springframework....BeanFactoryLocator ;import org.springframework.    ...ContextSingletonBeanFactoryLocator ;import org.springframework.    ...BeanFactoryReference ;// this was an ApplicationContext beforeprivate final BeanFactoryReference _singletons ;private ObjectRegistry(){  // ContextSingletonBeanFactoryLocator loads  //   contents of beanRefContext.xml  BeanFactoryLocator bfl =    ContextSingletonBeanFactoryLocator      .getInstance() ;  BeanFactoryReference bf =    bfl.useBeanFactory( "OBJ_REGISTRY_DEFS" );                           _singletons = bf ;}public Object get( final String key ){  return( _singletons.getFactory().getBean( key ) ) ;}

  以上代码将ApplicationContext替换成BeanFactoryReference,名称为OBJ_REGISTRY_DEFS,是从BeanFactoryLocator中得到的。同样,OBJ_REGISTRY_DEFS定义在名为beanRefContext.xml中:

<beans>  <bean    id="OBJ_REGISTRY_DEFS"    class="...ClassPathXmlApplicationContext"  >    <constructor-arg>      <list>        <value>spring-objectregistry.xml</value>      </list>    </constructor-arg>  </bean></beans>

  名为OBJ_REGISTRY_DEFS的bean实际上是原对象注册库配置文件(spring-objectregistry.xml)支持的ApplicationContext。对BeanFactoryReference调用getBean(),只是将其传递给底层的ApplicationContext。

  ApplicationContext自己负责ObjectRegistry。要使web层也使用OBJ_REGISTRY_DEFS(也就是,要使web层Spring配置SpringMVC-config.xml能够看到其中定义的对象),在web.xml中增加一些条目:

<context-param>     <param-name>       parentContextKey     </param-name>     <param-value>       OBJ_REGISTRY_DEFS     </param-value>  </context-param>  <context-param>     <param-name>       locatorFactorySelector     </param-name>     <param-value>       classpath*:beanRefContext.xml     </param-value>  </context-param>

  第一个条目告知web层Spring配置,它应该对任何找不到的对象调用名为OBJ_REGISTRY_DEFS的BeanFactoryReference。第二个条目告知框架从classpath加载名为beanRefContext.xml的任何文件。

  现在,spring-objectregistry.xml中定义的对象可以被SpringMVC-config.xml中的web层对象看到。这意味着可以逐步淘汰ObjectRegistry,而不是尝试一步实现这样影响深远的更改。

  不好看?是的。粘合代码?是的。这是当您已经拥有自己的单例注册库时,将应用程序迁移到Spring的一种方式?毫无疑问。现在,此应用程序将来不再需要重构:删除ObjectRegistry(及其显式加载的ApplicationContext)只会影响ObjectRegistry的客户端代码。

  但是有一点警告需要注意:Spring文档说明BeanFactoryLocator并非用于日常使用。它应该用于这类迁移项目。作为对照,如果您计划对新应用程序使用Spring,您的设计应该从头考虑正确的IoC注入。

结束语

  将原应用程序与更改后的应用程序进行比较,我首先注意到的是规模上的差异,代码减少了,这更易于调试。此外,让Spring处理这么多的对象实例化和依赖关系跟踪,意味着在系统增长时不会遇到太多烦恼。通过IoC注入还能简化测试,通过更改XML文件可以转出DAO实现。

  从更高的角度来看,我仔细考虑了自己使用的特殊Spring组件。对象查找和JDBC模板看起来很熟悉。在大型项目中,通常拥有处理对象查找或数据库连接的框架代码。这自然会提高Spring的实用价值。以前我看到过这种情况,现在我们从一个项目移动到另一项目时不必再编写这些内容。作为额外的优势,Spring团队可以重点增强自己的产品,而我们则关注自己的产品。

  采用Spring的另一个优势是它不是要么完全成功要么完全失败的行为。可以在不影响其他层的情况下,对各个应用程序层应用Spring,因此在此过程中可以随时停止。例如,如果我只希望利用Spring的JDBC模板,可以只更改DAO,而不修改应用程序的其余部分。

  尽管我是Spring团体的后来者,但是我非常高兴能够成为其中的一员。

资源

  • “What is Spring”的第一部分第二部分(作者Gehtland和Tate),提供了对Spring Framework的简要介绍。
 
分享到:
评论

相关推荐

    从Spring迁移到Spring Boot的方法步骤

    从Spring迁移到Spring Boot的方法步骤主要包括添加Spring Boot Starters、添加应用程序入口、Import Configuration和Components、迁移应用程序资源、迁移应用程序属性文件、迁移Spring Web程序等步骤。通过这些步骤...

    Spring Boot Migrator (SBM)是一种用于自动代码迁移以升级或迁移到Spring Boot的工具

    Java SSM项目是一种使用Java语言和SSM框架(Spring + Spring MVC + MyBatis)开发的Web应用程序。SSM是一种常用的Java开发框架组合,它结合了Spring框架、Spring MVC框架和MyBatis框架的优点,能够快速构建可靠、...

    将应用程序迁移到Spring Cloud + CSE的工具集(高分毕设).zip

    Java SSM项目是一种使用Java语言和SSM框架(Spring + Spring MVC + MyBatis)开发的Web应用程序。SSM是一种常用的Java开发框架组合,它结合了Spring框架、Spring MVC框架和MyBatis框架的优点,能够快速构建可靠、...

    spring-migration-analyzer:Spring Migration Anaylzer 是一个用于分析 Java EE 应用程序的命令行工具。 它生成一份报告,描述应用程序以及如何将其迁移到 Spring

    它生成一份报告,描述应用程序以及如何将其迁移到 Spring。 下载 用法 要开始使用迁移分析器,请执行以下操作以获取使用信息: unzip spring-migration-analyzer-&lt;version&gt;-dist.zip cd spring-migration-...

    spring 4.3.14(全)最新的spring4正式版

    Spring 框架是 Java 开发中的一个核心组件,它为构建企业级应用程序提供了全面的编程和配置模型。Spring 4.3.14 是该框架...如果你的项目还在使用Java 7或者尚未准备迁移到Spring 5,那么这个版本会是一个可靠的选择。

    SpringBatch-DataMigration SpringBatch数据迁移项目

    1.本项目运行在tomcat容器中,主要功能为从spring_batch_left库的user_from表抓取数据,之后批量插入到spring_batch_right库的user_to表 2.应用quartz对job进行定时触发(目前设置的定时为每隔一分钟执行一次,目前...

    spring-boot-migration:迁移到Spring Boot 2和Webflux演示

    从Spring Boot 1.5迁移到2.0 演示项目,用于。 比较标记1.5.x , 2.0.x和2.0.x-webflux以查看更改。技术生产代码语言: 应用程序服务器(Servlet容器): 应用程序和Web框架: 代码生成:测试代码工装建立:代码格式...

    Spring Security 把授权信息写入数据库

    在从Acegi安全框架转换到Spring Security 2.0时,一个重要的变化就是如何将授权信息存储从XML配置文件迁移到数据库。这使得授权策略更加灵活,易于管理和维护。 24.1. Spring Security简介 Spring Security 2.0...

    Spring2.5.6 参考文档

    - **变更内容**:概述了从早期版本迁移到Spring 2.5所需注意的变更,包括支持的JDK版本、Jar打包方式、XML配置变化等。 - **已废弃的类和方法**:列举了一些不再推荐使用的类和方法,帮助开发者避免使用这些即将被...

    spring-roo-docs

    - 项目迁移:将现有项目迁移到SpringRoo。 - 项目扩展:在现有项目基础上使用SpringRoo添加新功能。 **5.2 现有数据库** SpringRoo也可以与现有的数据库系统配合使用,包括: - 数据库适配:SpringRoo支持多种...

    Spring 2系列参考文档

    文档详细介绍了从早期版本迁移到Spring 2.0所需注意的变更,帮助开发者顺利过渡。 ### 示例应用和文档更新 Spring 2系列提供了更新的示例应用程序和改进的文档,为开发者提供了更丰富的学习资源和实践指南。 总之...

    良葛格Spring学习笔记

    此外,Spring还采用了非侵入式设计,这意味着开发者可以很容易地集成Spring到现有的项目中,或者将现有项目迁移到Spring框架上,减少了迁移成本。 2. **容器**:Spring提供了一个容器功能,该容器负责管理对象的...

    spring-boot-reference.pdf

    对于那些从旧版Spring项目迁移到Spring Boot的开发者,这是一个重要的知识点。 #### 8. 自动配置 自动配置是Spring Boot的核心特性之一。文档将解释如何通过@EnableAutoConfiguration注解来启用Spring Boot的自动...

    spring-boot-reference 2.0.0.RELEASE

    此外,文档还介绍了如何逐渐替换自动配置,这是在现有项目中迁移到 Spring Boot 时特别重要的一个步骤。 文档中还涉及了 Spring Boot 的一些高级特性,比如自动配置的细节、如何使用 Spring Boot 的自动配置机制,...

    dwr与spring集成的方式

    2. **在Spring配置文件中添加DWR配置**:将原本在dwr.xml中的配置信息迁移到Spring的配置文件中。例如: ```xml &lt;bean id="dwrConfig" class="org.directwebremoting.spring.SpringConfigurator"&gt; &lt;value&gt;...

    Spring+jsp老项目转Springboot的示例Demo

    6. **迁移业务逻辑**:最后,逐步将原有的Service层和DAO层迁移到Spring Boot的环境中,利用Spring Boot的数据访问和事务管理等特性,如`@Service`、`@Repository`和`@Transactional`等注解。 通过这个示例Demo,...

    Spring Security 2 参考手册 中文版 (html格式)

    这部分内容可能帮助那些从Acegi迁移到Spring Security的开发者理解两者之间的关系和差异。 `ca.html`和`springsecurity.html`的详细内容没有明确的描述,但根据常规,它们可能涉及证书权威(CA)和Spring Security...

    从SpringMVC迁移到Springboot的方法步骤

    从SpringMVC迁移到Springboot的方法步骤 从SpringMVC迁移到Springboot是一种常见的迁移方式,本篇文章主要介绍了从SpringMVC迁移到Springboot的方法步骤。 Profile配置是Spring框架中的一种重要机制,用于管理多个...

    Nacos Spring Stack 讲义1

    在Nacos中,从Spring Web MVC迁移到Spring Boot的过程中,日志系统的处理方式发生了变化。Nacos支持多种日志框架,如SLF4J、Logback和Log4j 2.x。其中,Logback是默认的日志系统,Log4j 1.x将被逐步移除。配置文件...

Global site tag (gtag.js) - Google Analytics