В предыдущей статье я продемонстрировал, как создавать приложения ExtJs. В следующих строках я покажу содержимое небольшого приложения для управления пациентами, использующего ExtJs в качестве клиентской среды и Java Web со средой Spring на стороне сервера.
I- таблица схемы базы данных
Ниже сценария DDL таблицы Patient :
CREATE TABLE Patient( Id INT NOT NULL AUTO_INCREMENT, FirstName VARCHAR(100) NOT NULL, LastName VARCHAR(100) NOT NULL, Address VARCHAR(100) NOT NULL, City VARCHAR(100) NOT NULL, Country VARCHAR(100) NOT NULL, PRIMARY KEY (ID) );
II — Клиентская сторона: архитектура ExtJs + MVC
Сначала нам нужно создать новый веб-проект Java (пожалуйста, следуйте этому руководству ) с Spring Web MVC в IDE NetBeans. Мой был назван PatientManagement .
Во второй раз мы создаем клиентскую часть, используя среду ExtJs и соблюдая архитектуру MVC (Controller и View). Ниже картинка, подытоживающая проект:
Index.html файл исходного кода:
<!-- To change this license header, choose License Headers in Project Properties. To change this template file, choose Tools | Templates and open the template in the editor. --> <!DOCTYPE html> <html> <head> <title>PATIENT MANAGEMENT</title> <link rel="stylesheet" type="text/css" href="ext/resources/css/ext-all.css"> <script type="text/javascript" src="ext/ext-all.js"></script> <script type="text/javascript" src="app.js"></script> </head> <body></body> </html>
App.js содержимое файла:
Ext.Loader.setConfig({ enabled: true }); Ext.application({ name: 'PM', appFolder: 'front/app', controllers: ['PatientController'], autoCreateViewport: true, launch: function() { } });
Взгляды :
AppToolbar.js содержимое файла:
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ Ext.define('PM.view.patient.AppToolbar', { extend: 'Ext.panel.Panel', alias: 'widget.apptoolbar', initComponent: function() { this.dockedItems = [ {xtype: 'toolbar', dock: 'top', items: [ { xtype: 'cycle', showText: 'true', text: '<html><b>Patient</b></html>', width: '300', menu: { xtype: 'menu', width: '150', items: [ { xtype: 'menucheckitem', text: 'New patient', action: 'create' }, { xtype: 'menucheckitem', text: 'Patients list', action: 'listing' } ] } } ] } ]; this.callParent(arguments); } });
AddPatient.js исходный файл кода:
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ Ext.define('PM.view.patient.AddPatient', { extend: 'Ext.window.Window', alias: 'widget.addpatient', title: 'Create a patient', layout: 'fit', autoShow: true, initComponent: function() { this.items = [ { xtype: 'form', bodyStyle: { background: 'none', padding: '10px', border: '0' }, items: [ { xtype: 'textfield', name: 'firstname', allowBlank: false, fieldLabel: '<html><b>Firts Name</b></html>' }, { xtype: 'textfield', name: 'lastname', allowBlank: false, fieldLabel: '<html><b>Last Name</b></html>' }, { xtype: 'textfield', name: 'address', fieldLabel: '<html><b>Address</b></html>', allowBlank: false }, { xtype: 'textfield', name: 'city', fieldLabel: '<html><b>City</b></html>', allowBlank: false }, { xtype: 'textfield', name: 'country', fieldLabel: '<html><b>Country</b></html>', allowBlank: false } ] } ]; this.buttons = [ { text: 'Save', action: 'save' }, { text: 'Cancel', scope: this, handler: this.close } ]; this.callParent(arguments); } });
Содержимое файла viewport
Viewport.js :
Ext.define('PM.view.Viewport', { extend: 'Ext.container.Viewport', alias: 'widget.viewport', items: [ { xtype: 'apptoolbar' }], initComponent: function() { this.callParent(arguments); } });
Контроллер:
Содержание PatientController.js ниже:
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ Ext.define('PM.controller.PatientController', { extend: 'Ext.app.Controller', views: ['patient.AddPatient', 'patient.AppToolbar'], init: function() { this.control({ 'addpatient button[action=save]': { click: this.doCreatePatient }, 'apptoolbar > toolbar > cycle > menu > menucheckitem[action=create]': { click: this.onCreatePatient } }); }, onCreatePatient: function() { //The panel to create a patient appears on the screen var view = Ext.widget('addpatient'); }, //Function to create a new patient doCreatePatient: function(button) { var win = button.up('window'), form = win.down('form'), values = form.getValues() if (form.getForm().isValid()) { Ext.Ajax.request({ url: 'PatientController', method: 'POST', params: { patientcreateData: Ext.encode(values) }, scope: this, stateful: true }); win.close(); } }, });
В этом контроллере мы используем синглтон Ext.Ajax для отправки HTTP-запроса на удаленный сервер. В нашем примере мы будем использовать метод POST для отправки данных, и мы будем использовать серверный сервлет PatientController.java (см. Ниже код источника). Объект JSON — это PatientCreateData .
Web.xml файл был изменен в соответствии с проектом , чтобы файл index.html в качестве страницы приветствия.
<welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list>
III — Серверная реализация
Ниже приведен пример файлов Java, определяющих серверную часть приложения:
Код модели Patient.java находится здесь:
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.model.patientmanagement; /** * * @author constantin */ public class Patient { private int id; private String firstname; private String lastname; private String address; private String city; private String country; public Patient() { } public Patient(String firstname, String lastname, String address, String city, String country) { this.firstname = firstname; this.lastname = lastname; this.address = address; this.city = city; this.country = country; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } }
Содержимое файла DAO P atientDao.java находится здесь:
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.dao.patientmanagement; import com.model.patientmanagement.Patient; import java.util.List; import javax.sql.DataSource; /** * * @author constantin */ public interface PatientDao { public void setDataSource(DataSource dataSource); public void createPatient(String firstname, String lastname, String address, String city, String country); public Patient getPatientById(Integer id); public void deletePatient(Integer id); public List<Patient> listPatients(); public void updateFirstName(Integer id, String firstname); }
Источник PatientTemplate.java :
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.impl.patientmanagement; import com.dao.patientmanagement.PatientDao; import com.model.patientmanagement.Patient; import java.util.List; import javax.sql.DataSource; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; /** * * @author constantin */ public class PatientTemplate implements PatientDao { private DataSource dataSource; private JdbcTemplate jdbcTemplateObject; @Override public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; this.jdbcTemplateObject = new JdbcTemplate(dataSource); } @Override public void createPatient(String firstname, String lastname, String address, String city, String country) { try { String Sql = "insert into Patient(firstname, lastname, address, city,country) values (?,?,?,?,?)"; jdbcTemplateObject.update(Sql, firstname, lastname, address, city, country); } catch (DataAccessException ex) { System.out.println("Error" + ex.getMessage()); } } @Override public Patient getPatientById(Integer id) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public void deletePatient(Integer id) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public List<Patient> listPatients() { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public void updateFirstName(Integer id, String firstname) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } }
PatientMapper.java содержимое файла:
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.impl.patientmanagement; import com.model.patientmanagement.Patient; import java.sql.ResultSet; import java.sql.SQLException; import org.springframework.jdbc.core.RowMapper; /** * * @author constantin */ public class PatientMapper implements RowMapper<Patient> { @Override public Patient mapRow(ResultSet rs, int i) throws SQLException { //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. Patient patient = new Patient(); patient.setId(rs.getInt("id")); patient.setFirstname(rs.getString("firstname")); patient.setLastname(rs.getString("lastname")); patient.setAddress(rs.getString("address")); patient.setCity(rs.getString("city")); patient.setCountry(rs.getString("country")); return patient ; } }
Вот источник кода метода doPost сервлета PatientController.java :
@Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //Get the context of the application ServletContext servletContext = this.getServletContext(); WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext); String patientcreateData = request.getParameter("patientcreateData"); //I parse here the json object GenericJsonParser jsonPatient = new GenericJsonParser(); HashMap<String, String> patientMap = jsonPatient.getJsonMap(patientcreateData); String firstname = patientMap.get("firstname"); String lastname = patientMap.get("lastname"); String address = patientMap.get("address"); String city = patientMap.get("city"); String country = patientMap.get("country"); PatientTemplate patient = (PatientTemplate) wac.getBean("patienttemplate"); patient.createPatient(firstname, lastname, address, city, country); }
Класс для анализа объекта Json реализован, как показано ниже ( GenericJsonParser.java ):
Этот класс очень важен, поскольку в API JSON-P нет метода для привязки объекта Java и объекта JSON. Он анализирует объект Json и возвращает карту, которую легче использовать в коде Java.
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.controller.patientmanagement; import java.io.StringReader; import java.util.HashMap; import javax.json.Json; import javax.json.stream.JsonParser; import static javax.json.stream.JsonParser.Event.END_OBJECT; import static javax.json.stream.JsonParser.Event.KEY_NAME; /** * * @author constantin Drabo * This class allow you to parse a Json object coming from client side */ public class GenericJsonParser { public GenericJsonParser() { } public HashMap<String, String> getJsonMap(String jsonflux) { String keyvalue; JsonParser parser = Json.createParser(new StringReader(jsonflux)); JsonParser.Event event = parser.next(); HashMap<String, String> jsonElements; jsonElements = new HashMap<String, String>(); while (event != END_OBJECT) { event = parser.next(); if (event == KEY_NAME) { keyvalue = parser.getString(); System.out.println("KeyValue === " + keyvalue); parser.next(); jsonElements.put(keyvalue, parser.getString()); } } return jsonElements; } }
IV- Запустить приложение
Приложение будет выглядеть так, когда оно запущено:
Вот пример данных, которые мы сохраним:
Когда они нажимают кнопку Сохранить, они получают этот объект Json (здесь захваченный Firebug):