web-dev-qa-db-fra.com

Un exemple de projet open source Spring plus grand que PetClinic?

J'ai fini de lire le doc du printemps et l'exemple de projet PetClinic. Tout comme pour voir un plus grand projet du monde réel réalisé avec Spring. Merci.

53
Tong Wang
106
Harsha Hulageri

Je travaille pour une grande compagnie d'assurance maladie où nous utilisons beaucoup Spring en backend. Je vais vous montrer comment est construite une application modulaire .

Squelette WEB-INF sans répertoire de classes

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

Squelette classes répertoire

        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
            ...

Remarquez comment chaque package sous br.com.ar.web correspond WEB-INF/view répertoire. C'est la clé nécessaire pour exécuter la convention sur la configuration dans Spring MVC. Comment ??? compter sur ControllerClassNameHandlerMapping

WEB-INF/ar-servlet.xml Remarquez la propriété basePackage, ce qui signifie rechercher n'importe quelle classe @ Controller sous br.com.ar.view package. Cette propriété vous permet de construire un contrôleur @ modulaire modulaire

<!--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>

Voyons maintenant, par exemple, 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);
    }

}

Comment ça marche ???

Supposons que vous fassiez une demande pour http://127.0.0.1:8080/ar/ moduleA/compte/formulaire .html

Spring supprimera le chemin entre le chemin de contexte et l'extension de fichier - mis en évidence ci-dessus. Lisons le chemin extrait de droite à gauche

  • form nom de la méthode
  • compte nom de classe non qualifié sans suffixe du contrôleur
  • moduleA package auquel sera ajouté à basePackage propriété

qui est traduit en

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

D'accord. Mais comment Spring sait-il quelle vue afficher ??? Voir ici

Et sur la persistance les problèmes liés ???

Tout d'abord, voyez ici comment nous implémentons le référentiel. Notez que chaque requête de module associée est stockée dans son package de référentiel associé . Voir squelette ci-dessus. Voici la propriété ar-persistence.xml Notice mappingLocations et packagesToScan

<?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>

Notez que j'utilise Hibernate. JPA doit être correctement configuré.

Gestion des transactions et analyse des composants ar-service.xml Remarque Deux points après br.com.ar dans aop: attribut d'expression de pointcut qui signifie

Tout package et sous-package sous package 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>

Test

Pour tester la méthode @Controller annotée, voir ici comment

Autre que la couche Web. Remarquez comment je configure une source de données JNDI dans la méthode @Before

@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);
    }

}

Si vous avez besoin d'une suite de tests, procédez comme suit

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

web.xml est présenté comme suit

<?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>

J'espère que cela peut être utile. Mettre à jour le schéma vers Spring 3.0. Voir la documentation de référence Spring. schéma mvc, Pour autant que je sache, est pris en charge uniquement dans Spring 3.0. Garde ça en tête

18
Arthur Ronald

Quelques candidats:

  • PetStore du printemps

  • AppFuse - Dans AppFuse, le framework Spring est utilisé partout pour sa prise en charge Hibernate/iBATIS, les transactions déclaratives, la liaison de dépendance et le découplage de couche.

  • Equinox (a.k.a. AppFuse Light) - une application CRUD simple créée dans le cadre de Spring Live.

  • Spring by Example - Divers exemples Spring plus quelques bibliothèques téléchargeables.

  • Tudu Lists - Tudu Lists est une application J2EE pour gérer les listes de tâches. Il est basé sur JDK 5.0, Spring, Hibernate et une interface AJAX (en utilisant le framework DWR).

  • magasin de printemps

7
Pascal Thivent

Regardez Apache CXF . Il utilise le printemps.

3
bmargulies