posts - 78, comments - 34, trackbacks - 0, articles - 1
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2010年1月9日

       我们的课程即将结束,有一种想立即进入公司工作的冲动,也有一种对这种整日在学校学习生活的眷恋。

      

       培训学校都是骗子,这是在网上见得多的传言。在我想找一家培训机构提升自己的技术时,现实和这些话语让我有些的警觉。为了找一家好的培训机构,我使用了两个月的业余时间不停的在网上转悠,不停的对比各培训机构的课程,对比视频,对比网上的评论...。因为我已经有近三年的桌面相关开发经验,我需要的课程内容是提高技术。最终找到了感觉上适合我的传智播客!(价钱也比较合理)

 

       我是2009115日班的,来到北京我不大喜欢学校推介的住宿环境,幸好我提前两天来到这里。第二天便与几个同学在外面找了个租处——唐家岭, 这里的环境还算不错,来到之后才知道唐家岭已经是全国知名的地境(蚂族)。这里吃饭的地方比较多,价格还算合理,多尝试了几家饭店,选择了我们比较喜欢的长吃(6-10元)。这里也有早餐,我一般都在饭店里吃(3元左右),特殊情况我才会在马路边上摆的摊子买点早餐。

 

       上了几天的课程,我已深觉到我的选择是正确的。来之前,家人和朋友还担心学校的可信度,现在他们是放心了。授课内容和方式正如传智播客所倡导的——深度,这是他们的文化,这是正确的道路。

 

       传智播客提倡学生们写学习日志,按要求完成后还有奖金,这是一个非常好的激励学习方式,当然也这是一个非常好的推广学校的方式。这一点也非常吸引我,所以在我来之前就做了写学习日志的决定。因为我知道我不想终生做为一个技术人员,即使做为一个技术人员做到一定的时候写些东西是必须的。可能会写技术文章、项目文档...。其次,我想将学习的每一项技术详细认真的总结,深入他们的原理。这些促使做了写日志的决定。

 

       但来到学校学习了几天才发现,要详细认真的总结所学习的内容那是不可能的。课后的每天晚上我都坚持写学习日志,忙的时候写到凌晨2:00(偶尔)。如果我能详细认真的总结出每天的学习内容,那我已经可以出三四本书籍了。

 

       至于写学习日志这一点,要适力而为。如果想写好学习日志,就要投入时间和精力,这样就减少了动手练习的时间,对于新人来说这是致命的。我一般都是使用休息的时间来动手。所以,写学习日志自己要打量好了,要写到什么程度、要做多少练习。

 

       在来传智之前,也有看到网上骂传智的贴子。这帖子无论是来自真实的学员、还是来自某些竞争对手。强大而美好的东西自然能证实自己。一个再好的人,怎么会得到所有的人认可!在学校里学习的都是好学生吗?都是努力学习的学生吗?肯定不是,似乎在哪里都能看到这一部分人,当然我以前也不那么喜欢学习。既然远远来到这里学习,也想找一份好工作,那就努力学习吧!

 

       在近期课程将要结束时,有到学校来招聘的公司。这些信息是即时在学校的网站上发布。

有的同学已经与公司签订了合同。但来直接来学校招聘的公司一般给的工资都不会太高,也有给的还算理想的,主要看个人能力。我想回大连工作,没有参加他们的面试。课程结束后我就回大连,虽然老师们不建议我回去...

 

       我要感谢传智播客那些认真、负责、可爱的老师,张孝祥、方力勋、冯威、佟刚、汤阳光、徐培成、毛伟、黎活明,他们让我大丰收。感谢他们的殷勤付出,祝他们身体健康,工作愉快!(话外,上老张和老黎的课要注意下课时及时打水和去卫生间,这两人太尿性了。)

 

       现在WEB开发、桌面开发对我来说已经没多大神秘了,但需要我学习的内容仍然很多很多!    

 

       我时而为自己的命运庆幸,我的道路让我深感到了他的正确!

 

posted @ 2010-03-16 21:27 長城 阅读(2995) | 评论 (6)编辑 收藏

    剩下5天的内容是ERP进销存项目和Linux,这几天我将为今后的工作做准备,所以可能不再学习总结了!

posted @ 2010-03-11 21:11 長城 阅读(1524) | 评论 (0)编辑 收藏

       今日继续我们的Axis学习,我只进行一下简单的总结。有机会再补上吧!

 

       昨天我们学习了,使用WebService进行运程调用,传递基本类型数据和类实体数据。在传递基本数据类型时,我们不需要进行任何操作。但在传递类实体类型数据时,我们需要在服务器端和客户端进行序列化和反序列化注册。那还有哪些数据传递是我们需要注意的?

 

       基本数据类型数组和集合、类类型数组和集合、远程异常。在传递基本类型数组或集合时,我们不需要添加任何声明。但在传递类类型数组或集合时,需要添加与传递类实例进行相同的注册。远程异常应该如何传递?

 

       远程异常,需要通过fault元素注册一个 远程异常。

 

       上面我们对基本数据类型和类类型的简单传输有了基本的认识,但是复合类型应该如何传递呢?类套类,这样下去,难道我们需要手动添加注册信息吗?当然不需要,Axis为我们提供了相应的工具,通过WSDL生成客户端和服务器端Java类,通过Java类(接口)生成WSDL文档,在此我就不详细总结了。

 

       除了Axis,老徐又给我们介绍了xfire,它也是WebService的一种实现工具。在此也不做总结了。

 

       有位网友跟我说还有一种WebService——xcf,是目前最流行的,我并未对此进行埋阅。但我想说的是,以后可能还会有其他流行的WebService实现,但无论出什么样的新东西,它的核心思想都是一样的。这也是我来传智学习的一大原因,如果只知道一种工具如何使用,而不知道它的道理,确实不高明。如果掌握了它的道理,那就是以不变应万变了!

 

posted @ 2010-03-10 21:42 長城 阅读(1525) | 评论 (0)编辑 收藏

     摘要:        WebService课程由徐培成老师主讲,依然发扬传智播客的特点——深入理论和实践。今天老徐讲的原理的专业术语比较多,但我只做WebService的应用总结。如果你的Java和JavaWeb基础好些,我想你看到WebService的应用,自然就能想到它的实现原理。      &nbs...  阅读全文

posted @ 2010-03-08 22:40 長城 阅读(3232) | 评论 (1)编辑 收藏

     摘要: 一、Android中的通知          一般手机上边都有一个状态条,显示电池电量、信号强度、未接来电、短信...。Android的屏幕上方也具有状态条。这里所说的通知,就是在这个状态条上显示通知。          发送通知的步骤如下: &n...  阅读全文

posted @ 2010-03-07 12:41 長城 阅读(2265) | 评论 (0)编辑 收藏

     摘要:          今日课程内容较多,我们的课上到晚7:20。   一、创建新的Activity        在进行桌面开发时,我们可以通过一个窗口上的控件事件打开另一个新的窗口。在WEB应用开发时,我们也可以通过一个连接打开一个新的页面。通过...  阅读全文

posted @ 2010-03-07 10:42 長城 阅读(6123) | 评论 (0)编辑 收藏

     摘要:        我们编写的是Andorid的HTTP多线程断点下载应用程序。因为之间我们学习的学习积累,直接使用单线程下载HTTP文件对我们来说是一件非常简单的事。那么,多线程断点下载的难点在哪里?1.多线程下载,2.支持断点。          多线程下载: &...  阅读全文

posted @ 2010-03-04 14:35 長城 阅读(5406) | 评论 (1)编辑 收藏

     摘要:        昨天我们只对Android接收网络数据进行了简单介绍,今天我们完成了Android数据存储网络部分的所有内容。在此我将对这非常重要的内容进行总结。          本篇日志是对Android与WEB应用服务之间进行数据交互的总结,下篇日志是一个经典...  阅读全文

posted @ 2010-03-04 11:34 長城 阅读(6184) | 评论 (0)编辑 收藏

既然是3G开发,网络重要性自然不必多说!Android的网络存储使用HTTP协议,我们编写的Android网络应用就相当于一个浏览器。由于Android的应用是使用Java来开发的,所以网络应用使用的也是J2SE的包。

 

       Android如何与服务器交互数据?我们可以建立一个WEB应用,这对我们来说是一件十分容易的事。在WEB应用的相关请求处理中接收Andorid提交的数据、返回XML数据或JSON数据。Android发送相应的请求并接收服务相应的数据。这就是AndroidWEB应用的数据交互。

 

       Android发送请求和获取数据如下:

String path = "http://www.android.com/images/opensourceproject.gif";

URL url = new URL(path);

HttpURLConnection conn = (HttpURLConnection)url.openConnection();

conn.setConnectTimeout(6 * 1000);

InputStream inStream = conn.getInputStream();

 

       既然获得了InputStream,那么对数据进行操作就比较容易了。

 

       通过上面的代码,可见Android的网络应用是如此容易!

 

       这只是个开始,明天继续学习网络部分!

 

posted @ 2010-03-02 22:53 長城 阅读(1479) | 评论 (0)编辑 收藏

     摘要:        早上我们简要的对SQLite进行回顾,然后将SQLite的事务管理和SQLiteDataBase提供的Insert、Update、Delete、Query方法进行了简单的讲解。          今日的重点内容是ContentProvider(内容提...  阅读全文

posted @ 2010-03-02 22:12 長城 阅读(4464) | 评论 (4)编辑 收藏

     摘要: 前两篇日志我已经总结了本地数据存储的前两种:文件和配置项。还剩下最后一种数据库存储——SQLite。   一、SQLite简介   在Android平台上,集成了一个嵌入式关系型数据库—SQLite,SQLite3支持 NULL、INTEGER、REAL(浮点数字)、TEXT(字符串文本)和BLOB(二进制对象)数据类型,虽然它支持的类型虽然只有五种,但实际上sqli...  阅读全文

posted @ 2010-03-01 22:58 長城 阅读(5803) | 评论 (5)编辑 收藏

     摘要:        在此之前的学习内容是数据存储之一文件存储。在本地存储中常用的有,文件、配置文件、数据库。前面的学习主要是针对本地文件的。我认为可以把SharedPreferences看做是配置文件,虽然它也是采用XML格式存储的。          比如我们使用的桌...  阅读全文

posted @ 2010-03-01 15:01 長城 阅读(2435) | 评论 (0)编辑 收藏

     摘要:        今日继续学习Android中使用Pull的XML解析技术实现对XML文件的解析和创建。由于明天休息,时间比较充裕,所以我也将昨天未总结的SAX解析技术在此做个总结。   一、SAX解析技术        Sax使用的是事件驱动的流式解析技术。事件驱...  阅读全文

posted @ 2010-03-01 12:01 長城 阅读(2941) | 评论 (0)编辑 收藏

     摘要:        今日重点内容是Adnroid的数据存储和访问。Android的数据存储有五种:文件 SharedPreferences、SQLite数据库、内容提供者(Content provider)、网络。今天老黎讲解Android的单元测试、文件存储和访问以及解析XML文件。   一、Android的单元测试 &nb...  阅读全文

posted @ 2010-02-27 21:31 長城 阅读(4777) | 评论 (4)编辑 收藏

 一、创建 Android工程

Project name:SendMessage

BuildTarget:Android2.1

Application name:发送短信

Package name:com.changcheng.Activity

Create Activity:SendMessage

Min SDK Version:7


二、编辑工程

1.编辑strings.xml文件内容为:

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

<resources>

<string name="hello">请输入手机号码:</string>

<string name="app_name">发送短信</string>

<string name="content">请输入信息内容:</string>

<string name="send">发送</string>

</resources>


2.编辑main.xml文件内容为:

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical" android:layout_width="fill_parent"

android:layout_height="fill_parent">

<!-- 请输入手机号码标签 -->

<TextView android:layout_width="fill_parent"

android:layout_height="wrap_content" android:text="@string/hello" />

<!-- 手机号码编辑框 -->

<EditText android:layout_width="fill_parent"

android:layout_height="wrap_content" android:id="@+id/mobile" />

<!-- 请输入信息内容标签 -->

<TextView android:layout_width="fill_parent"

android:layout_height="wrap_content" android:text="@string/content" />

<!-- 信息内容编辑框 -->

<EditText android:layout_width="fill_parent"

android:layout_height="wrap_content" android:minLines="3"

android:id="@+id/message" />

<!-- 发送按钮 -->

<Button android:layout_width="wrap_content"

android:layout_height="wrap_content" android:text="@string/send"

android:id="@+id/send"/>

</LinearLayout>

注意,我们在电话号码输入框和拨打电话按钮中添加了android:id属性。如电话号码输入框的android:id=”@+id/mobile”@代码R.java+id代码添加id静态内部类,mobile代表向id类中添加一个常量成员。ADT将自动为我们生成常量值。

android:minLines设置信息内容编辑框的最小行数。


3.编辑Call.java内容:

package com.changcheng.activity;


import java.util.List;

import android.app.Activity;

import android.os.Bundle;

import android.telephony.SmsManager;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.EditText;


public class SendMessage extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

// 根据ID获取按钮

Button button = (Button) this.findViewById(R.id.send);

// 注册按钮被单击事件

button.setOnClickListener(new OnClickListener() {


@Override

public void onClick(View v) {

// 根据ID获取手机号码编辑框

EditText mobileText = (EditText) findViewById(R.id.mobile);

// 获取手机号码

String mobile = mobileText.getText().toString();

// 根据ID获取信息内容编辑框

EditText messageText = (EditText) findViewById(R.id.message);

// 获取信息内容

String message = messageText.getText().toString();

// 移动运营商允许每次发送的字节数据有限,我们可以使用Android给我们提供 的短信工具。

if (message != null) {

SmsManager sms = SmsManager.getDefault();

// 如果短信没有超过限制长度,则返回一个长度的List

List<String> texts = sms.divideMessage(message);

for (String text : texts) {

sms.sendTextMessage(mobile, null, text, null, null);

}

}

}

});

}

}

sms.sendTextMessage(destinationAddress, scAddress, text, sentIntent, deliveryIntent)

destinationAddress:接收方的手机号码

scAddress:发送方的手机号码

text:信息内容

sentIntent:发送是否成功的回执,以后会详细介绍。

DeliveryIntent:接收是否成功的回执,以后会详细介绍。


4.编辑AndroidManifest.xml内容:

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

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.changcheng.activity" android:versionCode="1"

android:versionName="1.0">

<application android:icon="@drawable/icon" android:label="@string/app_name">

<activity android:name=".SendMessage" android:label="@string/app_name">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

</application>

<uses-sdk android:minSdkVersion="7" />

<!-- 注册发送短信的权限 -->

<uses-permission android:name="android.permission.SEND_SMS" />

</manifest>

注册发送短信的权限,如果没有注册这个,将使用不了系统的发送短信功能。以后在我们的应用程序开发中,有使用到系统功能的必须在这个文件中进行注册。我们可以查看Android的帮助手册都有哪些功能。(.../android-sdk-windows/docs/reference/android/Manifest.permission.html


三、启动模拟器

我们给谁发短信?我们可以启动两个模拟器。使用一个模拟器给另一个模拟器发信息。首先我们使用工具栏上的手机图标再添加一个Android2.1的模拟器,另记一个名称。


在启动两个模拟器之前,我们需要模拟器能“接收到信号”。如果我们的机器是联网的,启动模拟器后,主界面显示信号强度的旁边会有一个3G的字样,这说明模拟器已经能接收到信号了。如果我们的机器不能联网,那么将自己的IP地址、网关和DNS服务器都设置为相同的值,比如都设置为192.168.0.100。如果我们的机器是在局域网下,但没有联网,那么将自己的网关和DNS设置为路由的IP即可,一般情况下路由的IP192.168.0.1


OK,现在我们启动两个模拟器!


四、发送短信

我们启动模拟器后,可以看到模拟器窗口的标题栏上有555455556的字样。这是模拟器监听的端口即——127.0.0.15554


在工程上右键,Run As Android Application,选择其中的一个模拟器。比如选择了端口为5554的模拟器。OK,程序被加载到模拟器中了,会被自动运行。


我们在电话号码编辑框中输入5556(接收端模拟器的端口号),点击发送按钮!


OK,你看到效果了吗?5556主界面,显示信号强度的旁边显示收到新短信。


五、使用ADT插件发送短信给模拟器

如果机器太慢,无法启动两个模拟器,我们可以只启动一个模拟器。然后在菜单windows->show view->other->Android->Emulator Control打开Emulator Control面板。


Telephony Actions分组框中,Voice是呼叫,SMS是发送短信。Incoming number是模拟器的端口号,我们也可以使用这个功能给我们的模拟器拨打电话或发送短信。


posted @ 2010-02-27 00:20 長城 阅读(3501) | 评论 (0)编辑 收藏

 

一、创建 Android工程

Project name:Call

BuildTarget:Android2.1

Application name:拨打电话

Package name:com.changcheng.Activity

Create Activity:Call

Min SDK Version:7


二、编辑工程

1.编辑strings.xml文件内容为:

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

<resources>

<string name="hello">请输入 手机号码:</string>

<string name="app_name">拨打电话</string>

<string name="button_call">呼叫</string>

</resources>



2.编辑main.xml文件内容为:

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical" android:layout_width="fill_parent"

android:layout_height="fill_parent">

<!-- 标题标签 -->

<TextView android:layout_width="fill_parent"

android:layout_height="wrap_content" android:text="@string/hello" />

<!-- 电话号码输入框 -->

<EditText android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:id="@+id/mobile"/>

<!-- 拨打电话按钮 -->

<Button android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/button_call"

android:id="@+id/button_call"/>

</LinearLayout>

注意,我们在电话号码输入框和拨打电话按钮中添加了android:id属性。如电话号码输入框的android:id=”@+id/mobile”@代码R.java+id代码添加id静态内部类,mobile代表向id类中添加一个常量成员。ADT将自动为我们生成常量值。


3.编辑Call.java内容:

package com.changcheng.Activity;


import android.app.Activity;

import android.content.Intent;

import android.net.Uri;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.EditText;


public class Call extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

// 根据ID获取按钮

Button button = (Button) this.findViewById(R.id.button_call);

// 为按钮添加被单击事件

button.setOnClickListener(new OnClickListener(){


@Override

public void onClick(View v) {

// 根据ID获取编辑框

EditText editText = (EditText) findViewById(R.id.mobile);

// 获取电话号码

String mobile = editText.getText().toString();

// 生成呼叫意图

Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:"+ mobile));

// 开始呼叫

startActivity(intent);

}

});

}

}



4.编辑AndroidManifest.xml内容:

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

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.changcheng.Activity"

android:versionCode="1"

android:versionName="1.0">

<application android:icon="@drawable/icon" android:label="@string/app_name">

<activity android:name=".Call"

android:label="@string/app_name">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>


</application>

<uses-sdk android:minSdkVersion="7" />

<!-- 注册使用拨打电话功能的权限 -->

<uses-permission android:name="android.permission.CALL_PHONE"/>

</manifest>

注册使用拨打电话功能的权限,如果没有注册这个,将使用不了系统的拨打电话功能。以后在我们的应用程序开发中,有使用到系统功能的必须在这个文件中进行注册。我们可以查看Android的帮助手册都有哪些功能。(.../android-sdk-windows/docs/reference/android/Manifest.permission.html


三、启动模拟器

我们给谁打电话?我们可以启动两个模拟器。使用一个模拟器给另一个模拟器拨打。首先我们使用工具栏上的手机图标再添加一个Android2.1的模拟器,另记一个名称。


在启动两个模拟器之前,我们需要模拟器能“接收到信号”。如果我们的机器是联网的,启动模拟器后,主界面显示信号强度的旁边会有一个3G的字样,这说明模拟器已经能接收到信号了。如果我们的机器不能联网,那么将自己的IP地址、网关和DNS服务器都设置为相同的值,比如都设置为192.168.0.100。如果我们的机器是在局域网下,但没有联网,那么将自己的网关和DNS设置为路由的IP即可,一般情况下路由的IP192.168.0.1


OK,现在我们启动两个模拟器!


四、拨打电话

我们启动模拟器后,可以看到模拟器窗口的标题栏上有555455556的字样。这是模拟器监听的端口即——127.0.0.15554


在工程上右键盘,Run As Android Application,选择其中的一个模拟器。比如选择了端口为5554的模拟器。OK,程序被加载到模拟器中了,会被自动运行。


我们在电话号码编辑框中输入5556(接收端模拟器的端口号),点击呼叫按钮!


OK,你看到效果了吗?5554模拟器显示正在呼叫,5556模拟器有来电显示...


五、使用ADT插件呼叫模拟器

如果机器太慢,无法启动两个模拟器,我们可以只启动一个模拟器。然后在菜单windows->show view->other->Android->Emulator Control打开Emulator Control面板。


Telephony Actions分组框中,Voice是呼叫,SMS是发送短信。Incoming number是模拟器的端口号,我们也可以使用这个功能给我们的模拟器拨打电话或发送短信。

 

posted @ 2010-02-26 23:00 長城 阅读(3710) | 评论 (0)编辑 收藏

     摘要:   万众瞩目,Android终于开课了。本课程有黎活明老师主讲,讲课细致而流畅。想做细他的课程总结,那我没时间和精力了。也是总结个框框,虽然是个框框,但如果看着我的日志跟着我做,也能做起Android开发。 今日的重点内容是,3G简介、Android简介、Android的开发环境搭建、HelloWorld程序、Android程序运行过程、拨打电话小程序、发送短信小程序。我们跳...  阅读全文

posted @ 2010-02-26 21:21 長城 阅读(5338) | 评论 (2)编辑 收藏

 我今天用Struts2Spring整合,但部署到Tomcat(tomcat-6.0.20)时,WabAppClassLoader却给我抛出了一个异常:ClassNotFindException:xxx.ActionServletActionServletStruts1中使用的Action控制器。但我使用的是Struts2啊!

我反复查看自己的配置文件和使用到的Jar包,没有任何问题。然后到网上搜索答案,出现这个问题的人还不少。有的是使用Strut1出现这个问题,那么他可能是没有导入Struts1的核心包导致的。至于使用Struts2也出现这个问题多少就有些奇怪了。

一些网友给出答案,是将Tomcat删除,然后安装一个新的Tomcat这样就可以解决问题。确实如此,我使用这个方法解决了问题。但为什么会出现这个问题呢?我最先想到的是Tomcat可能有缓存功能,于是我查看Tomcat的目录。发现它有一个temp目录和一个work目录,temp目录是做什么用的我不知道,work目录是为我们生成JSPclass文件。

问题就可能出现在这两个目录,所以以后遇见莫名其妙的问题可以删除这两个目录中的内容,然后再试一试。

posted @ 2010-02-25 23:58 長城 阅读(440) | 评论 (0)编辑 收藏

       Struts2第四天,正如预期Struts2的内容还没有讲完,还需要再加一天课。按照正常的授课方式,Struts2在四天内是可以讲完的,但这可能是老张最后一次讲Struts2,所以他要讲得细致些。

 

       今天的重点内容是Struts2的表单错误信息排版、Struts2中的FreeMark、和Struts2中的UI标签。老张计的比较细致,我做总结就不做的那么细致了。

 

一、Struts2的表单错误信息排版

       Struts2的表单错误信息排版是一个比较常见的问题,但网给所见到的解决方案似乎并不正统。老张给出了他的解决方法。

 

       通过之前的学习,我们知道Struts2中的大部分数据交互操作是由ValueStack来完成的。错误信息也是如此。我们在后台使用配置文件校验或硬编码校验,Struts2将错误信息存放在类型为MapfieldErrors对象中。

 

       我们可以在页面表单字段的后边添加此错误信息,比如在user.name表单字段后边添加<s:property value="fieldErrors['user.name'][0]"/>,这样错误信息可以显示在对应的字段后边。这是针对我们使用非struts2ui标签时(使用提htmlui标签)。但这里有一个问题,如果我的表单字段特别的多,难道我要手动为每个字段添加一个这样的错误信息,这多少有些麻烦,而且以后字段有什么变化还需要行动更改...

 

       Struts2在各方面都做的非常细致和人性化,Struts2UI标签等主要是使用FreeMark来实现的。Struts2使用FreeMar来实现模板和主题,那么我们回显表单数据和错误信息也可以使用FreeMark来实现。此时我们的表单需要使用struts-tags提供的标签来定义,然后我们修改它的ftl模板文件。

 

       下面我们看看一下应该如何修改ftl模板文件,我们以UI标签<s:textarea>为例。Struts2的模板文件存在哪?在Struts2的核心包中的template.xhtml中,textarea.ftl文件内容:

<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />

<#include "/${parameters.templateDir}/simple/textarea.ftl" />

<#include "/${parameters.templateDir}/xhtml/controlfooter.ftl" />

      

       我们只需修改 controlheader.ftlcontrolfooter.ftl即可,难道我们需要修改Struts2核心包中的内容?当然不用,这一点Struts2已经为我们考虑到了。我们将这两个文件解压缩并放到WebRoot目录下的”template/xhtml”目录,必须是xhtml目录。看default.properties文件中的这断配置:

### Standard UI theme

### Change this to reflect which path should be used for JSP control tag templates by default

struts.ui.theme=xhtml

struts.ui.templateDir=template

#sets the default template type. Either ftl, vm, or jsp

struts.ui.templateSuffix=ftl

Struts2会先到我们的WebRoot目录搜索相关ftl文件,如果没有才到自己的包中找。

 

       我们的目标,要使用Struts2UI标签并将错误信息显示在标签的旁边。所以我们修改这两个文件的内容为:

controlheader.ftl

<#--

       Only show message if errors are available.

       This will be done if ActionSupport is used.

-->

<#assign hasFieldErrors = parameters.name?? && fieldErrors?? && fieldErrors[parameters.name]??/>

<#if parameters.labelposition?default("") == 'top'>

    <td align="left" valign="top" colspan="2"><#rt/>

<#else>

    <td class="tdLabel"><#rt/>

</#if>

<#if parameters.label??>

    <label <#t/>

<#if parameters.id??>

        for="${parameters.id?html}" <#t/>

</#if>

<#if hasFieldErrors>

        class="errorLabel"<#t/>

<#else>

        class="label"<#t/>

</#if>

    ><#t/>

<#if parameters.required?default(false) && parameters.requiredposition?default("right") != 'right'>

        <span class="required">${stack.findValue("getText('requiredmark')")}</span><#t/>

</#if>

${parameters.label?html}<#t/>

<#if parameters.required?default(false) && parameters.requiredposition?default("right") == 'right'>

 <span class="required"><@s.text name="requiredmark"></@s.text></span><#t/>

</#if>

${parameters.labelseparator?default(":")?html}<#t/>

<#include "/${parameters.templateDir}/xhtml/tooltip.ftl" />

</label><#t/>

</#if>

    </td><#lt/>

<#-- add the extra row -->

<#if parameters.labelposition?default("") == 'top'>

</tr>

<tr>

</#if>

 

controlfooter.ftl

${parameters.after?if_exists}<#t/>

    </td><#lt/>

<#assign hasFieldErrors = parameters.name?? && fieldErrors?? && fieldErrors[parameters.name]??/>

<#if hasFieldErrors>

    <td ><#rt/>

<#list fieldErrors[parameters.name] as error>

        <span class="errorMessage">${error?html}</span><#t/>

</#list>       

    </td><#lt/>

</#if>

<#--

       if the label position is top,

       then give the label it's own row in the table

-->

<tr>   

</tr>

 

至于为什么这么修改,一看便知,我就不多做解释了。

 

二、Struts2如何使用Freemarker

       Struts2是如何使用Freemarker的?在struts2的核心包中有一个default.properties配置文件,Struts2的默认配置都在这个文件中。有一些配置是开启的有一些配置是关闭的。我们要想打开被关闭的配置可以在struts.xml中,添加<constant name="配置项名" value="配置项值"></constant>元素。

 

       default.properties中有一个struts.freemarker.manager.classname=org.apache.struts2.views.freemarker.FreemarkerManager配置,Struts2是通过FreemarkerManager类来实现对Freemarker的操作的。

 

       通过查看源代码,我们知道通过调用FreemarkerManager类的buildTemplateModel方法生成一个model对象,然后将这个对象放在ValueStack中提供给Freemarker的引擎使用。model中都包含发哪些数据?Freemark的模板信息自然不用说,它还包含RequestApplicationResponse等这些在WEB应用中常用到的对象。具体我就不详细列出了,大家可以查看源代码。我们在上边两个模板文件中使用到的 parameters.name也是存储在model中的。

 

       在此特别提出一个被叫做UIBean的类型,UIBean就是对应Struts2UI标签的对象实体。比如标签有namethemeid等数据,这些都会被封装到UIBean中。Freemarker也正是使用这个东东给我们生成了相应该的页面文件。    

 

三、Struts2中的UI标签

       关于各UI标签的详细使用方式,在此就不做总结了。

 

       在实际开发中有一个重要的问题需要我们解决,比如有一个选择个人喜好的表单。我们需要通过一个Action的方法(likesUI)将喜好列表提供给页面,可以让用户选择。但在应用提交选择进行表单校验时,用户提交的数据不合法,我们需要重新返回到用户选择的界面。此时,我们需要调用 likesUI,获取列表将数据提供给用户选择的界面。

 

       我们可以在Action中添加”<result name="input" type="chain">likesUI</result>”,使其发生错误时直接跳转到likesUI,我们也需要在likesUI中添加一个 名称为inputresult标签,但这个标签的值不能为likesUI,否则会递归调用,直到缓存溢出。我们应将它的值指定为likesUI.jsp页面。但即使指定了这个页面,Struts2的内部实现方式也不会调用likesUI方法从,不会将数据传递给likesUI.jsp页面,而它直接跳转到likesUI.jsp页面。

 

       看来我们不能这么做,通过张老师对源代码的详细解析,我们只需要将likesUIAction中的likesUI的方法命名为input(),并只在likeUIAction中添加”<result name="input">/WEB-INF/pages/user/likesUI.jsp</result>“即可。为什么呢?

 

       在表单校验发生错误并使用 chain进行跳转时,会被chain拦截器给拦截了(ActionChainResult)。然后又会被拦截器validation给拦截了,它再进行表单校验进还是以前的数据,还是会出错然后它就直接跳转到我们指定的页面了。注意配置文件中的validation

<interceptor-ref name="validation">

       <param name="excludeMethods">input,back,cancel,browse</param>

</interceptor-ref>

它忽略请求为 input,back,cancel,browse请求路径。所以我们需要将我们的方法名定义为 input()

 

       我只是泛泛而结,如果想了解Struts2的更多细节请下载老张的视频看吧!

 

       最后送给大家一个Struts2开发用例参考模式图:

clip_image002
       1.用户申请注册,打开注册页面。

       2.用户提交注册申请,表单校验错误。

       3.表单校验错误不要跳转到regUser.jsp页面,而是应该跳转到RegUserUI这个Action方法。

       4.用户提交注册申请,表单校验通过。

       5.表单校验通过,调用RegUser这个Action方法进行注册。

       6.注册成功后,不要跳转到list.jsp页面。而是应该调用ListAction这个Action方法。

       7.ListAction获取所有用户信息后,跳转到list.jsp

 

       一定要记得老张还有一天的Struts2的课程,下一次课程的重点内容应该是Struts2的文件上传与下载,Struts2的防止表单重复提交,Struts2SpringAJAX整合,Struts2的插件。

 

       接下来的课程内容让我等的好久啊——Android!虽然听学习过的同学们说十分简单,但我还是迫不及待的想Android的一睹真容。我想很多人都是这样吧!那就关注我接下来6天课程的总结日志吧!

posted @ 2010-02-25 21:32 長城 阅读(576) | 评论 (0)编辑 收藏

       Struts2第三天。如果老张他喜欢头发,他肯定会把头上的头发有多少根,一根一根的数出来。他搞的太细了!

 

       今天的重点内容是国际化、表单与Action数据交互、表单校验,不多说了开始总结。

 

一、Struts2国际化

       在我们学习WEB基础的时候就讲到了国际化,Struts2中的国际化实现方式与我们之前所学习到的国际化相同。但是Struts2中对国际化做了强化支持!

 

       我们通过在struts.xml文件中加入”<constant name="struts.custom.i18n.resources" value="*.properties"></constant>”为指定全局国际化资源文件。Struts2会根据浏览器设置的语言信息运行对应的国际化文件,如果没找到就根据操作系统的语言查找指定的文件,还是没有,那就使用默认的。我们必须在struts.xml中使用定义在struts-default.xml文件中的defaultStack拦截器堆栈。使用defaultStack我们必须在package中添加extends="struts-default"属性。如果在我们的Action中没有使用任何拦截器,defaultStack默认被使用。如果有使用任何其他拦截器,我们必须手动加入defaultStack拦截器堆栈。Struts2将使用defaultStack拦截器堆栈中的i18n拦截器,为我们提供国际化支持。

 

       引入多个全局资源包的方法是在上面的value属性中添加以”,”分隔的多个资源文件。排在最后的资源包的优先级别最高(如果有重复的资源名称)。那如果有时我想在JSP页面中使用第一个资源包中的资源怎么办?Struts2为我们提供了一个标签“<s:i18n name="first.properties"></s:i18n>”,在标签体内使用到的国际化资源,全以first.properties为先。

 

       我们可以为每个Action指定一个资源包,资源包的名称与Action的名称相同。Struts2的国际化模块会先找与Action对应的资源包,如果没有就找它上一级的资源包,就这样逐级向上。如果直到类所在包的是后一层目录也没找到就使用全局资源。这有什么好处?我们可能会有多个Action使用同一个或多个相同的资源,难道我们要在每个Action对应的资源包里定义它吗?当然不需要,我们只需要把它定义在这几个Action的上级且同一目录即可。

 

       我们如何在JSP页面有使用国际化资源?Struts2tags为我们提供了“<s:text name=""></s:text>”标签,它是专门用来访问国际化资源的。除此之外我们也可以使用“<s:property value=”getText(key)”>”,这个getText()是哪来的?当然是ValueStack中的某个对象的方法喽!是类型为com.opensymphony.xwork2.DefaultTextProvider对象的。Struts2中使用OGNL操作ValueStackContextMapOGNL看到getText(key)时,它会在ValueStack中从上向上反射每一个对象,如果哪一个对象最先具有这个方法,则OGNL就调用这个对象的getText(key)方法。

 

       除了在JSP页面中需要使用到国际化资源,我们在Action中也需要使用国际化资源。此时,我们需要将我们的Action类继承自ActionSupport类,它实现了专门用于操作国际化的接口TextProviderActionSupport还实现了其他非常有用的接口,我们在下面会总结。此后,我们只需要调用getText()方法,即可获得相应的资源信息。我们的Action也可以继承自DefaultTextProvider类,但它默认情况下去搜索全局资源包,不会找Action的资源包。而ActionSUpport正如我们在上面所说,以Action的资源包优先级最高...

 

       我们知道我们可以为国际化资源指定参数,比如“regNameError={0} is invalid.”。我们在JSP页面中可以通过<s:param></s:param>标签来指定,如:

<s:text name=”regNameError”>

       <s:param></s:param>

</s:text>

<s:text name=”getText('regNameError','xxx')”></s:text>。在Action中直接使用getText(“regNameError”,”xxx”)

 

       我们之所以能够如此方便的使用国际化支持,JDK中的java.util.Locale为此做了很大的贡献。目前我们使用国际化操作,无不基于java.util.Locale。因为OGNL的强大,我们也可以在JSP页面中使用java.util.Locale还记得吗?在OGNL中调用XXX类的静态方法或成员的方式,比如调用java.util.LocalegetCountry()<s:property value=”@java.util.Locale@getDefault()”/>

 

二、表单与Action数据交互

       相比Struts1,在Strut2中的一大变化是我们不需要ActionForm了。我们在使用Struts1时,为了操作表单数据,我们需要额外定义一个继承自ActionFormFormBean。然后再将FormBean中的数据CopyBean中。

 

       Struts2是如何实现对表单数据的操作呢?Struts2ValueStack一直发辉着它的作用,ValueStack像是能完成Struts2的在所在操作,上面的国际化也是使用的ValueStack存储的。在Struts2中操作表单数据,我们需要在我们Action定义属性。在Action添加的属性可以是基本数据类型也可以是复合类型。

 

       进行表单与Action数据交互时,我们的Action类无需实现任何接口或继承自任何类。但是,我们必须在struts.xml中使用定义在struts-default.xml文件中的defaultStack拦截器堆栈。使用defaultStack我们必须在package中添加extends="struts-default"属性。如果在我们的Action中没有使用任何拦截器,defaultStack默认被使用。如果有使用任何其他拦截器,我们必须手动加入defaultStack拦截器堆栈。

 

       Struts2正是使用在defaultStack中的params拦截器,来为我们的Action设置属性值。如何使用基本类型属性和复合类型属性与JSP页面交互呢?比如在我们的RegUserAction中有一个User属性和一个字符串型的password2属性。那么我们在JSP页面中应该这样使用:

<s:form action=”RegUserAction”>

    <s:textfield name=”user.name”/>

    <s:textfield name=”user.password”/>

    <s:textfield name=”user.email”/>

    <s:textfield name=”password2”/>

    <s:submit value=”注册”></s:submit>

</s:form>

 

       点击注册按钮后,Struts2正是使用params拦截器将数据设置到RegUserAction的属性中。

 

       因为这些表单字段数据是被保存在ValueStack中,所以我们在JSP页面我们可以使用EL表达试,如:${user.name},也可以使用OGNL表达式,如:<s:property value=”user.name”/>来获取数据。

 

       除此之外,我们可以让Action实现ModelDriven接口,并将User做为它的泛型参数。如果被ModelDriven接管的实体类型中有与我们的Action属性相同的,ModelDriven的优先级高。Struts2会设置ModelDriven接管的实体类型的是属性,而忽略Action的同名属性。但这并不会引起错误,因为我们的数据全部放在ValueStack中,使用OGNL可以正确获取。我们不推荐使用ModelDriven

 

三、表单校验

       表单校验在Struts2中实现比较简单,表单数据的校验分为前台校验和后台校验。同样我们需要开启defaultStack拦截器堆栈,首先我们来看看后台校验。

 

       后台校验,我们的Action可以继承ValidationAwareSupport类和实现Validateable接口。因为我们同时需要在类中使用到国际化表单校验,所以我们可以直接继承ActionSupport类。Action类需要实现validate方法。

 

       validate方法中进行Action的属性校验,并且我们可以调用ActionSupport类的addActionError(String)方法,添加错误信息。我们可以在这里使用国际化支持,而在JSP页面中需要使用<s:fieldError>取出所有错误信息,或者指定字段名而取出某个字段的错误信息。

 

       但有一个问题,一个Action类可以有多个方法分别用于处理不同的请求。Struts2每当调用其中一个方法时都会进行表单校验,这没必要啊!所以我们在不需要进行表单校验的方法上添加“@SkipValiation”注解,这样就会被Struts2过滤掉。

 

       我们也可以添加”ActionClassName-validation.xml”配置文件,来为指定名称的Action(ActionClassName)添加表单校验。具体的配置可以参看struts2包中所带的例子程序。我们也可以使用“ActionClassName-actionname-validation.xml”来为Action类中的某个具体方法指定表单校验。

 

       前台校验,前台校验的好处不再说明了。前提我们以配置文件的方式为Action指定的表单校验,那么在JSP页面中,我们可以直接引用配置文件中的数据,实现前台校验。Struts2中的struts-tags为我们提供的表单标签中可以引用配置文件中对应的校验数据。在我们访问到某个JSP页面时,Struts2的标签会为我们自动生成相应的JavaScript代码,但Struts2的表单前台校验的这种功能还不够强大。在此就不多做总结了。

 

       老张讲得比较细致,我也仅仅是泛泛而总结。按照正常的进程,我们明天还有一天的Struts2课程,但由于时间不够,老张决定哪天同学们休息时再为我们补一天,太好了!

posted @ 2010-02-23 23:39 長城 阅读(531) | 评论 (0)编辑 收藏

     摘要: Struts2第二天,大家似乎没有从年假中苏醒过来,上课显得有些疲惫。不过还好,听课效果还不错。今日的主要内容是OGNL,Struts2使用OGNL访问contextMap和valueStack。老张很执着,他在研究Struts2时遇到的一些问题,一定要解决,并且要详细解决。通过他在讲课中,我们可以看出这一点。有开发经验的人都知道,我们时而被陌生技术的一个小细节搞的晕头转向,耗费了大半天的时间我们...  阅读全文

posted @ 2010-02-22 16:59 長城 阅读(740) | 评论 (0)编辑 收藏

     摘要:          春节假期终于结束了,假期内在北京只出去转了两天,感觉很好!剩余时间呆在屋子里写了个练习程序收获颇丰。          依然迫不及待,迫不及待的学完课程赶紧回大连。我想除了我,很多同学和网友也都期待着今天由张考祥老师主讲的Strut...  阅读全文

posted @ 2010-02-20 23:56 長城 阅读(573) | 评论 (0)编辑 收藏

     摘要:          今日教育办公系统结束。新内容有:导出数据到PDF文档、生成图表(饼图、柱图...),整体上操作比较简单。   一、创建PDF文档          我们使用iText创建PDF文档,需要到http://itext...  阅读全文

posted @ 2010-02-09 01:25 長城 阅读(480) | 评论 (0)编辑 收藏

     摘要:          今日我们已经将权限模块与员工管理整合完毕,但下午有学习新的内容。将数据导出为excel表格,或从excel表格导入数据。这一项功能比较常用!在Windows平台下微软有为我们提供Office的COM套件,Apache为我们提供的poi正是为Java打造的Office套件。    &...  阅读全文

posted @ 2010-02-08 00:30 長城 阅读(382) | 评论 (0)编辑 收藏

spring-security最后一天,今天的主要内容是将需要指定权限才可以访问的资源放到数据库中,脱离applicationContext.xml配置文件。然后我们将近两天学习的srping-security整合到教育办公系统中。


我们继续昨天的内容,将资源文件信息保存到数据库中。



1.applicationContext.xml

将昨天applicationContext.xml“配置SpringSecurityhttp安全服务”部分的内容替换为:

<sec:http auto-config="true" session-fixation-protection="none" />

<bean

class="org.springframework.security.intercept.web.FilterSecurityInterceptor"

autowire="byType">

<sec:custom-filter before="AUTHENTICATION_PROCESSING_FILTER"/>

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

</bean>

这里的objectDefinitionSource是下边的类,cutom-filter是在调用AUTHENTICATION_PROCESSING_FILTER过滤器之前调用FilterSecurityInterceptor


2.添加数据表

resc表与role表是多对多关系。


1).resc

image

2).resc_role

image

3.相关类

要让spring-security可以从数据库中获取相关资源信息,我们必须编写一个实现FactoryBean接口的类。

package cn.itcast.cc.spring.security;


import java.util.LinkedHashMap;

import java.util.Map;

import javax.annotation.Resource;

import org.springframework.beans.factory.FactoryBean;

import org.springframework.security.ConfigAttributeDefinition;

import org.springframework.security.ConfigAttributeEditor;

import org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource;

import org.springframework.security.intercept.web.RequestKey;

import org.springframework.security.util.AntUrlPathMatcher;

import org.springframework.security.util.UrlMatcher;

import org.springframework.stereotype.Component;


@Component("objectDefinitionSource")

public class DefaultFilterInvocationDefinitionSourceImpl implements FactoryBean {


@Resource

ResourceDetailsService resourceDetailsService;


private UrlMatcher getUrlMatcher() {

UrlMatcher urlMatcher = new AntUrlPathMatcher();

return urlMatcher;

}


@Override

public Object getObject() throws Exception {

UrlMatcher urlMatcher = this.getUrlMatcher();

// 获取数据Map

Map<String, String> srcMap = resourceDetailsService.buildRequestMap();

LinkedHashMap<RequestKey, Object> requestMap = new LinkedHashMap<RequestKey, Object>();

ConfigAttributeEditor editor = new ConfigAttributeEditor();

// 转换数据Map

for (Map.Entry<String, String> entry : srcMap.entrySet()) {

String url = entry.getKey();

String roles = entry.getValue();

if (roles != null) {

editor.setAsText(roles);

requestMap.put(new RequestKey(url), editor.getValue());

} else {

requestMap.put(new RequestKey(url), ConfigAttributeDefinition.NO_ATTRIBUTES);

}

}

// 生成并返回对象

return new DefaultFilterInvocationDefinitionSource(urlMatcher,

requestMap);

}


@Override

public Class getObjectType() {

return null;

}


@Override

public boolean isSingleton() {

return false;

}


}


其中ResourceDetailsService接口的实现类如下:

package cn.itcast.cc.spring.security;


import java.util.HashMap;

import java.util.List;

import java.util.Map;

import javax.annotation.Resource;

import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;

import org.springframework.stereotype.Component;


@Component("userDetailsService")

public class ResourceDetailsServiceImpl implements ResourceDetailsService {


@Resource

private SimpleJdbcTemplate jdbcTemplate;

@Override

public Map<String, String> buildRequestMap() {

// 注意:这里需要使用左外连接查询,是因为有些页面没有指定role

// 即,任何权限都不可以访问的页面!

String sql = "SELECT res_string as url,r.name as role " +

"FROME resc LEFT JOIN resc_role rr ON rr.resc_id = resc.id " +

"LEFT JOIN role r ON rr.role_id = r.id";

List<Map<String, Object>> results = this.jdbcTemplate.queryForList(sql);

Map<String, String> srcMap = new HashMap<String, String>();

// 将查询后的数据拼接并放入到Map

for(Map<String,Object> val:results){

String url = (String) val.get("url");

String role = (String) val.get("role");

if(srcMap.containsKey(url)){

role = srcMap.get(url) + "," + role;

}

srcMap.put(url, role);

}

return srcMap;

}

}


Spring-security还为我们提供了其他实用的辅助功能,具体的google一下吧!

posted @ 2010-02-04 23:18 長城 阅读(405) | 评论 (0)编辑 收藏

     摘要:          有没有发现一个问题,我们之前做的所有练习,都没的权限管理这个模块。我们的WEB应用中的同一个帐户可以在多台机器上同时登陆,每一个用户可以操作所有功能模块。这样在以后的应用开发中是结对不可行的!          &nb...  阅读全文

posted @ 2010-02-03 23:52 長城 阅读(2622) | 评论 (0)编辑 收藏

 

        今天重点内容是AJAX技术在教育办公系统中V层的应用,实现的功能有:AJAX分页查询、AJAX删除、AJAX修改。

        还记得学习AJAX时使用JQuery向服务器发送请求,并在回调函数中将返回的数据动态插入到DOM的某处吗?Yes,我们今天主要就是玩这个技术。感觉没什么好总结的,就是叠代码、串代码,没什么新鲜东西。


        但我想说的是看着佟佟搞着代码,操作着页面多少有些恶心。因为我以前是做桌面的组件没这么麻烦,也没这么灵活,但目标都是一样的——显示数据,提供给用户查询或编辑。所以我要思考一个问题,将分页、DAOAJAX操作封装成像桌面软件的组件那样方便易用,其实已经实现了通用分页和DAO。关于页面AJAX并不理想,虽然JQuery有很多插件,但从这两天的内容来看插件的操作并不理想,有时间我要为此多研究研究。

        明天的内容比较有吸引力!哈哈!


 

posted @ 2010-02-02 21:33 長城 阅读(291) | 评论 (0)编辑 收藏

 

         每次学习项目或者新的知识时,都 不能建立宏观的了解。中午或者晚上需要回来整理一下,才能对所学的知识有个宏观的了解(框架的了解)。我们现在做的这个项目,似乎一直学习的是新知识,其实并不是。而是Java的高级用法,它让我感觉到了Java的强悍。


         今日重点通用分页功能,几乎每一个像样些的练习都有分页功能,它如此重要!今天的分页功能是通用的,适用于任何WEB应用。基于昨天的两个工具类,今天新添加了一个HibernateDao 扩展了SimpleHibernateDao。这个DAO除了进行常规的CURD操作,还为我们提供了分页功能和多条件模糊查询功能,用起来更方便。

 

         下面是查询分页信息操作的时序图:


         (如有需要代码的,可以给我留言!)   

 

    项目整体上来说并不难,只要抓住了项目的框架和重点内容。什么才是最难的?自己动手实践才是最难的。来传智播客学习已经三个月了,我一直坚持着整理学习日志,想将每天的学习重点都详细的整理出来,但那根本不现实,因为学习内容太丰富了。我也有动手去实践那些重点的内容,但效果并不另我满意。我想我应该拿出更多的时间去实践,但写日志占用了我大部分时间!

 

         有失必有得,这都是个人的选择。我之所以写日志,是想练习自己对文章框架和知识结构的整理能力。做为一个优秀的程序员,我想这一点是十分重要的。我在这方面得到了一定的提升,别我欣慰。但仍然需要继续努力!说心里话,我的文章结构还差的很,因为没有经过细心整理和校验。

 

         我想我应该灵活的去处理实践与写作的时间,当实践变得重要时就应该拿出大部分时间给实践。当理论性知识重要时,更应该拿出些时间去写日志。嗯,就这么做吧!还有一个月20天课程就结束了!

posted @ 2010-01-31 23:55 長城 阅读(2047) | 评论 (5)编辑 收藏

     摘要:          东西好多啊,我的编写进度是跟不上了。把重点日志好好整理一下!以前编写的练习主要是练习基本功,现今的练习是要是怎么快怎么来。比如分页功能,以前是靠自己手动一点一点的写。而如今一个插件搞定,而且功能十分强大。          ...  阅读全文

posted @ 2010-01-30 23:11 長城 阅读(950) | 评论 (0)编辑 收藏

     摘要: 今天是教育办公系统的第一天,我本以为这个系统是一个全面些,功能强的项目。实际确实如此,功能强大、全面!但我们只需要完成其中的一小部分,核心的部分。其实想想,这么好的一个系统,如果真把它做出来并通过测试,我估计至少需要二个月左右的时间。而我们只有9天的时间,这9天的时间将项目的核心部分学习一下还是相当不错的。 其实在企业开发中,这种规模的项目是不可以由一个人来完成的。所以从这个角度考虑,我...  阅读全文

posted @ 2010-01-30 00:31 長城 阅读(621) | 评论 (0)编辑 收藏

     摘要: 今日的三大主要内容:Spring中的数据库操作事务、Spring整合hibernate、Spring整合Struts1.X,最来再来一个SSH整合。 数据库操作、数据库事务管理、hibernate、Sturts,这些大家都已经十分熟悉了。所以将他们与Spring整合使课程内容比较简单。Spring的特性是什么?不就是IOC的DI和AOP吗!简单在大脑里回顾一下,SSH整合正是使用这些特性。 一...  阅读全文

posted @ 2010-01-28 17:23 長城 阅读(656) | 评论 (0)编辑 收藏

     摘要: 这知识越学越简单了。其实现在学习的Spring和之前学习的Hibernate等框架等,他们的实现都是我们之前学习的Java基础和JavaWeb基础。再加之做了几个总结性的练习,巩固了基础。所以现在学习起来就比较容易了。 今日的课程内容为两部分:Spring中的AOP面向切面编程和Spring对JDBC的支持。   一、Spring-AOP AOP面向切面编程(Aspect-Orie...  阅读全文

posted @ 2010-01-26 22:49 長城 阅读(372) | 评论 (0)编辑 收藏

     摘要: “你用过什么框架?我用过Srping,但不要说成我用过春!”,哈哈。刚开课,佟佟就把大家斗乐了,非常开心。佟佟这称号是同学私底下叫的,比较亲切。他无论在哪个班上课,都可以听到那个班的欢声笑语。 大名鼎鼎的Spring大家都听过,spring是一个开源框架,Spring为简化企业级应用开发而生。使用Spring可以使简单的JavaBean实现以前只有EJB才能实现的功能。Spring是一个DI(依...  阅读全文

posted @ 2010-01-24 23:23 長城 阅读(1013) | 评论 (1)编辑 收藏

今日学习版本管理软件——SVN,我在以前的工作中正是使用SVN做为版本管理的。使团队合作更加轻松、方便、快捷。

 

SVN在当今软件项目开发中占的比重较大,在外国的软件行业中几乎全部使用SVN进行版本管理的。在国内的大中型企业也在使用,可能存在部分小型公司没有使用。

 

在当今开源的世界中SVN的应用屡见不鲜,今日的课程就是学习如何假设SVNCVS服务器,还有SVNCVS的客户端使用。Eclipse的经典更不用说,她真是一个和谐的大家庭!

 

SVNCVS的配置在互联网,或其官网“http://www.subversion.org.cn/ ”已经非常全面细至了。

 

我们平时自己写个项目时,都将代码备份到自己的本地其他逻辑空间中,定期也将代码发到自己的邮箱中备份。但Google为我们提供了免费的代码托管“http://code.google.com/intl/zh-CN/projecthosting/ ”使用起来十分方便!

 

我十分喜欢Google

posted @ 2010-01-23 21:45 長城 阅读(360) | 评论 (0)编辑 收藏

     摘要: EJB3的功能很是强大,但中小企业很少使用它做开发,一般应用SSH足以应付。JAVAEE是做什么的?她是分布式企业级应用的规范,那EJB就是为实现这样的应用而开发的。 什么是分布式应用?听着名字很大。比如咱们的在线支付系统,淘宝、china-pub和amazon等都支持支付宝在线支付。难道它们分别都要将支付宝模块放在自己的服务器上?完全没必要。支付宝模块单独放在一个服务器上,其他服务器使用(调用...  阅读全文

posted @ 2010-01-22 11:40 長城 阅读(344) | 评论 (0)编辑 收藏

     摘要: 今天内容为两个版块JPA与EJB,从学习hibernate、UML到JPA。他们都涉及到一个极为重要的细节——类与类、接口与接口或类与接口之间的四类关联关系。今日上午到下午3点左右内容为JPA中处理这四类关系。我想我应该将他们系统的做一下总结,这项任务就留着后天休息来完成吧! 近三天的课程内容除了带给我知识上的获取和见识的增长,更让我感觉到一种力量!在学习WEB之前,这些互联网的东西让我满头雾水...  阅读全文

posted @ 2010-01-20 23:20 長城 阅读(751) | 评论 (0)编辑 收藏

     摘要: 今后三天的课程内容为:JPA与EJB。我们的班型是JAVAEE精品就业班,我们学习的是JAVAEE吗?JAVAEE是分布式企业级应用,我们之前学习的JSP与Servlet都是JAVAEE的内容,是基础内容。那么JAVAEE的核心是什么?没有学习JAVAEE的核心还算是学习过JAVAEE吗?JAVAEE的核心是EJB! EJB具体是做什么的?目前还不清楚,这部分内容在明天和后天会学习。今日的重点内...  阅读全文

posted @ 2010-01-19 23:46 長城 阅读(578) | 评论 (0)编辑 收藏

UML,是我在整套课程中比较期盼的内容。虽说是对UML的期盼,更是对CMM标准化项目开发的期盼。软件工程的概念是参照建筑工程等流程提出来的,与建筑工程相同,软件工程需要可行性分析、需求分析、概要设计、详细设计...。建筑需要图纸,软件也需要图纸,设计软件图纸的工具就是UML(统一建模语言)。

到传智播客学习,了解和运用软件工程也是我的重要目标之一。因为我受够了没有经过软件工程标准化开发,而直接编码所带来的痛苦。今日的课程内容比较简单,上课的氛围比较轻松。有机会听徐老师谈一谈国内的软件公司现状。CMM是印度人总结出来的被国际公认并普遍使用的软件工程规范,最高等级应该是CMM5。但十分遗憾的是中国的真正意义上的CMM5等级的这种软件企业并不多,为什么?要搞一个CMM5的认证来,与我们社会中想搞一个学位证书的概念差不多。可想这种卑劣的文化!残害着自己的民族。在这个社会里一切都不会超过人情世故。

我对这种标准化的工程流程十分关注,国内在这方面做的比较好的是大连。但大连是中国最大的软件外包产业,几乎全在为日本工作。所以这种CMM5的高层(设计层)都是由日本人来完成的,中国的“打字员”只需要按照日本人设计的详细文档,把代码敲到电脑里并测试通过就可以了。我们知道编码只是软件开发中的一小部分而已,非常惭愧!

不在其位莫思其事!

老徐说给我们提供UML的课程是为了让大家在以后的工作中能看懂UML图。UML的画图工具很简单,难在你用丰富的经验画出优美的软件框架和详细设计来。

一、软件工程

简要学习一下软件工程,软件工程是由软件危机引起的。软件危机就引起了瀑布模型,从瀑布模型又升级出来RUP来。

一幅美丽的用来形容软件工程问题的漫画:

clip_image002[4]

1.瀑布模型

clip_image003[4]

模型的特点是:

1). 各阶段间具有顺序性和依赖性: 后一阶段工作必须在前一阶段工作完成后才能进行。

2). 质量保证机制的依赖性。即每一步都必须循序渐进,及早消除故障隐患,保证本阶段的工作的质量,从而达到保证整体软件质量的目的。

3). 推迟实现原则。前一阶段工作做的越细, 越扎实,后一阶段工作进行的就越顺利,强调”宁慢求好”。因此,各阶段工作总是一拖再拖,致使整个工期推迟实现。显然瀑布模型不能满足呈爆炸状增长的社会应用需求。

2. 统一软件开发过程:RUP(Rational Unified ProcessRUP)

一个通用的软件流程框架, 以架构为中心, 用例驱动的迭代化开发流程。 RUP 是从几千个软件项目的实践经验中总结出来的, 对于实际的项目具有很强的指导意义。RUP 用二维坐标来描述。 横轴通过时间来组织, 是过程展开的生命周期特征, 体现开发过程的动态结构;纵轴以内容来组织, 体现开发过程的静态结构。

clip_image004[4]

有关瀑布模型和RUP的资料网上有很多,在次就不多做总结了。

三、UML

UML(United Modeling Language,统一建模语言):是一种基于面向对象的可视化建模语言。

UML采用了一组形象化的图形(如类图)符号作为建模语言,使用这些符号可以形象地描述系统的各个方面。

UML通过建立图形之间的各种关系(如类与类之间的关系)来描述模型。

UML中有二类图(共10种):

1).静态模型图:描述系统的静态结构

类图、对象图、包图、组件图、部署图

2).动态模型图:描述系统行为的各个方面

用例图、时序图、协作图、状态图、活动图。

其中蓝色为重点图例,其他的图例比较少用。

在画图之前我们有必要复习一下类的四种关系:

u 关联关系(association)

u 依赖关系(dependency)

u 泛化关系(generalization)

u 实现关系(realization)

我们在hibernate中有学习到这四种关系,原本我以为那只是在hibernate中使用。没想到在UML中也有,其实这四种关系应该是软件工程中的规范了。那hiberante也是使用了这种规范进行相关开发的,这样可以促进hibernate路线的正确性,这太好了!

我们使用的是IBM的RationalRoseUML设计工具,使用工具具体图画的操作就不说明了。

1.用例图

用例图(Use Case Diagram): 也称为用户模型图, 是从软件需求分析到最终实现的第一步, 它是从客户的角度来描述系统功能。

用例图包含 3 个基本组件:

1) 参与者(Actor): 与系统打交道的人或其他系统即使用该系统的人或事物。在UML中参与者用人形图标表示。

2) 用例(Use Case): 代表系统的某项完整的功能。在UML中使用一个椭圆来表示。

3) 关系: 定义用例之间的关系:

a) 泛化关系:表示同一业务目的(父用例)的不同技术实现(各个子用例)。 在UML中,用例泛化用一个三角箭头从子用例指向父用例。以下是某购物网站为用户提供不同的支付方式。

b) 包含关系:一个用例可以包含其他用例具有的行为, 并把它包含的用例行为作为自身行为的一部分。 在 UML 中包含关系用虚线箭头加 “<<include>>”, 箭头指向被包含的用例。

c) 扩展关系:如果在完成某个功能的时候偶尔会执行另外一个功能, 则用扩展关系表示。在 UML 中扩展关系用虚线箭头加 “<<extend>>”, 箭头指向被扩展的用例。

clip_image006[4]

蓝线部分为:泛化关系。红线部分为:包含关系。绿线部分为:泛化关系。

2.类图

类图是面向对象系统建模中最常用的图,是定义其他图的基础。

类图主要是用来显示系统中的类, 接口以及它们之间的关系。

类图包含的主要元素有类, 接口和关系。 其中关系有关联关系, 泛化关系, 依赖关系和实现关系。 在类图中也可以包含注释和约束。

这里的关系十分重要,我们来一一看一下。

1). 泛化关系(继承关系):用来表示类与类, 接口与接口之间的继承关系. 泛化关系有时也称为”is a kind of”关系。

clip_image008[4]

2). 实现关系:用来表示类与接口之间的实现关系。

clip_image010[4]

3).依赖关系:比如我们上班需要交通工具,交通工具可以是公交车、私家车、电动车或自行车,步行也可以。这就是一依赖关系,使用某一个对象或对象的方法来完成一种功能。但与它不存在固定对应关系。

clip_image012[4]

4).关联关系:对于两个相对独立的系统,当一个系统的实例与另一个系统的一些特定实例存在固定的对应关系时,这两个系统之间为关联关系。

多对多双向关联,可以自动生成代码哦:

clip_image014[4]

关联关系中有一个难点,上面的图是多对多双向关联。我也可以映射出一对多和多对一的意向关联。但一对多关系中还有聚合关系和组成关系。

聚合关系:是更强形式的关联。强调部分和整体逻辑结构,但不强调生命周期。对应的属性具有get/set方法。例如计算机包含键盘和鼠标,但如果计算机不在了键盘和鼠标可以存。我们也可以为计算机换键盘和鼠标:

clip_image016[4]

UML中组成关系:是更强形式的聚合,不仅强调部分和整体,而且还强调生命周期。仅有get方法。比如人有头和手,如果主体不在了,那么部分肯定也不存在了。也不能更换。

clip_image018[4]

5).导航性:

导航性表示可从源类的任何对象到目标类的一个或多个对象遍历。 即:给定源类的一个对象, 可以得到目标类的所有对象。 可以在关联关系上加上箭头表示导航方向。

只在一个方向上可以导航的关联称为单向关联,用一个带箭头的方向表示; 在两个方向上都可以导航的关联称为双向关联, 用一条没有箭头的实线表示。

clip_image020[4]

3. 时序图

时序图用于描述对象之间的传递消息的时间顺序, 即用例中的行为顺序。

当执行一个用例时, 时序图中的每条消息对应了一个类操作或者引起转换的触发事件。

在 UML 中, 时序图表示为一个二维的关系图, 其中, 纵轴是时间轴, 时间延竖线向下延伸。 横轴代表在协作中各个独立的对象。 当对象存在时, 生命线用一条虚线表示, 消息用从一个对象的生命线到另一个对象的生命线的箭头表示。 箭头以时间的顺序在图中上下排列。

clip_image022[5]

时序图中的基本概念:

对象:时序图中对象使用矩形表示,并且对象名称下有下划线。将对象置于时序图的顶部说明在交互开始时对象就已经存在了。如果对象的位置不在顶部,表示对象是在交互的过程中被创建的。

生命线:生命线是一条垂直的虚线。表示时序图中的对象在一段生命周期内的存在。每个对象底部中心的位置都带有生命线。

消息:两个对象之间的单路通信。从发送方指向接收方。在时序图中很少使用返回消息。

激活:时序图可以描述对象的激活和钝化。激活表示该对象被占用以完成某个任务。钝化指对象处于空闲状态,等待消息。在 UML 中,对象的激活时将对象的生命线拓宽为矩形来表示的。矩形称为计划条或控制期。对象就是在激活条的顶部被激活的。对象在完成自己的工作后被钝化。

对象的创建和销毁:在时序图中, 对象的默认位置是在图的顶部。这说明对象在交互开始之前就已经存在了。如果对象是在交互过程中创建的,那么就应该将对象放到中间部分。如果要撤销一个对象,在其生命线终止点处放置“ X”符号。

5.活动图

活动图就是流程图,但在UML工具中可以加入泳道:

clip_image024[4]

6.状态图

通过建立对象的生存周期模型来描述对象随时间变化的动态行为。比如hibernate中持久化对象的三种状态:临时状态、持久化状态、游离状态。

clip_image026[4]

状态图的基本概念:

状态:用圆角矩形表示。状态名称表示状态的名字,通常用字符串表示。一个状态的名称在状态图所在的上下文中应该是唯一的。

转换:用带箭头的直线表示。一端连着源状态,一端连着目标状态。

初始状态:每个状态图都有一个初始状态。此状态代表状态图的起始位置。初始状态只能作为转换的源,不能作为转换的目标,并且在状态图中只能有一个。初始状态用一个实心圆表示。

终止状态:模型元素的最后状态,是一个状态图的终止点。终止状态在一个状态图中可以有多个。

7.协作图、对象图、包图

不画了,用处不大且非常简单。

8.组件图

组件图用来建立系统中各组件之间的关系,各组件通过功能组织在一起。

Javabean,ejb,jsp都是组件。在UML中,组件使用在左侧有两个小矩形的大矩形来表示。

组件图可以用来设计系统的整体构架:

clip_image028[4]

9.部署图

部署图用来帮助开发者了解软件中的各个组件驻留在什么硬件位置,以及这些硬件之间的交互关系。

节点:用来表示一种硬件,可以是打印机,计算机等。节点的标记符号是一个三维框,在框的左上方包含了节点的名称。

通信关联:节点通过通信关联建立彼此的关系,采用从节点到节点绘制实线来表示关联。

clip_image030[4]

一下子搞出来这么多东西,这么一看UML贯穿软件设计的各个阶段。让人感觉很好!

一定要学好软件工程,努力在工作中总结经验!

posted @ 2010-01-19 00:24 長城 阅读(1039) | 评论 (0)编辑 收藏

     摘要:          前两天我们已经完成了流程定义的管理和表单的定义的管理。今天们将整合这两大模块,使他们形成一个标准的工作流程。            在学习OA项目时,就像学习其他知识一样跟着老师的思路走。有的时候东西讲...  阅读全文

posted @ 2010-01-17 14:03 長城 阅读(734) | 评论 (1)编辑 收藏

     摘要: 来到北京,今天的天气似乎是最好的,希望不要再有降温天气了。今日继续我们的审批流程,今天的内容似乎有点多,同学们需要努力学习哦!   我个人认为今天的内容多,是为因今天加入了测试部分。使用JBPM开发OA系统,说简单些就是将自定义表单数据放到JBPM工作流中流转。我们所需要实现的功能就是,使用户可以向系统中部署自定义工作流,用户可以自己添加自定义表单。我们通过编写通用表单实体,让任何自定义...  阅读全文

posted @ 2010-01-15 23:29 長城 阅读(731) | 评论 (0)编辑 收藏

     摘要: 今日的北京气温回升,昨天是降温。天气的变暖,让大家感觉十分温暖,课上睡意连绵。汤兄弟有发现大家的状况,所以今天拿出了一点时间与大家交流学习方法或技术上的一些问题。授课进度完全在掌握之中。 未来三天的内容,学习使用JBMP解决审批流转这一大模块的需求。今日的课程内容比较简单,但在实际项目中的应用却十分重要。把WEB基础搞的差不多了,这些框架并没什么难的。更多的是应该多使用,多熟悉他们。两大重点内容...  阅读全文

posted @ 2010-01-14 23:58 長城 阅读(626) | 评论 (0)编辑 收藏

     摘要: 今日完成部门(department)和员工(employee)管理,由于昨天已经对增、删、改、查摸了遍,所以今日的内容相对就比较简单了。虽然简单,仍然有需要注意的地方。经验丰富的程序员,编写的代码十分优雅,这也是新人们严重不足的地方,当然我也应该加强这方面的能力。   不过说来也十分无聊,手动编写OA项目已二天了。这两天除了项目的架构与优雅的接口设计让我感觉好些外,其他没有什么让我感觉愉...  阅读全文

posted @ 2010-01-13 15:32 長城 阅读(401) | 评论 (0)编辑 收藏

     摘要: 上一节课我们已经完成了OA项目的基础部分,对DAO和BEAN的基本操作。今日开始学习OA项目中“组织管理”这一部分。在学习的过程中,整体上难度相对比较简单,更多的是项目经验上的学习。但在配置hibernate的映射文件时,大家有些应付不来。我也不例外,一对一映射关系我掌握的不好。但汤兄弟为人正直、善良,他在晚上下课后给我们被了    。   这个项目虽然未详...  阅读全文

posted @ 2010-01-11 23:45 長城 阅读(414) | 评论 (0)编辑 收藏

     摘要: 今日开始进行OA项目了,OA是一个大型的办公自动化管理系统。汤老师使用6天的时间带领我们做这个项目,显然是不可能全部完成的,我们要做其中重点的几个模块。这个项目将对我们之前学习的struts1、hibernate3、jbpm3、jstl1.1、junit4进行综合性的系统练习。   在跟着老师学习新技术时,课堂上我们能很好的理解各知识点。但放到一起,在实际项目中应用时还时感觉有点陌生。不...  阅读全文

posted @ 2010-01-10 10:34 長城 阅读(786) | 评论 (0)编辑 收藏

     摘要: 今日继续讲解jbpm框架,早上汤老师领着大家把昨天的内容复习了一下,然后做了总结。总结之后十分清晰。   一、昨日回顾   1.          部署流程定义:“deployProcessDefinition”向“jbpm_processdefinition” 表中添加新的流程定义记录...  阅读全文

posted @ 2010-01-09 00:03 長城 阅读(1497) | 评论 (0)编辑 收藏