Web application development. Part 4

В предыдущей части я разработал серверную часть вэб-приложения с помощью Java. В этой части, я «подружу» клиентскую и серверную часть вэб-приложения с помощью Spring Framework.

Создадим spring контекст my-context.xml c:
• настройками подключения к БД;
• бином EntityManager — объект, через который происходит взаимодействие с БД. Инжектится в CarDaoImpl.java;
• инжектом объекта класса CarDaoImpl.java в объект класса CarServiceImpl.java;



my-context.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:jdbc="http://www.springframework.org/schema/jdbc"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"

       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                           http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
                           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
          p:dataSource-ref="dataSource"
          p:packagesToScan="model"
          p:jpaProperties-ref="jpaProperties"
          p:persistenceProvider-ref="persistenceProvider"/>

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"
          depends-on="entityManagerFactory"/>

    <bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close"
          p:driverClass="com.mysql.jdbc.Driver"
          p:jdbcUrl="jdbc:mysql://localhost:3306/CarCatalog?characterEncoding=UTF-8"
          p:username="root"
          p:password="1234"
          p:idleConnectionTestPeriodInMinutes="1"
          p:idleMaxAgeInSeconds="240"
          p:minConnectionsPerPartition="2"
          p:maxConnectionsPerPartition="5"
          p:partitionCount="2"
          p:acquireIncrement="1"
          p:statementsCacheSize="100"
          p:releaseHelperThreads="2"
          p:statisticsEnabled="false"/>

    <bean id="persistenceProvider" class="org.hibernate.ejb.HibernatePersistence"/>

    <bean id="jpaProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="properties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="connection.pool_size">1</prop>
                <prop key="current_session_context_class">thread</prop>
                <prop key="show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">create</prop>
                <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
            </props>
        </property>
    </bean>
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
          p:entityManagerFactory-ref="entityManagerFactory"/>

    <tx:annotation-driven transaction-manager="transactionManager"/>

    <bean name="carDao" class="model.dao.impl.CarDaoImpl">
    </bean>

    <bean name="CarService" class="service.impl.CarServiceImpl">
        <property name="carDao" ref="carDao">
        </property>
    </bean>

</beans>

Создайте БД с названием CarCatalog и кодировкой utf_general_ci или измените название в контексте my-context.xml на своё. Также измените p:username и p:password, если не совпадает.

Создадим настройки для spring DispatcherServlet, который будет обрабатывать запросы с клиента:


mvc-dispatcher-servlet.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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="controllers"/>
    <mvc:view-controller path="/" view-name="/index.jsp"/>
    <mvc:resources mapping="/**" location="/"/>
    <mvc:annotation-driven/>

    </beans>
context:component-scan поиск и регистрация компонентов в контейнере спринга;
mvc:view-controller домашняя страница;
mvc:resources автоматически обрабатывать запросы на получение статических данных;

Добавим spring контекст my-context.xml и настройки для spring DispatcherServlet в дескриптор развертывания 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">

    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>CharacterEncodingFilter</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>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:/my-context.xml
        </param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

</web-app>

Добавим в контролер CarCatalogController.js параметр refs и обработчики для компонентов:
    Ext.define('CarCatalog.controller.CarCatalogController', {
    extend: 'Ext.app.Controller',

    refs: [
        {selector: 'carGridView',
            ref: 'carGridView'},
        {selector: 'carGridView button[action="add"]',
            ref: 'carGridAdd'},
        {selector: 'carGridView button[action="delete"]',
            ref: 'carGridDelete'},
        {selector: 'searchCarView button[action="search"]',
            ref: 'searchCar'},
        {selector: 'addCarFormView',
            ref: 'addCarFormView'},
        {selector: 'carCatalogView',
            ref: 'carCatalogView'},
        {selector: 'addCarFormView textfield[name=name] ',
            ref: 'addCarFormName'},
        {selector: 'addCarFormView textfield[name=price]',
            ref: 'addCarFormPrice'},
        {selector: 'addCarFormView button[action=save]',
            ref: 'addCarFormSave'}
    ],

    init: function () {
        this.control({
            'carGridView  button[action=add]': {
                click: this.onAddCar
            },
            'carGridView  button[action=delete]': {
                click: this.onDelCar
            },
            'searchCarView  textfield[name="search"]': {
                change: this.onChangeText
            },
            'carGridView': {
                cellclick: this.onLineGrid
            },
            'addCarFormView  button[action=save]': {
                click: this.onSaveCar
            },
            'addCarFormView  textfield[name=name]': {
                change: this.onValidation
            },
            'addCarFormView  textfield[name=price]': {
                change: this.onValidation
            }
        });
    },

    onSaveCar: function (button) {
        var me = this;
        var carModel = Ext.create('CarCatalog.model.CarCatalogModel');
        carModel.set(this.getAddCarFormView().down('form').getValues());
        carModel.save({
            success: function (operation, response) {
                var objAjax = operation.data;
                Ext.getStore('CarCatalogStore').add(objAjax);
                me.getAddCarFormView().close();
            },
            failure: function (dummy, result) {
                Ext.MessageBox.show({
                    title: 'Дубликат!',
                    msg: 'Такая модель и цена уже существуют',
                    buttons: Ext.Msg.OK,
                    icon: Ext.Msg.ERROR
                });
            }

        });
    },

    onAddCar: function () {
        Ext.widget('addCarFormView');
    },

    onDelCar: function () {
        var sm = this.getCarGridView().getSelectionModel();
        var rs = sm.getSelection();
        this.getCarGridView().store.remove(rs[0]);
        this.getCarGridView().store.commitChanges();
        this.getCarGridDelete().disable();
    },

    onChangeText: function () {
        Ext.getStore('CarCatalogStore').load({
            params: {
                search: this.getCarCatalogView().down('searchCarView').getValues()
            }
        });
    },

    onLineGrid: function () {
        this.getCarGridDelete().enable();
    },

    onValidation: function () {
        if (this.getAddCarFormName().validate() && this.getAddCarFormPrice().validate()) {
            this.getAddCarFormSave().enable();
        } else {
            this.getAddCarFormSave().disable();
        }
    }

});
ref ссылка на что-то в selector'e;
selector указывает на компоненты, для быстро обращения к ним через ref;
onSaveCar создается модель данных и сохраняется;
onAddCar создает виджет формы добавления;
onDelCar удаляет запись;
onChangeText загружает данные в соответствии со значением в поле поиска;
onLineGrid при выделении строки кнопка «Удалить» становится активной;
onValidation валидация полей формы добавления;

И последнее — добавим иконки к кнопкам «Добавить» и «Удалить».


index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Каталог</title>
    <link rel="stylesheet" type="text/css" href="resources/packages/ext-theme-neptune/build/resources/ext-theme-neptune-all.css"/>
    <script type="text/javascript" src="resources/ext-all.js"></script>
    <script type="text/javascript" src="resources/packages/ext-theme-neptune/build/ext-theme-neptune.js"></script>
    <script type="text/javascript" src="app.js"></script>
    <style type="text/css">
        .icon-delete {
            background-image: url(resources/delete.png) !important;
        }
        .icon-add {
            background-image: url(resources/add.png) !important;
        }
    </style>
</head>
<body>
</body>
</html>



Скачать проект: CarCatalog

Comments (0)

    You need to login to create comments.

    Recent posts

    Last comments

    Popular posts

    Instagram

    Quote of the day

    Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. (С) John Woods.

    Vijvij