В предыдущей статье я продемонстрировал, как создавать приложения 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):