Тема 10 XP eXtreme Programming 1. 2. 3. 4. 5. 6. 7. Контроллеры (SimpleFormController, UrlFilenameViewController); Модель и представление соединяются посредством класса org.springframework.web.servlet.ModelAndView Для поддержки работы с формой используется командный объект (JavaBean, который заполняется значениями из полей формы) Представления реализуются с помощью JSP страниц. Для упрощения сценариев существуют специальные теги из библиотеки дескрипторов Spring. Используются объекты, раскрывающие интерфейс Validator (для проверки правильности ввода данных в форму) Перехватчики – классы, которым передается управление перед (после) тем, как будет выполнен контроллер Преобразователи представления – класс InternalResourceViewResolver. Осуществляет преобразование имен представлений (файл с расширением htm) в фактическое представление (файл с расширением jsp) XP Перенаправление на контроллеры осуществляет класс org.springframework.web.servlet.DispatcherServlet Управление на него передается с помощью настройки в файле web.xml приложения. XP В корневой папке приложения – index.jsp В папке WEB-INF содержатся файлы настройки приложения web.xml и timex-servlet.xml Файлы настройки Hibernate находятся в папке classes XP <target name="copy_files"> <copy todir="${webinf.dir}/${src.dir}"> <fileset dir="${src.dir}"> <include name="**/*.java" /> </fileset> </copy> <copy todir="${webinf.dir}/${data.dir}"> <fileset dir="${data.dir}"> <include name="**/*" /> </fileset> </copy> </target> XP <target name="copy_files"> <copy todir="${webinf.dir}/${src.dir}"> <fileset dir="${src.dir}"> <include name="**/*.java" /> </fileset> </copy> <copy todir="${webinf.dir}/${data.dir}"> <fileset dir="${data.dir}"> <include name="**/*" /> </fileset> </copy> <copy todir="${war.dir}"> <fileset dir="${web.dir}"> <include name="**/*" /> </fileset> </copy> <copy todir="${jsp.dir}"> <fileset dir="${views.dir}" /> </copy> </target> XP <target name="dist" depends="rebuild”> <mkdir dir="${dist.dir}" /> <war destfile="${war.file}" webxml="${src.dir}/conf/web.xml"> <fileset dir="${war.dir}"> <include name="**/*.*" /> <exclude name="**/web.xml" /> <exclude name="**/test/*.class" /> <exclude name="**/*mock*.jar" /> </fileset> </war> <delete dir="${webinf.dir}/${src.dir}" failonerror="false" /> </target> XP <?xml version="1.0" encoding="ISO-8859-1"?> <web-app 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" version="2.4"> <display-name>Time Expression</display-name> <description> Example </description> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> XP <servlet> <servlet-name>timex</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>timex</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping> </web-app> XP Файл контекста приложения задает JavaBean’ы, используемые в приложении и их отношения внедрения. Разберем сначала функциональность авторизации пользователя. XP <?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.xsd"> <!– Настройка URL с расширением htm на контроллер --> <bean id="urlMap" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="urlMap"> <props> <prop key="/signin.htm">signInController</prop> <prop key="/signout.htm">signOutController</prop> <prop key="/ok.htm">urlFilenameController</prop> </props> </property> </bean> XP <!-- Bean для перехватчика запросов --> <bean id="httpRequestInterceptor" class="com.visualpatterns.timex.controller.HttpReques tInterceptor"> <property name="signInPage"> <value>signin.htm</value> </property> <property name="applicationSecurityManager"> <ref bean="applicationSecurityManager" /> </property> </bean> XP <!-- Bean для контроллера формы ввода логина и пароля --> <bean name="signInController“ class="com.visualpatterns.timex.controller.SignInController"> <property name="sessionForm"> <value>true</value> </property> <property name="formView“> <value>/signin</value> </property> <property name="successView"> <value>redirect:ok.htm</value> </property> <property name="commandClass"> <value>com.visualpatterns.timex.controller.SignLogin</value> </property> <property name="validator"> <ref bean="signinValidator" /> </property> <property name="applicationSecurityManager"> <ref bean="applicationSecurityManager" /> </property> </bean> XP <!-- Bean для контроллера выхода из системы --> <bean name="signOutController" class="com.visualpatterns.timex.controller.SignOutCon troller"> <property name="applicationSecurityManager"> <ref bean="applicationSecurityManager" /> </property> <property name="successView"> <value>redirect:signin.htm</value> </property> </bean> XP <!-- Bean для валидатора формы ввода пароля --> <bean id="signinValidator“ class="com.visualpatterns.timex.controller.SignInValidator" /> <!-- Bean для управления параметрами сессии --> <bean id="applicationSecurityManager" class="com.visualpatterns.timex.controller.ApplicationSecuri tyManager"/> <!-- Bean для перенаправления без контроллера --> <bean id="urlFilenameController" class="org.springframework.web.servlet.mvc.UrlFilenameViewCo ntroller" /> XP <!-- Bean для определения фактических имен представлений --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResour ceViewResolver"> <property name="viewClass"> <value>org.springframework.web.servlet.view.JstlView</ value> </property> <property name="prefix"> <value>/WEB-INF/jsp/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> XP <!-- Bean для формирования сообщений системы --> <bean id="messageSource" class="org.springframework.context.support.Resourc eBundleMessageSource"> <property name="basenames"> <list> <value>messages</value> </list> </property> </bean> Файл messages.properties должен содержать строки: Id сообщения = текст сообщения XP <!-- Bean для назначения перехватчиков --> <bean id="urlMapAuthenticate" class="org.springframework.web.servlet.handler.SimpleUrlHandle rMapping"> <property name="interceptors"> <list> <ref bean="httpRequestInterceptor" /> </list> </property> <property name="urlMap"> <props> ... </props> </property> </bean> XP package com.visualpatterns.timex.controller; public class SignLogin { String login, password; public String getLogin() {return login;} public void setLogin(String login){this.login=login;} public String getPassword(){return password;} public void setPassword(String pass){ password=pass;} } XP package com.visualpatterns.timex.controller; import javax.servlet.http.HttpServletRequest; public class ApplicationSecurityManager { public static final String USER = "user"; public Object getUser(HttpServletRequest request) { return request.getSession(true).getAttribute(USER); } public void setUser(HttpServletRequest request, Object user) { request.getSession(true).setAttribute(USER, user);} public void removeUser(HttpServletRequest request) { request.getSession(true).removeAttribute(USER);} } XP package com.visualpatterns.timex.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import com.visualpatterns.timex.controller.SignLogin; import com.visualpatterns.timex.controller.ApplicationSecurityManager; public class HttpRequestInterceptor extends HandlerInterceptorAdapter { private String signInPage; private ApplicationSecurityManager applicationSecurityManager; public String getSignInPage() { return signInPage;} public void setSignInPage(String signInPage) { this.signInPage = signInPage;} public ApplicationSecurityManager getApplicationSecurityManager() { return applicationSecurityManager;} public void setApplicationSecurityManager( ApplicationSecurityManager applicationSecurityManager) { this.applicationSecurityManager = applicationSecurityManager;} XP public void setApplicationSecurityManager( ApplicationSecurityManager applicationSecurityManager) { this.applicationSecurityManager = applicationSecurityManager;} public boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String log = (String)applicationSecurityManager.getUser(request); if (log == null) { response.sendRedirect(this.signInPage); return false; } return true; } } XP 1. Обращение к форме: - formBackingObject – создание командного объекта - initBinder – регистрация редакторов свойств - showForm - referenceData – формирование списков 2. Данные в форме некорректные: - initBinder - onBind - onBindAndValidate - processFormSubmission - showForm - referenceData 3. Данные были корректными: - initBinder - onBind - onBindAndValidate - processFormSubmission - onSubmit XP package com.visualpatterns.timex.controller; import org.springframework.validation.Errors; import com.visualpatterns.timex.controller.SignLogin; public class SignInValidator implements org.springframework.validation.Validator { public boolean supports(Class clazz) { return clazz.equals(SignLogin.class); } public void validate(Object command, Errors errors) { SignLogin log = (SignLogin) command; if (log == null) return; String login = log.getLogin(); String password = log.getPassword(); if (!(login.equals("admin") && password.equals("admin"))) errors.reject("error.login.invalid"); } } XP package com.visualpatterns.timex.controller; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.validation.BindException; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.SimpleFormController; import com.visualpatterns.timex.controller.ApplicationSecurityManager; import com.visualpatterns.timex.controller.SignLogin; public class SignInController extends SimpleFormController { private ApplicationSecurityManager applicationSecurityManager; protected Object formBackingObject(HttpServletRequest request) throws Exception { return new SignLogin(); } XP public ModelAndView showForm( HttpServletRequest request, HttpServletResponse response, BindException errors, Map controlModel) throws Exception { if (applicationSecurityManager.getUser(request) != null) return new ModelAndView(getSuccessView()); return super.showForm(request, response, errors, controlModel); } public void onBindAndValidate( HttpServletRequest request, Object command, BindException errors) throws Exception { if (errors.hasErrors()) return; SignLogin formUser = (SignLogin) command; applicationSecurityManager.setUser(request, formUser.getLogin()); } XP public ModelAndView onSubmit( HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception { return new ModelAndView(getSuccessView());} public ApplicationSecurityManager getApplicationSecurityManager() { return applicationSecurityManager; } public void setApplicationSecurityManager( ApplicationSecurityManager applicationSecurityManager) { this.applicationSecurityManager = applicationSecurityManager; } } XP package com.visualpatterns.timex.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import com.visualpatterns.timex.controller.ApplicationSecurityManager; public class SignOutController implements Controller { private ApplicationSecurityManager applicationSecurityManager; private String successView; public String getSuccessView() { return successView; } public void setSuccessView(String successView) { this.successView = successView; } XP public ModelAndView handleRequest( HttpServletRequest request, HttpServletResponse response) throws Exception { applicationSecurityManager.removeUser(request); return new ModelAndView(getSuccessView()); } public ApplicationSecurityManager getApplicationSecurityManager() { return applicationSecurityManager;} public void setApplicationSecurityManager( ApplicationSecurityManager applicationSecurityManager) { this.applicationSecurityManager = applicationSecurityManager; } } XP Цель – перенаправление на страницу авторизации <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <c:redirect url="signin.htm"/> XP <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> <%@ page contentType="text/html; charset=windows-1251" %> <html><body><h1>Авторизация</h1> <form method="post"> <br/> <spring:bind path="command.*"> <c:if test="${not empty status.errorMessages}"> <c:forEach var="error" items="${status.errorMessages}"> <font color="red"><c:out value="${error}" escapeXml="false" /></font> <br /> </c:forEach> </c:if> </spring:bind> <c:if test="${not empty message}"> <font color="green"><c:out value="${message}" /></font> <c:set var="message" value="" scope="session" /> </c:if> XP <br/> Логин: <spring:bind path="command.login"> <input name='<c:out value="${status.expression}"/>' value='<c:out value="${status.value}"/>' type="text" size="6" maxlength="6"> </spring:bind> <br/> Пароль: <spring:bind path="command.password"> <input name='<c:out value="${status.expression}"/>' value='<c:out value="${status.value}"/>' type="password" size="8" maxlength="10"> </spring:bind> <br/> <input type="submit" name="Submit" value="Войти"> </form> </body> </html> XP <%@ page contentType="text/html; charset=windows-1251" %> <html> <body> <h1>Вы успешно вошли в систему</h1> <a href="signout.htm">Выйти из системы</a> </body> </html> XP