视频课:https://edu.csdn.net/course/play/7621

1.1 学习技能点

本次在线学习将学习以下知识技能:

Ø 柱状图

Ø 饼状图

Ø 折线图

1.2 学习任务

ExtJS3使用的Flash Chart来源于YUI,其中包括柱状图、饼状图等多种图表,这些图表可以与ExtJS组件完美整合,不仅可以在Panel中显示图表,还可以通过Store为图表提供数据。

1.2.1 任务1使用柱状图统计每月的访问人数

需求说明

首先定义一个JsonStroe为我们要实现的图表提供数据,代码如下:

var store = new Ext.data.JsonStore({

        fields:['name', 'visits', 'views'],

        data: [

            {name:'Jul 07', visits: 245000, views: 3000000},

            {name:'Aug 07', visits: 240000, views: 3500000},

            {name:'Sep 07', visits: 355000, views: 4000000},

            {name:'Oct 07', visits: 375000, views: 4200000},

            {name:'Nov 07', visits: 490000, views: 4500000},

            {name:'Dec 07', visits: 495000, views: 5800000},

            {name:'Jan 08', visits: 520000, views: 6000000},

            {name:'Feb 08', visits: 620000, views: 7500000}

        ]

 });

JsonStroe中包含3列数据,分别是namevisitsviews,分别表示日期、访问人数、浏览量,本章各个任务都使用此数据。

大家已经学习了可以使用grid显示这些数据,但是不利于分析,也很难看出数据的变化,下面就使用柱状图统计每个月的访问人数,效果如图6.1.1所示。

 

6.1.1 柱状图

实现步骤

//此行代码必须,指定图表swf文件路径

Ext.chart.Chart.CHART_URL = 'extjs/resources/charts.swf';

Ext.onReady(function(){

   var store = new Ext.data.JsonStore({

        fields:['name', 'visits', 'views'],

        data: [

            {name:'Jul 07', visits: 245000, views: 3000000},

            {name:'Aug 07', visits: 240000, views: 3500000},

            {name:'Sep 07', visits: 355000, views: 4000000},

            {name:'Oct 07', visits: 375000, views: 4200000},

            {name:'Nov 07', visits: 490000, views: 4500000},

            {name:'Dec 07', visits: 495000, views: 5800000},

            {name:'Jan 08', visits: 520000, views: 6000000},

            {name:'Feb 08', visits: 620000, views: 7500000}

        ]

    });

    new Ext.Panel({

        title: 'Chart',

        renderTo: 'chart',

        width:500,

        height:300,

        frame:true,

        layout:'fit',

        items: {

            xtype: 'columnchart',//指定是柱状图

            store: store,//指定数据

            xField: 'name',//X坐标数据来源

            yField: 'visits'//Y坐标数据来源

        }

    });

});

注意:包含图表的页面必须部署到服务器中进行访问,否则无法显示图表。

1.2.2 任务2使用折线图统计每月的访问人数

需求说明

使用折线图统计每月的访问人数,效果如图6.1.2所示。

 

6.1.2 折线图

1.2.3 任务3:使用饼状图统计每月的访问人数

需求说明

使用饼状图统计每月的访问人数,效果如图6.1.3所示。

 

6.1.3 饼状图

1.3 参考资料

本章节学习资料来源于:

http://www.sencha.com/

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

第2章 复习指导

2.1 知识总结

2.1.1 阶段核心技能目标

本课程要掌握如下技能和知识:

Ø 掌握XML文档和解析

Ø 熟练应用ExtJS常用组件

Ø 熟练应用ExtJS常用布局

Ø 掌握ExtJS工具栏和菜单

Ø 掌握ExtJS图表

2.1.2 知识体系总结

本课程所学知识如图6.1.1所示,从图中可以总结使用ExtJS开发常用知识。

 

7.1.1 使用ExtJS开发RIA应用知识

 

2.2 综合实训

2.2.1 任务描述

本次综合实训任务是使用ExtJS作为前端RIA框架,后台技术使用SSH实现一个学生管理系统。系统首页如图7.1.2所示。

 

7.1.2 学生管理系统首页

点击添加工具按钮,出现添加学生界面,效果如图7.1.3所示。

 

7.1.3 添加学生信息界面

选中Grid中的一行数据后,点击修改工具按钮出现学生信息修改,效果界面如图7.1.4所示。

 

7.1.4 学生信息修改界面

双击Grid中的一行数据,将使用RowEditor进行编辑学生信息,效果如图7.1.5所示。

 

7.1.5 使用RowEditor编辑学生信息

修改学生信息,点击更新按钮后完成学生信息修改,效果如图7.1.6所示。

 

7.1.6 使用RowEditor修改学生信息成功

2.2.2 系统功能

本系统包括以下功能:

Ø 使用Grid本页显示学生信息

Ø 添加学生信息

Ø 修改学生信息

Ø 删除学生信息

Ø 使用行编辑器编辑学生信息

2.2.3 开发要求

ExtJS3Struts2Hibernate3Spring2.5JSONLib

2.2.4 实现步骤

1. 新建Web项目并添加SSH框架支持

2. 编写Hibernate实体类和映射文件

实体类代码如下所示:

package com.yccn.student.entity;

public class Student {

private int id;

private String code;

private String name;

private int sex;

private int age;

private String political;

private String origin;

//省略gettersetter

}

3. 编写DAO层接口和实现

DAO接口代码代码如下所示:

package com.yccn.student.dao;

public interface StudentDAO {

Serializable save(Student st);

Student getById(int id);

void deleteById(int id);

List<Student> queryByPage(int start,int limit);

Object merge(Student st);

Long getCount();

}

DAO实现类代码如下所示:

package com.yccn.student.dao.impl;

import java.io.Serializable;

import java.util.List;

import org.hibernate.Session;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.yccn.student.dao.StudentDAO;

import com.yccn.student.entity.Student;

 

public class StudentDAOImpl extends HibernateDaoSupport implements StudentDAO {

@SuppressWarnings("unchecked")

@Override

public List<Student> queryByPage(int start, int limit) {

Session session = getSession(false);

List<Student> students = session.createQuery(

"from Student s order by s.code").setFirstResult(start)

.setMaxResults(limit).list();

return students;

}

 

@Override

public Serializable save(Student st) {

return getHibernateTemplate().save(st);

}

 

@Override

public Student getById(int id) {

return (Student) getHibernateTemplate().get(Student.class, id);

}

 

@Override

public void deleteById(int id) {

getHibernateTemplate().delete(getById(id));

}

 

@Override

public Object merge(Student st) {

return getHibernateTemplate().merge(st);

}

 

@Override

public Long getCount() {

return (Long) getHibernateTemplate().find(

"select count(id) from Student").get(0);

}

 

}

4. 编写业务逻辑层接口和实现类

业务逻辑层接口代码参考如下:

package com.yccn.student.service;

import java.io.Serializable;

import java.util.List;

import com.yccn.student.entity.Student;

public interface StudentService {

List<Student> listStudentsByPage(int start, int limit);

Serializable doAdd(Student st);

Object doEdit(Student st);

void doDelete(int id);

Long getCount();

}

 

业务逻辑层实现类代码参考如下:

package com.yccn.student.service.impl;

 

import java.io.Serializable;

import java.util.List;

import com.yccn.student.dao.StudentDAO;

import com.yccn.student.entity.Student;

import com.yccn.student.service.StudentService;

public class StudentServiceImpl implements StudentService {

private StudentDAO studentDAO;


public void setStudentDAO(StudentDAO studentDAO) {

this.studentDAO = studentDAO;

}


public List<Student> listStudentsByPage(int start,int limit){

return studentDAO.queryByPage(start, limit);

}

 

@Override

public Serializable doAdd(Student st) {

return studentDAO.save(st);

}

 

@Override

public Object doEdit(Student st) {

return studentDAO.merge(st);

}

 

@Override

public void doDelete(int id) {

studentDAO.deleteById(id);

}

 

@Override

public Long getCount() {

return studentDAO.getCount();

}

}

5. 编写Action

Action类代码参考如下:

package com.yccn.student.action;

 

import java.io.IOException;

import java.io.PrintWriter;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ModelDriven;

import com.yccn.student.entity.Student;

import com.yccn.student.service.StudentService;

 

public class StudentAction implements ModelDriven<Student> {

private Student student = new Student();

private StudentService studentService;

private int start;

private int limit;


public int getStart() {

return start;

}

public void setStart(int start) {

this.start = start;

}

public int getLimit() {

return limit;

}

public void setLimit(int limit) {

this.limit = limit;

}

public void setStudentService(StudentService studentService) {

this.studentService = studentService;

}

@Override

public Student getModel() {

return student;

}

//分页查询学生信息

public String listStudents() throws Exception {

List<Student> students = studentService.listStudentsByPage(start, limit);

Map<String,Object> data = new HashMap<String,Object>();

data.put("totalCount", studentService.getCount());

data.put("result", students);

this.outPrint(this.toJSONString(data));

return null;

}

//添加学生信息

public String add() throws Exception {

studentService.doAdd(student);

outPrint("{success:true,msg:'添加学生信息成功'}");

return null;

}

//修改学生信息

public String edit() throws Exception {

studentService.doEdit(student);

System.out.println(student);

outPrint("{success:true,msg:'修改学生信息成功'}");

return null;

}

//删除学生信息

public String delete() throws Exception {

studentService.doDelete(student.getId());

System.out.println(student.getId());

outPrint("{success:true,msg:'删除学生信息成功'}");

return null;

}

private String toJSONString(Object o){

return JSONObject.fromObject(o).toString();

}

private void outPrint(String s) throws IOException{

HttpServletResponse response = ServletActionContext.getResponse();

response.setCharacterEncoding("utf8");

PrintWriter out = response.getWriter();

out.print(s);

}

}

6. 框架配置

最终各个配置文件如下所示:

web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<listener>

<listener-class>

org.springframework.web.context.ContextLoaderListener

</listener-class>

</listener>

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:applicationContext_*.xml</param-value>

</context-param>

<filter>

<filter-name>struts2</filter-name>

<filter-class>

org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

</filter-class>

</filter>

<filter-mapping>

<filter-name>struts2</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

</web-app>

Hibernate配置文件:

<?xml version='1.0' encoding='UTF-8'?>

<!DOCTYPE hibernate-configuration PUBLIC

          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>

<property name="dialect">

org.hibernate.dialect.MySQLDialect

</property>

<property name="connection.url">jdbc:mysql:///test</property>

<property name="connection.username">root</property>

<property name="connection.password">admin</property>

<property name="connection.driver_class">

com.mysql.jdbc.Driver

</property>

<property name="hibernate.show_sql">true</property>

<property name="hibernate.hbm2ddl.auto">update</property>

<mapping resource="com/yccn/student/entity/Student.hbm.xml" />

</session-factory>

</hibernate-configuration>

Spring配置使用多配置文件的方式,其中applicationContext_common.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:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

 

<bean id="sessionFactory"

class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<property name="configLocation" value="classpath:hibernate.cfg.xml">

</property>

</bean>


<bean id="myTxManager"

class="org.springframework.orm.hibernate3.HibernateTransactionManager">

<property name="sessionFactory" ref="sessionFactory" />

</bean>

 

<aop:config>

<aop:pointcut id="serviceMethods"

expression="execution(* com.yccn.student.service.impl.*.*(..))" />

<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods" />

</aop:config>

 

<tx:advice id="txAdvice" transaction-manager="myTxManager">

<tx:attributes>

<tx:method name="do*" />

<tx:method name="*" propagation="SUPPORTS" read-only="true" />

</tx:attributes>

</tx:advice>


</beans>

applicationContext_student.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:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

 

<bean name="studentDAO" class="com.yccn.student.dao.impl.StudentDAOImpl">

<property name="sessionFactory" ref="sessionFactory"></property>

</bean>

<bean name="studentService" class="com.yccn.student.service.impl.StudentServiceImpl">

<property name="studentDAO" ref="studentDAO"></property>

</bean>

<bean name="studentAction" class="com.yccn.student.action.StudentAction" scope="prototype">

<property name="studentService" ref="studentService"></property>

</bean>

</beans>

7. 编写前端界面

前端使用ExtJS实现,参考代码如下所示。

Ext.onReady(function() {

Ext.QuickTips.init();

    var sexRenderer = function(value) {

        if (value == 1) {

            return '<span style="color:red;font-weight:bold;"></span>';

        } else if (value == 2) {

            return '<span style="color:green;font-weight:bold;"></span>';

        }

    };

 var editor = new Ext.ux.grid.RowEditor({

        saveText: '更新',

        cancelText:'取消'

        

});

editor.on("afteredit",function(roweditor, changes, record, rowIndex){

Ext.Ajax.request({

        url: 'student_edit.action',

        success: function(response) {

         record.commit();

            var json = Ext.decode(response.responseText);

            if (json.success) {

                Ext.example.msg('操作提示',json.msg);

            }

        },

        failure: function() {

            Ext.Msg.alert('错误', "删除失败");

        },

        params: record.data

});

});

 

    var StudentRecord = Ext.data.Record.create([

        {name: 'id', type: 'int'},

        {name: 'code', type: 'string'},

        {name: 'name', type: 'string'},

        {name: 'sex', type: 'int'},

        {name: 'age', type: 'int'},

        {name: 'political', type: 'string'},

        {name: 'origin', type: 'string'},

        {name: 'professional', type: 'string'}

    ]);

 

    var store = new Ext.data.Store({

        proxy: new Ext.data.HttpProxy({url: 'student_listStudents.action'}),

        reader: new Ext.data.JsonReader({

            totalProperty: 'totalCount',

            root: 'result'

        },StudentRecord),

        remoteSort: true

    });

    store.load({params:{start:0,limit:10}});

var sexCombo = new Ext.form.ComboBox({

fieldLabel: '性别',

name: 'sexText',

        hiddenName: 'sex',

triggerAction: 'all',

mode: 'local',

valueField: 'value',

displayField: 'text',

store: new Ext.data.SimpleStore({

    fields: ['value','text'],

    data: [['1',''],['2','']]

})


});

var politicalCombo = new Ext.form.ComboBox({

name: 'political',

store: new Ext.data.SimpleStore({

                fields: ['text'],

                data: [['群众'],['党员'],['团员']]

            }),

        emptyText: '请选择',

        mode: 'local',

        triggerAction: 'all',

        valueField: 'text',

        displayField: 'text',

        fieldLabel: '政治面貌'

});

    var columns = new Ext.grid.ColumnModel([{

header : '学号',

dataIndex : 'code',

editor : {

xtype : 'textfield',

allowBlank : false

}

}, {

header : '姓名',

dataIndex : 'name',

editor : {

xtype : 'textfield',

allowBlank : false

}

}, {

header : '性别',

dataIndex : 'sex',

renderer : sexRenderer,

editor:{

xtype:'combo',

triggerAction: 'all',

mode: 'local',

valueField: 'value',

displayField: 'text',

store: new Ext.data.SimpleStore({

    fields: ['value','text'],

    data: [['1',''],['2','']]

})


}

}, {

header : '年龄',

dataIndex : 'age',

editor : {

xtype : 'numberfield',

allowBlank : false

}

}, {

header : '政治面貌',

dataIndex : 'political',

editor:{

xtype: 'combo',

store: new Ext.data.SimpleStore({

                fields: ['text'],

                data: [['群众'],['党员'],['团员']]

            }),

        emptyText: '请选择',

        mode: 'local',

        triggerAction: 'all',

        valueField: 'text',

        displayField: 'text'

}

}, {

header : '籍贯',

dataIndex : 'origin',

editor : {

xtype : 'textfield',

allowBlank : false

}

}]);

    columns.defaultSortable = true;

 

    // grid start

    var grid = new Ext.grid.GridPanel({

        title: '学生信息列表',

        region: 'center',

        loadMask: true,

        stripeRows:true,

        plugins: [editor],

        store: store,

        cm: columns,

        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),

        viewConfig: {

            forceFit: true

        },

        bbar: new Ext.PagingToolbar({

            pageSize: 10,

            store: store,

            displayInfo: true,

            plugins: new Ext.ux.ProgressBarPager()

        }),

        tbar:[{

         text:'添加',

         icon:'icon/add.gif',

         handler:function(){

         form.getForm().reset();

         window.show();

         }

        },'-',{

         text:'修改',

         icon:'icon/edit.png',

         handler:function(){

         var record = grid.getSelectionModel().getSelected();

         if(!record){

         Ext.Msg.alert("提示","请选择要操作的记录行");

         } else {

         form.getForm().loadRecord(record);

         window.show();

         }

         }

        },'-',{

         text:'删除',

         icon:'icon/delete.gif',

         handler: function() {

                var record = grid.getSelectionModel().getSelected();

                if (!record) {

                    Ext.Msg.alert('提示', '请选择需要删除的信息。');

                } else {

                 Ext.Msg.confirm("提示","删除后将无法恢复,确定要删除记录吗?",

                 function(btn){

                 if(btn == "yes"){

                 Ext.Ajax.request({

                        url: 'student_delete.action',

                        success: function(response) {

                          var json = Ext.decode(response.responseText);

                          if (json.success) {

                            Ext.Msg.alert('消息', json.msg, function() {

                                    grid.getStore().reload();

                                    form.getForm().reset();

                                });

                            }

                        },

                        failure: function() {

                            Ext.Msg.alert('错误', "删除失败");

                        },

                        params: "id=" + record.data.id

                    });

                 }

                 })

                }

            }

        },'-',{

         xtype:'textfield',

         width:250

        },'-',{

         text:'搜索',

         icon:'icon/query.png'

        }]

    });

    /*grid.on("rowdblclick",function(g,i){

     var rc = grid.getStore().getAt(i);

      form.getForm().reset();

        form.getForm().loadRecord(rc);

        window.show();

    });*/

    // grid end

 

    // form start

    var form = new Ext.form.FormPanel({

        frame: true,

        width: 300,

        autoHeight: true,

        labelAlign: 'right',

        labelWidth: 60,

        defaultType: 'textfield',

        buttonAlign:'center',

        defaults: {

            width: 200,

            allowBlank: false

        },

        items: [{

            xtype: 'hidden',

            name: 'id'

        },{

            fieldLabel: '学号',

            name: 'code'

        },{

            fieldLabel: '姓名',

            name: 'name'

        },{

            fieldLabel: '年龄',

            name: 'age',

            xtype: 'numberfield',

            allowNegative: false

        },sexCombo,politicalCombo,{

            fieldLabel: '籍贯',

            name: 'origin'

        }],

        buttons: [{

            text: '提交',

            handler: function() {

                if (!form.getForm().isValid()) {

                    return;

                }

                var v = form.getForm().findField("id").getValue();

                //alert(v);

                if(v == ""){

                  // 添加

               form.getForm().submit({

                    url: 'student_add.action',

                    success: function(f, action) {

                        if (action.result.success) {

                        window.hide();

                          Ext.Msg.alert('消息', action.result.msg, function() {

                                grid.getStore().reload();

                                form.getForm().reset();

                            });

                        }

                    },

                    failure: function() {

                        Ext.Msg.alert('错误', "添加失败");

                    }

               });

                } else {

                 //修改

                 form.getForm().submit({

                    url: 'student_edit.action',

                    success: function(f, action) {

                     if (action.result.success) {

                       window.hide();

                       Ext.Msg.alert('消息', action.result.msg, function() {

                                grid.getStore().reload();

                                form.getForm().reset();

                            });

                      }

                    },

                    failure: function() {

                        Ext.Msg.alert('错误', "添加失败");

                    }

               });

                }

               

            }

        },{

            text: '重置',

            handler: function() {

                form.getForm().reset();

            }

        }]

    });

    // form end

var window = new Ext.Window({

title:'编辑学生信息',

closable:true,

width:312,

closeAction:'hide',

modal:true,

items:form

});

 

    // layout start

    var viewport = new Ext.Viewport({

        layout: 'border',

        items: [grid]

    });

    // layout end

});