Andrei Ermicioi's Blog

Just another WordPress.com weblog

Web proiect pe SpringFramework 3.0

Acest post va fi un refactoring la alt post de al meu postat pe fostul blog, pe care nu-l mai utilizez 🙂

Aici voi incerca sa arat cum utilizez eu SpringFramework-ul si MVC-ul sau.

Tehnologiile utilizate in proiect sunt:

  • Spring framework 3.0
  • Hibernate
  • Tiles2
  • Maven

Tiles2 – este un framework ce tine de partea de layouting.

Maven – raspunde de satisfacerea dependetilor de librarii.

Structura proiectului

Structura proiectului este in conformitatea cu strucutra Maven a unui web proiect. Diferenta cu structura standart, generata de Eclipse, este ca fisierile web pleaca in src/main/webapp, iar codul sursa in src/main/java si resursele in src/main/resources.

Atit SpringFramework cit si Tiles2 au nevoie de fisiere de configurare. Cu acest scop in WEB-INF este create folderul config/ care are alte doua foldere:

  • WEB-INF/config/spring/
  • WEB-INF/config/tiles/

In scopuri de securitate in webapp/ nu se va afla nici un fisier .jsp, cu exceptia a unui singur pe care l-am numit redirect.jsp si a carui functie este de a rederectiona la MVC controlerul default. Fisierele view, .jsp, le-am structurat conform urmatoarei structuri:

  • WEB-INF/view/layout/
  • WEB-INF/view/jsp/

Astfel in folderul layout/ pleaca fisierele ce raspund de layout, iar in jsp/ fisierele ce raspund de continut.

Configurarea proiectului, web.xml

Configurarea SpringFramework-ului se poate face cu ajutorul fisierilor .xml si cu ajutorul annotarilor plasate direct in cod. Eu am ales sa utilizez ambele posibilitati, utilizind .xml fisiere unde imi era mai comod s-o fac cu ajutorul xml si annotari unde am considerat ca e mai bine annotari.

In web.xml specificam fisierul de configurare .xml pentru SpringFramework si un listener

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/spring/webapp.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Se mai adauga si un filtru pentru a codifica toate request-urile in UTF-8

<filter>
<filter-name>encoding-filter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Defenim servletul care va face dispatching-ul

<servlet>
<servlet-name>numerology</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>numerology</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>

mai ramine si definirea a fisierului default cind se acceseaza pe domen

<display-name>Numerology-web</display-name>
<welcome-file-list>
<welcome-file>redirect.jsp</welcome-file>
</welcome-file-list>

Configurarea SpringFramework, webapp.xml

Pentru a avea o configurarea cit mai clara am impartit configurarea a spring-ului in alte trei fisiere xml.

  • WEB-INF/config/spring/dao.xml
  • WEB-INF/config/spring/service.xml
  • WEB-INF/config/spring/mvc.xml

Pentru a include aceste trei fisiere in calitate de configurare in webapp.xml avem urmatorul cod

<?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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"><
<!-- Imports the configurations of the different infrastructure systems of the application -->
<import resource="dao.xml" />
<import resource="service.xml" />
<import resource="mvc.xml" />
</beans>

In dao.xml configuram toate bean-urile ce tin de lucru cu baza de date

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://192.168.3.7:5432/numerology2" />
<property name="username" value="postgres" />
<property name="password" value="free" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>hbms/MyDBObject.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
<prop key="show_sql">true</prop>
<prop key="format_sql">true</prop>
</props>
</property>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>

Fisierul services.xml contine definitia bean-urilor care au rol de servicii, aceste bean-uri mai pot fi definite si cu ajutorul annotarilor

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean
id="sendMailService"
class="com.creafire.numerology.core.util.SendMailService" />
</beans>

Toate configurarile ce tin de MVC sunt definite in mvc.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config />
<context:component-scan base-package="com.creafire.numerology" />
<!-- Enables POJO @Controllers (like CartController) -->
<bean
class= "org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<ref bean="advertiseInterceptor"/>
</list>
</property>
</bean>
<!-- Enables annotated methods on POJO @Controllers (like CartController) -->
<bean class=
"org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
<bean id="viewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView" />
</bean>
<bean id="tilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/config/tiles/layouts.xml</value>
<value>/WEB-INF/config/tiles/parts.xml</value>
<value>/WEB-INF/config/tiles/pages.xml</value>
</list>
</property>
</bean>
<bean id="localeResolver"
class="com.creafire.numerology.web.system.LocaleResolver"/>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
<!-- i18n Support -->
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:dictionary" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
</beans>

Mare treaba in configurarea a Tiles nu este, e totul asa cum e descris pe site-ul Tiles, iar dupa cum se vede din listingul anterior, configurarile Tiles sunt incluse in fisierul mvc.xml.

Controller

SpringFramework permite definirea unui controller per URL sau un singur controller sa prelucreze mai multe URL-uri. Un controller este o classa Java.

Codul ce ar defini un singur controller per URL ar fi

@Controller
@RequestMapping("/account/login")
public class AccountController {
}

Un Controller ce ar prelucra mai multe URL-uri ar fi

@Controller
public class AccountController {
@RequestMapping("/account/login")
public void loginAction() {
}
@RequestMapping("/account/logout")
public void logoutAction() {
}
}

La annotarea @RequestMapping putem adauga si un modificator. Modificatorul arata ce tip de request este, POST, GET, DELETE, etc

@Controller
@RequestMapping(value="/account/login", method=RequestMethod.GET)
public class AccountController {
}

Deoarece eu utilizez pe partea de view Tiles, aproape toate metodele returneaza un string, care este numele la view-ul ce trebuie prezentat. Totodata toate controllere extind o clasa AbstractController care codul de care se utilizeaza toate controllere.

@Controller
public class AccountController extends AbstractController {

@Autowired
private CertificateDao certificateDao;

@Resource(name="feedbackDao")
private FeedbackDao feedbackDao;

@RequestMapping(value="/account/login", method=RequestMethod.GET)
public String loginGetAction() {
return "account.login";
}

@RequestMapping(value="/account/login", method=RequestMethod.POST)
public String loginPostAction() {
return "redirect:/account.html";
}

Asa deci, au aparut element noi, sa le clarific.

@Resource(name="feedbackDao")
private FeedbackDao feedbackDao;

Ii zicem spring-ului ca acestui attribut sa-i injicteze un obiect definit cu un astfel de nume din fisierul de configurare.

@Autowired
private CertificateDao certificateDao;

Spirng-ul va injecta un bean definit cu annotare.

return "redirect:/account.html";

Aceasta zice ca trebuie de facut redirect, iar daca dorim un forward atunci in loc de cuvintul redirect scriem forward.

Parametrii din URL, Request/Response obiect, pasarea parametrilor catre view

SpringFramework ofera o modalitate foarte comoda de a obtine parametrii din URL si automata convertire la tipul de care avem nevoie. Urmatoare metoda va clarifica totul

@RequestMapping(value="/account/login", method=RequestMethod.POST)
public String loginPostAction(@RequestParam("username") String username, @RequestParam("password") String password, HttpServletRequest request, ModelMap model) {
// some code
}

Aceasta metoda primeste patru parametri.

@RequestParam("username") String username

Astfel noi zicem ca in variabila cu numele username sa se injecteze parametru username din URL. In caz ca acest parametru va lipsi, SpringFramework va arunca exceptie. In caz ca parametru nu este obligatoriul, codul va avea forma

@RequestParam(value="username", required=false) String username

Al trei-lea parametru este obiectul HttpServletRequest, SpringFramework il injecteaza automat, fara a folosi careva annotare.
ModelMap este un obiect care va transmite catre view valorile prelucrate in controller si de care vor fi nevoie in view. In view (.jsp)  aceste valori vor fi accesibile prin EL Expresii.

Valori in view se mai poat transmite cu ajutorul unei metode din controller, care va avea annotare @ModelAttribute, urmatorul cod ilustreaza aceasta

@ModelAttribute("activeMenuItem")
public MenuElement activeMenuItem(HttpServletRequest request) {
//code
}

Defenirea bean-urilor ca servicii

Pentru a defeni o clasa ca serviciu ce va fi automat injectat datorita la annotarea @Autowired, clasa e nevoie de annotat cu annotarea @Repository(“”), in rezultat toate obiectele DAO in proiect sunt annotate cu aceasta annotare, in rezultat este prezent un astfel de cod

@Repository("certificateDao")
public class CertificateDao extends AbstractDao {
}

Toate clasele DAO in proiect mostenesc AbstractDao pentru a avea acces la metode necesare tuturor obiectelor DAO.

Configurator

SpringFramework mai ofera o metoda de defenire a bean-urilor si acesta este configuratorul. Configuratorul este o clasa care este annotata cu @Configuration, exemplu urmeaza

@Configuration
public class ApplicationConfigurer {
@Autowired
HibernateTemplate hibernateTemplate;
@Bean
public CertificateDao certificateDao() {
CertificateDao dao = new CertificateDao();
dao.setHibernateTemplate(hibernateTemplate);
return dao;
}
@Bean
public SendMailService mailService() {
return new SendMailService();
}
}

Dupa cit se poate de observat aici in configurator este definit acel serviciu care e definit si in service.xml. Codul precedent este luat din alt proiect pentru a prezenta configurator-ul, de aia el nu face conflict cu ceea ce e defenit in service.xml.

The end

Aceasta in linii genirale a fost descris modalitatile cum eu creez web proiecte pe baza la SpringFramework + Hibernate + Tiles2. Sunt sigur ca nu fac totul corect, dar cu timpul mecanismul se va cizila, daca sunt intrebari sau replici de ce asa sau idei cum ar fi mai bine, plz dati un mail pe erani.mail@gmail.com.

Sper sa urmeze ceva posturi in care voi vorbi mai detaliat despre cele prezentate mai sus.

Advertisements

Written by eraniblog

April 26, 2010 at 17:30

Posted in Coding

%d bloggers like this: