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

      Азат Султанов 30 june 2017, 06:08
      Reviews 13

    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