有没有比PetClinic更大的开源Spring示例项目?

56

我已经读完了Spring文档和PetClinic示例项目。只是想看一些使用Spring完成的更大型的真实项目。谢谢。

4个回答

111

我给你一个赞(+1),因为你做了一次非常好的关于基于Spring的项目的谷歌搜索。 - Arthur Ronald
4
这份编制的清单是我维护作为参考的笔记的复制粘贴。 - Harsha Hulageri

19

我在一家大型医疗保险公司工作,我们在后端广泛使用Spring。我将向您展示如何构建一个模块化的应用程序。

骨架WEB-INF没有类目录。

ar
    WEB-INF
        web.xml
        /**
          * Spring related settings file
          */
        ar-servlet.xml
        web
            moduleA
                account
                    form.jsp
            moduleB
                order
                    form.jsp

骨架 目录

        classes
            /**
              * Spring related settings file
              */
            ar-persistence.xml
            ar-security.xml
            ar-service.xml
            messages.properties
            br
                com
                    ar
                        web
                            moduleA
                                AccountController.class        
                            moduleB
                                OrderController.class
            br
                com
                    ar
                        moduleA
                            model
                                domain
                                    Account.class
                                repository
                                    moduleA.hbm.xml
                                service
            br
                com
                    ar
                        moduleB
                            model
                                domain
                                    Order.class
                                repository
                                    moduleB.hbm.xml
                                service
            ...

注意看下br.com.ar.web下的每个包都与WEB-INF/view目录相对应。这是在Spring MVC中运行约定优于配置所需的关键。如何依赖于ControllerClassNameHandlerMapping

WEB-INF/ar-servlet.xml注意basePackage属性,它意味着查找br.com.ar.view包下的任何@Controller类。该属性允许您构建模块化的@Controller。

<!--Scans the classpath for annotated components at br.com.ar.web package-->
<context:component-scan base-package="br.com.ar.web"/>
<!--registers the HandlerMapping and HandlerAdapter required to dispatch requests to your @Controllers-->
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
    <property name="basePackage" value="br.com.ar.web"/>
    <property name="caseSensitive" value="true"/>
    <property name="defaultHandler">
        <bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
    </property>
</bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/view/"/>
    <property name="suffix" value=".jsp"/>
</bean>

现在让我们来看一下,例如AccountController。

package br.com.ar.web;

@Controller
public class AccountController {

    @Qualifier("categoryRepository")
    private @Autowired Repository<Category, Category, Integer> categoryRepository;

    @Qualifier("accountRepository")
    private @Autowired Repository<Account, Accout, Integer> accountRepository;

    /**
     * mapped To /account/form
     */
    @RequestMapping(method=RequesMethod.GET)
    public void form(Model model) {
        model.add(categoryRepository().getCategoryList());
    }

    /**
     * mapped To account/form
     */
    @RequestMapping(method=RequesMethod.POST)
    public void form(Account account, Errors errors) {
        accountRepository.add(account);
    }

}

它是如何工作的?

假设您发出一个请求,URL为 http://127.0.0.1:8080/ar/moduleA/account/form.html

Spring将删除上述路径中上下文路径和文件扩展名之间的部分。让我们从右到左读取提取的路径。

  • form 方法名
  • account 未经控制器后缀修饰的类名
  • moduleA 包名,将被添加到basePackage属性中。

这将翻译为:

br.com.ar.web.moduleA.AccountController.form

好的。但是Spring如何知道要显示哪个视图?请参见 这里

至于与持久化相关的问题?

首先,请看一下我们如何实现仓库的 这里。请注意,每个相关模块的查询都存储在其相关的仓库包中。请参见上面的骨架。在这里显示了ar-persistence.xml。请注意和属性。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
                       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                       http://www.springframework.org/schema/util 
                       http://www.springframework.org/schema/util/spring-util-2.5.xsd  
                       http://www.springframework.org/schema/jee 
                       http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">
    <jee:jndi-lookup id="dataSource" jndi-name="jdbc/dataSource" resource-ref="true">
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mappingLocations">
            <util:list>
                <value>classpath:br/com/ar/model/repository/hql.moduleA.hbm.xml</value>
                <value>classpath:br/com/ar/model/repository/hql.moduleB.hbm.xml</value>
            </util:list>
        </property>
        <property name="packagesToScan">
            <util:list>
                <value>br.com.ar.moduleA.model.domain</value>
                <value>br.com.ar.moduleB.model.domain</value>
            </util:list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
                <prop key="hibernate.connection.charSet">UTF-8</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.validator.autoregister_listeners">false</prop>
            </props>
        </property>
    </bean>
</beans>

请注意我正在使用Hibernate。JPA 应该被正确配置。

事务管理和组件扫描 ar-service.xml 注意在 aop:pointcut 的 expression 属性后面有两个点,这意味着:

br.com.ar 包及其子包下的任何包

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
                       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                       http://www.springframework.org/schema/tx    
                       http://www.springframework.org/schema/tx/spring-tx-2.5.xsd 
                       http://www.springframework.org/schema/context
                       http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <context:component-scan base-package="br.com.ar.model">
    <!--Transaction manager - It takes care of calling begin and commit in the underlying resource - here a Hibernate Transaction -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    <tx:advice id="repositoryTransactionManagementAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="add" propagation="REQUIRED"/>
            <tx:method name="remove" propagation="REQUIRED"/>
            <tx:method name="update" propagation="REQUIRED"/>
            <tx:method name="find*" propagation="SUPPORTS"/>
        </tx:attributes>
    </tx:advice>
    <tx:advice id="serviceTransactionManagementAdvice" transaction-manager="transactionManager">
        <!--Any method - * - in service layer should have an active Transaction - REQUIRED - -->
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut id="servicePointcut" expression="execution(* br.com.ar..service.*Service.*(..))"/>
        <aop:pointcut id="repositoryPointcut" expression="execution(* br.com.ar..repository.*Repository.*(..))"/>
        <aop:advisor advice-ref="serviceTransactionManagementAdvice" pointcut-ref="servicePointcut"/>
        <aop:advisor advice-ref="repositoryTransactionManagementAdvice" pointcut-ref="repositoryPointcut"/>
    </aop:config>
    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
</beans>

测试

要测试带注释的 @Controller 方法,请参阅这里如何操作

除了 Web 层之外。请注意我如何在 @Before 方法中配置 JNDI 数据源。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:ar-service.xml", "classpath:ar-persistence.xml"})
public class AccountRepositoryIntegrationTest {

    @Autowired
    @Qualifier("accountRepository")
    private Repository<Account, Account, Integer> repository;

    private Integer id;

    @Before
    public void setUp() {
         SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
         DataSource ds = new SimpleDriverDataSource(new oracle.jdbc.driver.OracleDriver(), "jdbc:oracle:thin:@127.0.0.1:1521:ar", "#$%#", "#$%#");

         builder.bind("/jdbc/dataSource", ds);
         builder.activate();

         /**
           * Save an Account and set up id field
           */
    }

    @Test
    public void assertSavedAccount() {
        Account account = repository.findById(id);

        assertNotNull(account);
    }

}

如果您需要一套测试,请按照以下步骤进行

@RunWith(Suite.class)
@Suite.SuiteClasses(value={AccountRepositoryIntegrationTest.class})
public void ModuleASuiteTest {}

以下是web.xml文件的示例

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:ar-persistence.xml
            classpath:ar-service.xml
        </param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>ar</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>ar</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
    <resource-ref>
        <description>datasource</description>
        <res-ref-name>jdbc/dataSource</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
</web-app>

我希望这会有所帮助。将模式更新为Spring 3.0版本,请参阅Spring参考文档。据我所知,mvc模式仅支持Spring 3.0版本以上。请记住这一点。


这正是我一直在寻找的。讲解得非常好,特别是约定优于配置部分。 - coolscitist

7

以下是一些候选项:

  • AppFuse - 在AppFuse中,Spring框架被广泛应用于Hibernate/iBATIS支持、声明式事务、依赖绑定和层解耦等方面。

  • Equinox(也称为AppFuse Light)- 这是一个简单的CRUD应用程序,作为Spring Live的一部分创建。

  • Spring by Example - 各种Spring示例以及一些可下载的库。

  • Tudu Lists - Tudu Lists是一个J2EE应用程序,用于管理待办事项列表。它基于JDK 5.0、Spring、Hibernate和一个AJAX界面(使用DWR框架)。


3

1
感谢您的迅速回复。我会看一下它。但是,我认为它更像是建立在Spring之上的框架,我真正想看到的是一些建立在Spring之上的多层Web应用程序。 - Tong Wang
我无法帮助你处理Web应用程序。CXF有很多Spring应用程序上下文配置的示例。 - bmargulies

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接