2008年12月29日
最近在学习如何使用maven,做了一个demo(基于S2S整合),总结一下与大家分享,期待与大家讨论以期快速进步。
一、maven介绍
1、maven是什么
http://maven.apache.org/
官方解释:Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。
2、使用maven有什么好处,解决什么问题
jar统一管理了:
如果建立了一个本地的jar仓库,那么所有人都是从仓库里面下载jar,拷贝项目时只需要copy几K的源码即可!其次,依然是仓库,使得每个人的jar版本都是一致的,不会出现因为版本不同,引起的莫名其妙的错误。
项目的自动化:
只需要mvn package命令,在eclipse里面,看run里面,只需要选择就行了!它会自动的从编译,测试开始,一直到打包,自动的运行,保证你的包没有问题。
我们在做多个不同的Java项目时,每个项目所用到的库文件基本都是大同小异的,通常的做法是每个项目下面都会复制一份这些库文件,甚至会把这些库文件都提交到vss上去,这样带来的问题不仅是增大了项目占用的硬盘空间,而且也使包管理很混乱。
我们可以这样查看jar包的依赖关系,是不是很爽?!
还可以单元测试覆盖率报表:
2、helloword
1、下载Maven 附件中的maven3.jar 解压到任意目录
2、安装eclipse插件m2eclipse
方式一:在线安装 更新地址是:http://m2eclipse.sonatype.org/sites/m2e
方式二:本地安装 help-->install new softeware-->add-->name填写maven-->archive..-->jar:file:/../m2e.zip!/-->ok
安装完成重启eclipse,在Window-->Preferences-->Maven下配置
禁用eclipse启动时更新maven index 主要是每次eclipse启动时都更新很烦人
添加自己的maven
3、新建maven项目
按照下图步骤
- groupId定义了项目属于哪个组,这个组往往和项目所在的组织或公司存在关联。譬如在googlecode上建立了一个名为myapp的项目,那么groupId就应该是com.googlecode.myapp.
- artifactId定义了当前Maven项目在组中唯一的ID,groupId为com.googlecode.myapp的例子中,你可能会为不同的子项目(模块)分配artifactId,如myapputil、myappdomain、myappweb等。
- version指定了项目当前的版本——1.0SNAPSHOT。SNAPSHOT意为快照,说明该项目还处于开发中,是不稳定的版本。随着项目的发展,version会不断更新,如升级为1.0、1.1SNAPSHOT、1.1、2.0等。
- name元素声明了一个对于用户更为友好的项目名称
点击Finish完成
4、maven项目结构
下图为基于maven项目结构,这里跟我们以前的项目结构很不一样,以前的项目结构约定俗成的只有两块 一个src 一个webRoot,当然这些都可以随意配置,比如WebRoot有的叫WebContent
这里maven倡导约定优于配置,maven的约定就是以下目录结构
src/main/java 下存放java类
src/main/webapp 下存放页面文件(需要手动创建)
src/main/resources 下存放资源文件
src/test/java 下存放单元测试代码
src/test/resources 下存放测试资源文件
5、添加jar包
只需维护pom.xml
比如添加struts2-core
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.0.11.2</version>
</dependency>
我在172.20.66.230上部署了一个maven仓库,访问地址http://172.20.66.230:8081/nexus/
maven会根据pom.xml中的配置访问230的仓库下载对应的jar source 以及doc,下载到哪?这要看maven3/conf/settings.xml 55:
<localRepository>F:/Maven3/repository</localRepository>
6、编写代码
附件中有一个struts2+spring 的demo,解压然后import eclipse
在项目名上右键 run as -->Run Configurations
按图配置,点击Run即可。浏览器中访问http://localhost:8080/MavenSSH/
Maven运行的生命周期
===========================
-
以上是一个简单的例子,只是用它获取依赖的jar包 。maven还有很多诸如项目管理方面的功能,比如文档编制、发布管理、配置管理...
-
第一个次运行项目会比较慢,因为要下载jar包。
-
MavenSSH.rar是一个struts2与spring集成的例子,页面用到了sitemesh div+css 也值得学习
-
项目debug是运行在jetty(类似于tomcat的容器)中。
如果部署GAE时正在upload files时退出,下次部署时会报错
Another transaction by user is already in progress for this app and major version. That user can undo the transaction with appcfg.py's "rollback" command
找到eclipse中的GAE SDK目录
如:D:\eclipse\plugins\com.google.appengine.eclipse.sdkbundle.1.3.8_1.3.8.v201010161055\appengine-java-sdk-1.3.8\bin
执行命令
appcfg.cmd rollback 后面跟gae项目war所在目录
如 appcfg.cmd rollback D:/spring/eclipse_workspace/taobaoke/war
执行:
********************************************************
Warning: Future versions of the Dev App Server will require Java 1.6 or later. P
lease upgrade your JRE.
********************************************************
Reading application configuration data...
2010-11-15 9:34:23 com.google.apphosting.utils.config.AppEngineWebXmlReader read
AppEngineWebXml
信息: Successfully processed D:/spring/eclipse_workspace/taobaoke/war\WEB-INF/ap
pengine-web.xml
2010-11-15 9:34:23 com.google.apphosting.utils.config.AbstractConfigXmlReader re
adConfigXml
信息: Successfully processed D:/spring/eclipse_workspace/taobaoke/war\WEB-INF/we
b.xml
2010-11-15 9:34:23 com.google.apphosting.utils.config.AbstractConfigXmlReader re
adConfigXml
信息: Successfully processed D:/spring/eclipse_workspace/taobaoke/war\WEB-INF/cr
on.xml
Beginning server interaction for taokeapp...
0% Rolling back the update.
Success.
Cleaning up temporary files...
在网上无意搜到一个用Ext实现的淘宝客,恩 ,咱用GWT做一个车轮
下了淘宝的 SDK for java就开干 参考API文档按部就班
在淘宝的沙箱里测试,很顺利,乘胜前进,到正式环境下测试
问题来了
invalid signature
网上搜了一通,有说时间戳不对,果不其然,GAE使用的是标准时间,整整差了8小时,遂在获得的当前时间上加了8小时,OK
invalid signature 可能的另一个原因是APP_KEY 或 APP_SERCET不正确,仔细检查
调用 taobao.item.get
是
1 TaobaoClient client=new DefaultTaobaoClient(TaobaokeConstant.SANDBOX_URL, TaobaokeConstant.APP_KEY, TaobaokeConstant.APP_SERCET);
2 ItemcatsGetRequest req=new ItemcatsGetRequest();
3 java.util.Calendar c=java.util.Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));
4 c.add(Calendar.HOUR, 8);
5 req.setTimestamp(c.getTime().getTime()) ;
6 req.setParentCid(new Long(0));
7 ItemcatsGetResponse response=client.execute(req);
8 return response.getItemCats();
调用 taobao.taobaoke.items.get
1 TaobaoClient client=new DefaultTaobaoClient(TaobaokeConstant.SANDBOX_URL, TaobaokeConstant.APP_KEY,TaobaokeConstant.APP_SERCET);
2 TaobaokeItemsGetRequest req=new TaobaokeItemsGetRequest();
3 req.setFields("num_iid,title,nick,pic_url,price,click_url,commission,commission_rate,commission_num,commission_volume,shop_click_url,seller_credit_score,item_location,volume,taobaoke_cat_click_url,keyword_click_url");
4 req.setCid(Long.parseLong(cid));
5 req.setNick(TaobaokeConstant.NICK);
6 req.setSort("commissionRate_desc");
7 TaobaokeItemsGetResponse response=client.execute(req);
8 return response.getTaobaokeItems();
没找到原因
改用自己写的缓存,然后用App Engine Cron 服务管理缓存
corn.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <cronentries>
3 <cron>
4 <url>/cron/recache</url>
5 <description>Repopulate the cache every 1 hours</description>
6 <schedule>every 1 hours</schedule>
7 </cron>
8 </cronentries>
摘要: 01 var $j = jQuery.noConflict();
02 //使用此方法验证所有text textarea 是否含有非法字符
03 $j(document).ready(function(){
04 $j("input[type='text']").each(functio...
阅读全文
一个喜欢coding的程序员,工作在北京,从事java web 开发,喜欢JavaScript,平时关注技术新闻,试用各种新框架、新语言,学海无涯,有时也迷茫
平时没事翻翻编程思想、浏览各位同行的blog,将各种实际中的技巧、方法拿来养眼,并用到自己的项目中感受快乐
头儿的评价:不管遇到什么难题,都会钻窟窿盗洞把它解决掉
求职简历
Compiling module com.capinfo.cdss.gwt.olap.Olap
Compiling 12 permutations
Compiling permutation 0...
Compiling permutation 1...
Compiling permutation 2...
Compiling permutation 3...
Compiling permutation 4...
Compiling permutation 5...
Compiling permutation 6...
Compiling permutation 7...
Compiling permutation 8...
Compiling permutation 9...
Compiling permutation 10...
Compiling permutation 11...
Compile of permutations succeeded
Linking into D:\spring\workspace\fusionchart\war\olap.
Link succeeded
Compilation succeeded -- 291.925s
在#.gwt.xml中添加支持Firefox
<!-- User Agent -->
<set-property name="user.agent" value="gecko1_8" />
编译的确变得很快,但IE中果真不好使
GWT设置UncaughtExceptionHandler 以捕获为捕捉的异常,这gwt在host mode编译后的JavaScript如果出现错误,No errors in Hosted Mode and Compiled localy, but deployed to tomcat yields in errors
这是恼人,加上UncaughtExceptionHandler起码有一丝线索
|
GWT.setUncaughtExceptionHandler(new GWT.UncaughtExceptionHandler() {
public void onUncaughtException(Throwable throwable) {
String text = "Uncaught exception: ";
while (throwable != null) {
StackTraceElement[] stackTraceElements = throwable
.getStackTrace();
text += throwable.toString() + "\n";
for (int i = 0; i < stackTraceElements.length; i++) {
text += " at " + stackTraceElements[i] + "\n";
}
throwable = throwable.getCause();
if (throwable != null) {
text += "Caused by: ";
}
}
System.err.print(text);
text = text.replaceAll(" ", " ");
Window.alert("系统错误:"+text);
}
});
java.lang.IllegalStateException:Should only call onDetach when the widget is attached to the browser's document
这个异常是在com.google.gwt.user.client.ui.Widget protected void onDetach() 方法抛出的
当页面重新加载或离开页面时会执行这个方法
如果系统没有正常初始化,会有这个异常
郁闷的是No errors in Dev Mode but Compiled localy and deployed to tomcat in errors
|
private void showWaitMess(Frame window){
final MessageBox box = MessageBox.wait("等待", "正在查询数据,请稍后...", "查询中...");
final Element frame = window.getElement();
final Timer t = new Timer() {
@Override
public void run() {
if (ready(frame)) {
this.cancel();
box.close();
}
}
};
t.scheduleRepeating(100);
}
private native boolean ready(Element frame)/*-{
return frame.contentWindow.document.readyState=="complete";
}-*/;
又涨见识了
IE8报下面错误,而且是我的机器不报,同事的机器报,试了4台,两个报,两个不报,IE版本都一样,没想明白
解决:1、查看是否有未关闭的html标签,比如<table>而没有</table> (我就是这个原因)
2、是否在页面未加载完前js代码操作了body里的元素,将相关js代码移到</body>后面
网页错误详细信息
用户代理: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)
时间戳: Wed, 14 Apr 2010 08:33:56 UTC
消息: HTML Parsing Error: Unable to modify the parent container element before the child element is closed (KB927917)
行: 0
字符: 0
代码: 0
URI:
http://support.microsoft.com/kb/927917
|
本来系统是由JSP+润乾报表做的,做出一版来给人家客户演示,人家觉得体验不够,也没不够绚丽,要求回去返工,主要是因为他们看过他们兄弟部门的一个类似系统,要求向那个系统靠拢,可殊不知人家那是.net做的C/S,交互体验当然好了。
面临一个抉择,换.net平台做winform,然后用sql server Analysis Services 的现成组件,这要技术上肯定可行,但是需要购买一堆微软的东西,钱啊。
正好以前看过一些GWT的资料,以及基于GWT的开源框架,它的界面效果倒是可以满足客户的要求,遂毛遂自荐,想试试用GXT实验是否能实现要求的功能和效果,同时也有其他同事考察了SAP的BI,水晶E表,IBM的Cognos,结果因功能实现不够或者商务问题搁浅
好像春节后没多久就开始搞GWT,现在终于实现了(或是变相实现了)要求的功能、满足了客户的意见,很有成就感,期间经历了两次重构,现在采用的GXT提供的MVC模型,底层数据访问是通过调用润乾报表API,将润乾报表运算结果转化为一个List,然后交给GXT在页面展现。
页面功能上,GXT挺全面,Grid列排序,隐藏显示特定列,树形展开收缩,用open chart封装的统计图表,数据钻取,列标题分组,拖拽形式动态设置列维度、行维度以实现灵活查询,将灵活查询行列维度保存起来供以后随时打开,将结果到处Excel、PDF、Word,动态设置查询条件的显示隐藏,动态的进度条提示等等
接下来还要融入GIS,实现报表到地图,地图到报表。
值得注意的是所有这些功能都是在一个窗口中完成的,实现了菜单、维度定义、报表、统计图功能的融合,不用客户点来点去,一步了然。
|
OLAP(On_line Analytical Processing联机分析处理) 和 OLTP(On_line Transaction Processing联机事务处理)
OLTP:On_line Transaction Processing 联机事务处理 ,以业务处理为主
OLAP:On_line Analytical Processing 联机分析处理,则是专门为支持复杂的分析操作而设计的,侧重于对决策人员和高层管理人员的决策支持
因为客户不满意界面设计,人家看中了兄弟单位用的系统的样子,可他却不知那时cs程序,要想用bs做成那样的效果还是先天不足,就这样开始了GWT GXT的探索,一边摸索一边用GXT重写这个系统
现在想想 经历了三个阶段
刚开始是demo阶段,因为不知道路走不走的通,全面摸索GXT能实现的效果,也没注意模块的规划,甚至就一个类
而后发现还是能走通的,就开始添砖加瓦,发现代码越加越乱,决心重构,定义了多个包,多个类负责不同的功能模块,定义了一些Panel,一下子清晰多了,也遇到了不同模块间互相调用的问题,自己想当然的办法就是在一个类中声明每个模块作为属性,就像一个总管,每个屋子的钥匙我都有了,也认识到了这样的缺点,一些模块中的事件不等不在这个主管中定义
现在Now,用一天时间再次改写,仿照Gxt中的例子Explorer
1、将各个模块定义成com.extjs.gxt.ui.client.mvc.View,View中必须实现方法handleEvent(AppEvent event),负责处理发给自己的事件
2、为每个View定义com.extjs.gxt.ui.client.mvc.Controller,每个Controller中包含View,在这里定义View要处理的事件
3、在Dispatcher中注册每个Controller
这样,每个View各司其职,他们各自有各自的功能,会接收为他们定义的所有事件并处理,发送事件Dispatcher.forwardEvent(appEvent);
感觉这次改写后 速度还没有改写前的快,现在每次操作url会自动添加Hash,想把它去掉,一直没找到根结
Gwt中调用panel的setUrl方法嵌入一个网页
在网页加载过程中加入wait
在页面中加入javascript
var ready = false;
$j(document).ready(function(){
ready = true;
});//这里用了jquery
然后再java中声明
public native boolean ready(Element frame)/*-{
return frame.contentWindow.ready?true:false;
}-*/;
然后在设置Frame的url时
olapFrame = centerCp.setUrl(GWT.getHostPageBaseURL()
+ com.google.gwt.http.client.URL.encode("jsp/showOlap.jsp?dim="
+ dims + "&dimname=" + colLabels + ""));
final MessageBox box = MessageBox.wait("等待", "正在查询数据,请稍后...", "查询中...");
final Element frame = olapFrame.getElement();
final Timer t = new Timer() {
@Override
public void run() {
if (ready(frame)) {
this.cancel();
box.close();
}
}
};
t.scheduleRepeating(100);
|
organize imports应该是ctrl+shift+o的操作
add import导入指定的类
organize imports导入所有需要导入的类,并且如果有些import是没用的,那么eclipse会自动删除
Gwt中调用panel的setUrl方法嵌入一个网页
在网页加载过程中加入wait
在页面中加入javascript
var ready = false;
$j(document).ready(function(){
ready = true;
});//这里用了jquery
然后再java中声明
public native boolean ready(Element frame)/*-{
return frame.contentWindow.ready?true:false;
}-*/;
然后在设置Frame的url时
olapFrame = centerCp.setUrl(GWT.getHostPageBaseURL()
+ com.google.gwt.http.client.URL.encode("jsp/showOlap.jsp?dim="
+ dims + "&dimname=" + colLabels + ""));
final MessageBox box = MessageBox.wait("等待", "正在查询数据,请稍后...", "查询中...");
final Element frame = olapFrame.getElement();
final Timer t = new Timer() {
@Override
public void run() {
if (ready(frame)) {
this.cancel();
box.close();
}
}
};
t.scheduleRepeating(100);
javascript 调用java代码
//调用JAVA静态方法
//规则: @全路径类名::静态方法名(方法签名)(传入参数)
//@com.capinfo.cdss.gwt.olap.client.ui.PartOlapCenterTab::saveOlapState
(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava
/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)
(saveName,dims,rowDims,colDims,sql,colLabels,expandInfo,hideInfo,exp,field,remark);
//调用JAVA非静态方法
//规则:实例对象.@全路径类名::方法名(方法签名)(传入参数)
//this.@com.capinfo.cdss.gwt.olap.client.ui.PartOlapCenterTab::saveOlapState
(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava
/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)
(saveName,dims,rowDims,colDims,sql,colLabels,expandInfo,hideInfo,exp,field,remark);
//调用JAVA的非静态属性
//规则:实例对象.@全路径类名::属性名
//var field=this.@com.capinfo.cdss.gwt.olap.client.ui.PartOlapCenterTab::field;
参考:http://java.sun.com/j2se/1.4.2/docs/guide/jni/spec/types.html#wp16432
http://yonglin4605.javaeye.com/blog/568045
http://yonglin4605.javaeye.com/blog/564829
在*.gwt.xml中加入 显示中文
<inherits name="com.google.gwt.i18n.I18N"/>
<extend-property name="locale" values="zh" />
在页面中加入
<meta name="gwt:property" content="locale=zh" >
调用panel的setUrl方法嵌入一个网页
要访问这个网页中的js变量 var abc
setUrl返回一个Frame
public native void jsGetVar(Element element)/*-{
var abc = element.contentWindow.abc;
//element.contentWindow.document.getElementById("name");访问element
}-*/;
调用 jsGetVar(frame.getElement());
参考:http://tailorcai.javaeye.com/blog/186897
在网上搜索了很多部署gwt到tomcat的blog,吸取了大家的经验,又发现一些问题,总结一下
我是用的Google Plugin for Eclipse ,跟用gwt的sdk编译有点点不一样
1、在gwt项目右键Google > GWT Compile,就会在项目中的war中得到编译后的文件
To run the application as JavaScript in what GWT calls "production mode", compile the application by right-
clicking the project and choosing Google > GWT Compile.
参考:http://code.google.com/webtoolkit/usingeclipse.html#compiling
2、将war中这些文件复制到tomcat webapp/应用 目录下
看一下WEB-INF\classes是不是有相应的class文件,要是没有用eclipse编译后复制过来
3、这样就需要gwt-user.jar了
url中也不需要?gwt.codesvr=172.20.66.140:9997这样的参数了
4、打开tomcat访问相应html可能什么都出不来,或者访问数据库时出错,查看gwt编译时控制台输出,是不是跟web.xml中配的
Servlet mapping是不是对应,
比如
Linking into D:\spring\workspace\fusionchart\war\olap.
Link succeeded
Compilation succeeded -- 92.640s
我的web.xml原来是
<servlet-mapping>
<servlet-name>olap</servlet-name>
<url-pattern>/com.capinfo.cdss.gwt.olap.Olap/olap</url-pattern>
</servlet-mapping>
要改成
<servlet-mapping>
<servlet-name>olap</servlet-name>
<url-pattern>/olap/olap</url-pattern>
</servlet-mapping>
相应html中原来是
<script type="text/javascript" language="javascript" src="com.capinfo.cdss.gwt.olap.Olap/com.capinfo.cdss.gwt.olap.Olap.nocache.js"></script>
改成
<script type="text/javascript" language="javascript" src="olap/olap.nocache.js"></script>
还没闹清楚为什么会这样
跟eclipse自动编译有关?高人告知啊
ext-gwt 设置日期格式
DateField date = new DateField();
date.setPropertyEditor(new DateTimePropertyEditor("yyyy-MM-dd"));
如果要去掉此提示,打开SQL 2008 在最上面
工具-〉选项-〉左侧有个 设计器-〉表设计器和数据库设计器 -> 阻止保存要求重新创建表的更改(右侧) 把钩去即可
参考:http://www.cnblogs.com/ajayumi/archive/2009/04/08/1431429.html
连接Sql Azure
微软早就公布Sql Azure可以使用了,今天切身体验了一下,方法看下面链接
http://blogs.msdn.com/sqlcrd/archive/2009/12/28/sql-azure.aspx
测试asp.net连接时,启动项目报错:
Windows Azure Tools: Failed to initialize the Development Storage service. Unable to start Development Storage.
Failed to start Development Storage: the SQL Server instance ‘localhost\SQLExpress’ could not be found. Please configure the SQL Server instance for Development Storage using the ‘DSInit’ utility in the Windows Azure SDK.
解决方法:
go to the "Windows Azure SDK Command Prompt"
执行:
DSInit /sqlInstance:. /forceCreate
再次重新启动,惊喜,报一堆这样的错误:
命名空间“http://schemas.microsoft.com/developer/msbuild/2003”中的“PropertyGroup”。 的子元素
命名空间“http://schemas.microsoft.com/developer/msbuild/2003”中的“ServiceHostingSDKInstallDir”。
无效。应为可能元素的列表: 命名空间“http://schemas.microsoft.com/developer/msbuild/2003”中的“Property”。。
C:\Program Files\MSBuild\Microsoft\Cloud Service\v1.0\Microsoft.CloudService.targets 9 6 杂项文件
闹了半天是因为刚才
开着"Windows Azure SDK Command Prompt"
关了就OK了
今天上班发现访问公司局域网里的计算机共享不好使了,输入正确的用户名密码,也提示不正确,差点就还原系统了,最后Google到了方法: WIN7电脑上开始 search 输入sec , 打开local security policy, 找到security settings\local policies\Network Security: LAN Manager authentication level, the default vaule 是 not defined. 改为"Send NTLM response only"后即可. 参考:http://bbs.pcbeta.com/thread-511161-1-1.html
http://www.infzm.com/content/39708
一直比较喜欢南方周末,不像一些报纸媒体报喜不报忧,想南方为追求事实真相的记者致敬!!!
另发句牢骚:对北京的除雪工作甚是不满,要政府干啥吃的
余年已七十有余,一朝怛化,揆诸生寄
死归之理,一切无所 萦怀,惟我瞻四方,蹙国万里,民穷财尽,实所痛心,生平不喜多言,往日曲突徒薪之谋,国人或不尽省记,今则本识途之验,为将死之鸣,愿我国人静听而力行 焉!则余生虽死犹生,九原瞑目矣。国虽微弱,必有复兴直道,亦至简单。
勿因我见而轻起政争,勿尚空谈而不顾实践,勿兴不急之务而浪用民财,勿信过激言行之说而自摇邦本。讲外交者,勿忘巩固国防;司教育者,勿忘
保存国粹;治家者,勿弃国有之礼教;求学者,勿鹜时尚之纷华。
本此八勿,以应万有,所谓自力更生者在此,转弱为强者亦在此矣。余生平不事生产,后人宜体我乐道安贫之意,丧葬力崇节简,殓以居士服,毋以荤腥馈祭。
好一个
勿兴不急之务而浪用民财
引自:时寒冰 -- 腾讯博客 http://shihanbing.qzone.qq.com
java.lang.InstantiationException
在Struts creating form bean的时候遇到这个异常
在form bean 中加一个无参的构造函数就Ok了
惊闻诸如赶集网\263这类网站上的租房信息都被中介代理买断了,只有他们能看到,天理何在阿
在这发一个,气死我了
自己的房子出租
房屋信息:出租西三旗桥东南角常秀家园南北通透三居住房一套,面积80平米,6层的6层。三室为正规三室无隔断,主卧朝阳20平左右,有阳台,2次卧朝北面积10平左右。
房屋装修为中装,新刷白墙,房间整洁干净,设施齐全。天然气入户,电热水器,上网方便。
房屋周边信息:小区周边交通设施方便,有二十几趟公交车,下楼小区门口就有运通103、运通109、运通118三趟公交始发。
离小区步行5分钟的公交站有919、307、315、345、379、393、398、407、618、625、670、629、753、810、819、运通117等N趟四通八达
的公交车,其中的919大站快车,919区间等八达岭高速的直达车,在上班高峰时间直达三环马甸只需不到半小时时间。919大站
快车一站直达起家豁子(换乘10号线地铁)3站德胜门站(换乘地铁2号线)。小区离13号线城铁龙泽站仅2站地公交。周边商业圈发达并正在迅速崛起中,购物及吃饭都很方便
,京客隆、超市发、肯德基、烤鸭店、老家肉饼、苏宁电器、购物中心、24小时药店……环绕周边应有尽有。
出租条件:房屋觅有正当职业,无不良嗜好的有为青年出租,希望生活习惯良好,收入稳定,长期出租,可整租也可单租,全天看房。中介勿扰,谢谢~
联系方式:13810428318 QQ 122088025
做编程的劳苦兄弟优惠
这有图
http://beijing.koubei.com/fang/detail-rent-r38c4e1aede9546588a7150079255ec2d.html
request.getInputStream() 和 request.getReader()不能同时调用,否则会引发java.lang.IllegalStateException异常。
API中有写:
getInputStream
public ServletInputStream getInputStream()
throws java.io.IOException
- Retrieves the body of the request as binary data using a
ServletInputStream
. Either this method or getReader()
may be called to read the body, not both.
-
- Returns:
- a
ServletInputStream
object containing the body of the request
- Throws:
java.lang.IllegalStateException
- if the getReader()
method has already been called for this request
java.io.IOException
- if an input or output exception occurred
eclipse中如果选中一个变量,则在本源文件中高亮显示相同的变量
Window->Preferences,在type filter text 中输入Mark Occurrences
在Java-Editor-Mark Occurrences中将Mark occurrences of the selected element in the current file.选中OK即可
|
下午头儿出去了,这周一口气粘帖复制了14个Action20个jsp,没什么技术含量,完全是粘帖复制,我在等待什么?
|
工作快三年了,一直没有用到spring,做的几个项目全部基于struts+hibernate,昨天忙完手头的活儿,自己建了个struts+spring+hibernate的demo,能用MyEclipse自动生成的全部自动生成,表映射、pojo、SessionFactory、applicationContext.xml、struts-config.xml都自动生成了,弄了两个jsp,一个add,一个view
运行发现,spring未被加载,原因找来找去找不到,最后还是看了以前写的一篇blog,可能存在重复jar包,有冲突,确实发现Myeclipse自动键入的jar包好多好多,而且有的有重复,捣鼓出以前做的例子,复制lib里面的jar包,果然OK了,实现了增查。
spring确实是个好东西,强大、强大。
Google SSH整合的例子,发现都是Struts2SpringHibernate了,俺还struts1呢,out了
转自:http://pengjiayou.com/blog/fedora-10-auto-install-scripts
easyLife 是另一款和 autoten 类似的软件,是刚刚才发现的,不过其官方网站打不开,需翻墙解决,我找到了它的下载页面,在 sf.net 上,请直接点击这里下载最新的 easylife-1.1-1.fc10.noarch.rpm 。
easyLife 允许你配置 Fedora 10 的各软件,只需用鼠标点击就搞定了!它的主要特性如下:
- 为你系统中的常规用户添加 sudo 命令
- 自动安装 Flash Player 插件
- 安装各种 Codecs (视频、音频解码库等)
- 安装额外字体
- 安装 Livna 软件仓库以安装其它额外及非免费软件
- 安装 Skype
- 为 Firefox 安装 Sun Java 和 Sun Java Plugin 插件
- 用 system-switch-java 整合 Sun Java
- 安装 Adobe Raeder
- 安装其他软件等
用esayLife安装来Flash Player 挺好用,真的是省了很多事,可能对我这个Linux初学者不是啥好事
google app engine对String长度有限制,里面中有个com.google.appengine.api.datastore.Text类型以替换长String,但是换了com.google.appengine.api.datastore.Text后不能向数据库保存了,就单单这个字段不能保存,看数据库列中就没有这个字段,google中找到 说要在字段前加@Enumerated,但是在我这也不好使,后来又找到要加
@Persistent(serialized="true", defaultFetchGroup="true")
private Text text;
// private String text;
恩,这下好使了
开发中遇到这个异常:
NestedThrowablesStackTrace:
Attempt was made to manually set the id component of a Key primary key.
If you want to control the value of the primary key, set the name
component instead.
org.datanucleus.exceptions.NucleusUserException: Attempt was made to
manually set the id component of a Key primary key. If you want to
control the value of the primary key, set the name component instead.
原来的修改代码是这样些的:
public void attachDirty(UrlTarget instance) {
PersistenceManager pm = null;
try {
pm = PMF.get().getPersistenceManager();
UrlTarget ut = (UrlTarget) pm.getObjectById(UrlTarget.class, instance.getId());
ut.setName(instance.getName());
ut.setRemark(instance.getRemark());
ut.setUrl(instance.getUrl());
pm.makePersistent(ut);
} catch(Exception ex){
ex.printStackTrace();
}finally {
if(pm != null)pm.close();
}
}
public UrlTarget findById(Long id) {
PersistenceManager pm = PMF.get().getPersistenceManager();
try{
return (UrlTarget) pm.getObjectById(UrlTarget.class, id);
}catch(Exception ex){
ex.printStackTrace();
}finally {
pm.close();
}
return null;
}
在利用findById方法得到对象后修改,但是findById中pm已经关闭,这就是错误的原因了
来自http://net.zdnet.com.cn/network_security_zone/2008/0519/869835.shtml
一.简介
vi是unix世界中最通用的全屏编辑器,linux中是用的是vi的加强版vim,vim同vi完全兼容,vi就是"visual
interface"的缩写。它可以执行输出、删除、查找、替换、块操作等众多文本操作,而且用户可以根据自己的需要对其进行定制,这是其它编辑程序所没
有的。
vi不是一个排版程序,它不象Word或WPS那样可以对字体、格式、段落等其他属性进行编排,它只是一个文本编辑程序。
vi没有菜单,只有命令,且命令繁多。只要在命令行上键入vi就可进入vi的编辑环境。vi有三种状态:命令模式,文本输入模式和末行模式。键入vi回车后首先进入vi的命令模式。
在命令模式下用户输入的任何字符都被Vi当作命令加以解释执行,如果用户要将输入的字符当作是文本内容时,则首先应将Vi的工作模式从命令模式切换到文
本输入模式。在命令模式下,按一下"a"("A")键或者”i”
("I")或者"o"("O")键,即进入插入态文本输入模式。按"a"键,插入到当前光标的后面;按"i"键,在当前光标处插入;按"A"键,在当前光
标所在行的最后插入;按"I"键,在当前光标所在行的开头插入。在文本输入模式下,按Esc键,即回到命令模式。
末行模式也称ex转义模式。Vi有一个专门的“转义”命令,可访问很多面向行的Ex命令。在命令模式下,用户按“:”键即可进入末行模式下,此时Vi会
在显示窗口的最后一行(通常也是屏幕的最后一行)显示一个“:”作为末行模式的提示符,等待用户输入命令。多数文件管理命令都是在此模式下执行的(如把编
辑缓冲区的内容写到文件中等)。末行命令执行完后,Vi自动回到命令模式。
例如:
:1,$s /A/a/g
则从文件第一行至文件尾将大写A全部替换成小写a。
若在末行模式下输入命令过程中想转换的到命令模式,可按键,或用退格键将输入的命令全部删除之后,再按一下退格键,即可使Vi回到命令模式下。
如果要从命令模式转换到编辑模式,可以键入命令a或者i;如果需要从文本模式返回,则按Esc键即可。在命令模式下输入“:”即可切换到末行模式,然后输入命令。
Vi中的许多命令都要用到行号及行数等数值。若编辑的文件较大时,自己去数是非常不方便的。为此Vi提供了给文本加行号的功能。这些行号显示在屏幕的左
边,而相应行的内容则显示在行号之后。 需要说明的是,这里加的行号只是显示给用户看的,它们并不是文件内容的一部分。
当用Vi建立一个新文件时,在进入Vi的命令中也可以不给出文件名,当编辑完文件需要保存数据时,再由用户指定文件名。
进入Vi时,用户不仅可以指定一个待编辑的文件名,而且还有许多附加操作。如果希望在进入Vi之后,光标处于文件中特定的某行上,可在Vi后加上任选
项+n,其中n为指定的行数。例如 键入命令:vi +3 example.txt后,光标将位于文件example.txt中的第3行上。
二.vi常用的命令
1.插入(Insert)命令
Vi提供了两个插入命令:i 和 I命令
(1)i命令
插入文本从光标所在位置前开始,并且插入过程中可以使用键删除错误的输入。此时Vi处于插入状态,屏幕最下行显示“--INSERT--”(插入)字样。
例1,有一正在编辑的文件,如下所示:
Welcome to vi world!Come on!
~
~
光标位于第一个“!”上,需在其前面插入:
This is an example!
使用i命令,并输入相应文本后,屏幕显示如下:
Welcome to vi world This is an example!!Come on!
~
~
由此例可以看到,光标本来是在第一个“!”处,但是由于是从光标所在位置前开始插入,所以这个“!”就被挤到了新插入的文本之后。
(2)I命令
该命令是将光标移到当前行的行首,然后在其前插入文本.
2.光标移动操作在屏幕上移动
全屏幕文本编辑器中,光标的移动操作无疑是最经常使用的操作了。用户只有熟练地使用移动光标的这些命令,才能迅速准确地到达所期望的位置处进行编辑。
Vi中的光标移动既可以在命令模式下,也可以在文本输入模式下,但操作的方法不尽相同。
(1)在文本输入模式下,可直接使用键盘上的四个方向键移动光标。
(2)在命令模式下,有很多移动光标的方法。不但可以使用四个方向键来移动光标,还可以用h、j、k、l这四个键代替四个方向键来移动光标,这样可以避免
由于不同机器上的不同键盘定义所带来的矛盾,而且使用熟练后可以手不离开字母键盘位置就能完成所有操作,从而提高工作效率。
3.在屏幕上移动
Vi提供了三个关于光标在全屏幕上移动并且文件本身不发生滚动的命令。它们分别是H、M和L命令。
(1)H命令
该命令将光标移至屏幕首行的行首(即左上角),也就是当前屏幕的第一行,而不是整个文件的第一行。利用此命令可以快速将光标移至屏幕顶部。若在H命令之前
加上数字n,则将光标移至第n行的行首。值得一提的是,使用命令dH将会删除从光标当前所在行至所显示屏幕首行的全部内容。
(2)M命令
该命令将光标移至屏幕显示文件的中间行的行首。即如果当前屏幕已经充满,则移动到整个屏幕的中间行;如果并未充满,则移动到文本的那些行的中间行。利用此
命令可以快速地将光标从屏幕的任意位置移至屏幕显示文件的中间行的行首。例如,在上面屏幕显示的情况下(不论光标在屏幕的何处),在命令模式下,输入命令
M之后,光标都将移到add这一行的字母a上。同样值得一提的是,使用命令dM将会删除从光标当前所在行至屏幕显示文件的中间行的全部内容。
(3)L命令
当文件显示内容超过一屏时,该命令将光标移至屏幕上的最底行的行首;当文件显示内容不足一屏时,该命令将光标移至文件的最后一行的行首。可见,利用此命令
可以快速准确地将光标移至屏幕底部或文件的最后一行。若在L命令之前加上数字n,则将光标移至从屏幕底部算起第n行的行首。同样值得一提的是,使用命令
dL将会删除从光标当前行至屏幕底行的全部内容。
4.编辑命令
让我们看看最简单也是最常用的编辑过程:没有人不犯错误。所以迟早你会碰到修改你输入的文本的时候。实际上花在字处理上的大多数时间是修改而不是输入新的东西。因此,你要知道如何方便地修改就很重要。
(1)x--删除一个字符
删除文字的最简单的方式是用x。这个命令的结果是光标所处的字符的消失,后面的文字左移动。如果你删除的字符是一行最后的一个字符,那么光标将向左移动一个,这样光标就不会停留在不存在的字符的下面了。假如没有任何文字了,喇叭就叫。
(2)d--删除对象
这个命令的右边还要有一定的文字对象。文字对象就是一块文字。他右边接的就是在控制光标移动的那些字符。例如 w 表示向前一个单词,那么 dw 将删除下一个单词。5w 表示前进5个单词,那么 d5w 将删除他们。
(3)dd--删除一行
最常用的 d 系列命令之一。和前面一样, 5dd 将删除 5 行
(4)D--整个删除
大写形式的 D 用来删除从光标到行尾。和 d$ 一样效果。
(5)u--恢复
要后悔吗?他不仅仅撤消删除,还撤消你所有的编辑工作。
(6).--重复
重复编辑工作。
5.退出Vi
当编辑完文件,准备退出Vi返回到shell时,可以使用以下几种方法之一。
(1)在命令模式中,连按两次大写字母Z,若当前编辑的文件曾被修改过,则Vi保存该文件后退出,返回到shell;若当前编辑的文件没被修改过,则Vi直接退出, 返回到shell。
(2)在末行模式下,输入命令 :w Vi保存当前编辑文件,但并不退出,而是继续等待用户输入命令。在使用w命令时,可以再给编辑文件起一个新的文件名。
例如:w newfile
此时Vi将把当前文件的内容保存到指定的newfile中,而原有文件保持不变。若newfile是一个已存在的文件,则Vi在显示窗口的状态行给出提示信息:
File exists (use ! to override)
此时,若用户真的希望用文件的当前内容替换newfile中原有内容,可使用命令
:w! newfile
否则可选择另外的文件名来保存当前文件。
(3)在末行模式下,输入命令 :q 系统退出Vi返回到shell。若在用此命令退出Vi时,编辑文件没有被保存,则Vi在显示窗口的最末行显示如下信息:
No write since last change (use ! to overrides)
提示用户该文件被修改后没有保存,然后Vi并不退出,继续等待用户命令。若用户就是不想保存被修改后的文件而要强行退出Vi时,可使用命令:q! Vi放弃所作修改而直接退到shell下。
(4)在末行模式下,输入命令 :wq Vi将先保存文件,然后退出Vi返回到shell。
(5)在末行模式下,输入命令 :x 该命令的功能同命令模式下的ZZ命令功能相同。
来自:http://net.zdnet.com.cn/network_security_zone/2008/0519/869835.shtml
因为最近比较闲 有点不思进取 也没什么问题要写了
今天不错,发现一个,恩,感觉不错
做了一个上传Excel并解析数据然后入库的功能,里面涉及到是否是日期格式的判断
之前是这么写的(深谙这么写是不好的,但以为它是可靠的)
private boolean checkDate(String content) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
sdf.parse(content);
return true;
} catch (Exception e){
return false;
}
}
现在发现问题了,对于“2008-06-23asdf”这种情况是返回true的,哈哈,看来是孤陋寡闻了,基础不扎实了,看API上这样讲:
在默认情况下,进行的分析是不严格的:如果输入的形式不是此对象的格式化方法使用的形式,但仍可作为日期进行分析,则分析将获得成功。客户机可能通过调用 setLenient(false) 来强调严格遵守该格式。
按照API说法,将代码改成
private boolean checkDate(String content) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
sdf.
setLenient(false);
sdf.parse(content);
return true;
} catch (Exception e){
return false;
}
}
运行结果“2008-06-23asdf”这种情况还是返回true的,但“2008-13-23”这种情况是返回false的
最后改进程这种写法,可以适应"yyyy-MM-dd""yyyy-M-d""yyyy-MM-d""yyyy-M-dd"
private boolean checkDate(String content) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-M-d");
try {
sdf.setLenient(false);
content = content.replaceAll("-0", "-");
Date d = sdf.parse(content);
String s = sdf.format(d);
return content.equals(s);
} catch (Exception e){
return false;
}
}
参考资料http://www.99inf.net/SoftwareDev/Java/52734.htm
http://blog.163.com/everlee@126/blog/static/263574220089822631229/
当然也可以用正则表达式做到。
昨天就发现这个问题,用firefox没问题,我的chrome谷歌浏览器是3.0.182.3
提示 yahoo邮箱无法加载
按照提示 清楚缓存也没有用
|
Yahoo! 邮箱无法加载 |
Loading Yahoo! Mail failed due to a client side error
您可以尝试对您的防火墙进行设置,并且禁用“屏蔽广告”。如果这个方法仍不凑效,请联系我们的客服。
|
建一个文本文件,命名为proxy.pac
用文本编辑器打开 输入:
function FindProxyForURL(url,host){ if(dnsDomainIs(host, ".blogspot.com")){ return "PROXY google.cn:80"; } }
保存后,在FireFox-工具-选项-高级-网络选项卡-设置-选自动代理配置URL ,在文本框中输入file:///C:/proxy.pac
OK,可以访问blogger了。
别的代理
https://soproxy.appspot.com/
http://proxy-12345.appspot.com/
貌似已经跟我没啥关系的六一儿童节,忙活了一天,签字画押,我勇敢的加入房奴大军了...
一下子从小康生活回归到了解放前,呜呜~~~~(>_<)~~~~
拿着一大堆票据、一大把钥匙回到家倒头便睡,累死了
预祝房奴生活开开心心。
想参考一下roller的设计思路,遂又捡起roller,刚开始是看roller4.0,磨叽了半天时间,因为对struts2不熟悉,转而搞了个
roller3.0,还好都运行起来了,之中发现下载的源码竟然不全,如果不引用roller的jar包的话会报错,缺几个package里的类,累的我
还要反编译,不知道我是走弯路了还是怎么着,总算运行起来了,改了log4j的配置让日志在控制台输出,昨晚下班刚弄到这儿,接着捣鼓
突然想起来写blog也好长时间了,可以追溯到3年前,一开始是在msn space,后来搬家到baidu,那时候对baidu还是很支持的,后来感觉baidu进步有点慢啊,完了还出来一些绯闻
接着就有些不安分了,到处搬家哈哈,csdn、javaeye、博客大巴、yo2、blogjava、blogger,哦天,真的不少,现在csdn、
javaeye、博客大巴、yo2已经荒了,blogger这几天还被和谐了很郁闷,就剩blogjava和baidu了,现在在捣鼓在
GAE上弄个java写的blog,已经糊弄上去了,凑合能添加文章,一有空就修改一下代码往上面更新一下,现在在研究怎么静态化和上传图片
好几天了,发现无法打开我的google blogger,难道被传说中的和谐了?!我刚刚搬家到blogger啊,还没玩儿几天呢
private void buttonToExcel_Click(object sender, EventArgs e)
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "Execl files (*.xls)|*.xls";
saveFileDialog.FilterIndex = 0;
saveFileDialog.RestoreDirectory = true;
saveFileDialog.CreatePrompt = true;
saveFileDialog.Title = "Export Excel File To";
saveFileDialog.ShowDialog();
Stream myStream;
myStream = saveFileDialog.OpenFile();
StreamWriter sw = new StreamWriter(myStream, System.Text.Encoding.GetEncoding(-0));
string str = "";
try
{
//写标题
for (int i = 0; i < this.dataGridView3.ColumnCount; i++)
{
if (i > 0)
{
str += "\t";
}
str += this.dataGridView3.Columns[i].HeaderText;
}
sw.WriteLine(str);
//写内容
for (int j = 0; j < this.dataGridView3.Rows.Count; j++)
{
string tempStr = "";
for (int k = 0; k < this.dataGridView3.Columns.Count; k++)
{
if (k > 0)
{
tempStr += "\t";
}
tempStr += this.dataGridView3.Rows[j].Cells[k].Value + "";
}
sw.WriteLine(tempStr);
}
sw.Close();
myStream.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
sw.Close();
myStream.Close();
}
MessageBox.Show("OK");
}
今早看到一则新闻:出处
http://www.infoq.com/cn/news/2009/05/vs2010-beta1
昨日,Soma在其
博客上宣布Visual Studio 2010和.NET 4.0的Beta 1已经可以通过MSDN订阅下载了。
过去的几个月里,我们已经初步了解了Visual Studio 2010和.NET 4.0的
一系列新特性。和上次发布的CTP版本不同,这次的Beta 1是以安装包形式发布的,而非VPC镜像。这样我们就可以自己下载安装,一睹为快了,不过大家最好还是安装到虚拟机中。
在Visual Studio 2010的产品站点上,我们可以了解到VS 2010给我们带来的革新:
-
加强的用户体验:VS2010带来了新用户界面,让工作更专注。
-
便捷的SharePoint开发:对SharePoint开发更完善的支持,让SharePoint开发不再痛苦。
-
应用程序生命周期管理(ALM):把项目角色更紧密地集成到整个应用程序生命周期中。
-
更佳的Web应用开发:对JavaScript的加强,Silverlight开发的完整支持,更容易部署。
-
云应用程序开发:集成Azure开发包,无缝进行云应用程序的开发。
-
数据库支持:对IBM DB2和Oracle更好的支持。
-
并行编程:从运行时到IDE都对并行编程提供了很好的支持。
-
更高的生产力:代码上下文可帮助理解现存代码,对C++开发体验的提升,Windows 7的支持,Office开发支持的加强。
经常遇到javascript 缺少对象的错误,无外乎调用的js方法未定义,名字写错了,之类,今儿遇到的郁闷的
我在页面中加了一个注释 ,注意结束标签--和>之间有个空格,结果未起作用,结果可想而知,找了半天才找到
通过简单修改,将blogger原有标签widget改成标签云形式
修改html模板
找到
<b:loop values='data:labels' var='label'>
..........
</b:loop>
将<b:loop>标签之间的内容改成:
<b:if cond='data:blog.url == data:label.url'>
<span expr:dir='data:blog.languageDirection'>
<font expr:size='data:label.count'><data:label.name/></font>
</span>
<b:else/>
<a expr:dir='data:blog.languageDirection' expr:href='data:label.url'>
<font expr:size='data:label.count'><data:label.name/></font>
</a>
</b:if>
<span dir='ltr'>(<data:label.count/>)</span>
OK啦 看看效果吧
早就注意到google blogger 首页文章不能只显示摘要,而是全部显示
google了几个网页提供的方法,官方的方式是在文章中加一个span,让当在首页显示时span隐藏,这种方式只适合以后新增文章,以前的旧文章均没有加入这个span,就不好使
想到blogger这么高度自定义,那么用jquery实现吧
经过一个晚上的实验,终于出结果了
修改html模板,在<head>下面加入
<b:if cond='data:blog.pageType != "item"'>
<script src='http://www.google.com/jsapi'/>
<script type='text/javascript'>
google.load('jquery', '1.3.2');
</script>
<script language='javascript' src='http://www.reindel.com/truncate/jquery.truncate.js' type='text/javascript'/>
<script type='text/javascript'>
$(function() {
$("div[class='post-body entry-content']").truncate( 500, {
chars: /\s/,
trail: [ " ( <a href='#' class='truncate_show'>more</a> . . . )", " ( . . . <a href='#' class='truncate_hide'>less</a> )" ]
});
});
</script>
</b:if>
经测试,IE7中会提示:是否停止运行脚本?此页面的脚本造成Internet Explorer 运行速度减慢,如果继续运行,您的计算机将可能停止响应
这个.truncate的第一个参数设的大小也有关系,这里设了500
在FireFox3和Google Chrome中没有什么提示,速度还挺快,但会有显示问题,因为应用的jquery.truncate框架有浏览器兼容问题
截止到今天下午,中午把自己的应用部署到了Google app engine,用了一周的时间啊,真是费劲周折
好长时间了,听说Google出了个
Google App Engine - Google Code,说是可以让用户上传自己的应用,但是只支持python,当时就想什么
时候支持java啦啊,上个月看新闻就听说Google app engine 要开始支持java啦,哈哈,喜,到时候把我的写的blog传上去,哈哈
上周,终于知道了Google app engine终于开始宣布支持java了,哈哈呼呼,动手,到官网一看,没有支持java的动静啊,
对,英文页面,哈哈,看来中文的还是慢一拍啊
首先到注册一个,竟然还要手机号发注册码,Google了一下 说在手机号前加 86就OK了,填上手机号点按钮,呦,短信马
上就来啦,搞定,注册成功。
这下下载SDK,还有eclipse插件,帮助文档只有英文的,配合Google工具栏的翻译功能,基本能看懂,哈哈,感觉一路下
来,英语水平有所上升啊,哈哈
打开eclipse,装上插件,很轻松的建了第一个应用,插件自动生成了一个小实例,部署上去,惊叹于Google的GWT
开始一直我原来写的blog程序,原来到处找免费的空间,jsp的空间不好找,先是找了
http://www.eatj.com/,但是没24小
时(好像是)就会自动停止,必须手动重启服务,原来还坚持去上去看看,后来终于因为有一次很忙时间太长被注销了,接下来就听
说了
http://www.stax.net/,跟Google的路子差不多,好像还更自定义些,继续使用着,搞java朋友可以去看看
因为google app engine使用Google Account,原来的用户管理模块需要剔除,原来数据库使用的是mysql hibernate,现在
Google 使用JDO,数据库被封装了,还好,当初设计是采用了工厂模式,实现了数据库访问模块与业务处理模块的松耦合,很容易
配置数据库访问模块的更改,感受到好的设计真是为以后修改省很多事啊。
接着说部署我的Google app engine,终于改好相关代码,准备上传了,噩梦开始了
1、Unable to upload:
java.lang.IllegalStateException: cannot find javac executable based on java.home, tried “D:\Java\jdk1.6.0_13
\jre\bin\javac.exe” and “D:\Java\bin\javac.exe”
参考http://zhuyx808.javaeye.com/blog/370124
http://onlypython.group.javaeye.com/group/blog/366471
http://618119.com/archives/2009/04/12/148.html
2、决定转战Linux..
手上有四个版本的Linux,Ubuntu,Redhat,Fedora,openSUSE,都装过,后来感觉还是Fedora比较好用,我装的是
Fedora9,Fedora10正在下载中
以下Linux安装配置,仅限于在Fedora9上安装通过,资料都是通过Google搜索得来,感谢各位网友,网络的力量真是强大。
1、在VMware中装上Fedora9后,首先安装VMware-tools,方便与主机交互
首先需要下载相应的kernel-devel.rpm包进行安装
首先查看内核版本:uname -r一下,我的是2.6.25-14.fc9.i686,
所以下载kernel-devel-2.6.25-14.fc9.i686.rpm,然后运行rpm -ivh kernel-devel-2.6.25-14.fc9.i686.rpm 进行安装. 内核安
装完毕后,需要用这个命令确定内核 C header 的安装目录:ls -d /usr/src/kernels/$(uname -r)*/include
安装内核具体步骤如下:
[root@localhost ~]# uname -r
2.6.25-14.fc9.i686
[root@localhost ~]# rpm -q kernel-devel
package kernel-devel is not installed
[root@localhost ~]# cd /home
[root@localhost home]# wget ftp://rpmfind.net/linux/fedora/releases/9/Everything/i386/os/Packages/kernel-devel-
2.6.25-14.fc9.i686.rpm
[root@localhost home]# rpm -i kernel-devel-2.6.25-14.fc9.i686.rpm
[root@localhost home]# rpm -q kernel-devel
kernel-devel-2.6.25-14.fc9.i686
再安装gcc,否则安装VMware-tools时会提示:Setup is unable to find the "gcc" program on your machine. Please make
sure it
is installed. Do you want to specify the location of this program by hand?
[yes]
What is the location of the "gcc" program on your machine?
在命令行执行:yum install gcc
然后安装VMware Tools就行了,打开菜单“VM -> Install VMware Tools”,然后有光盘自动弹出,把里面的源代码拷贝出来.我的文
件是VMwareTools-6.5.0-xxxxx.tar.gz,我把它拷贝到/opt里.
安装 VMware TOOLS
cd /opt
tar -zxvf VMwareTools-6.5.0-xxxxx.tar.gz
cd vmware-tools-distrib/
./vmware-install.pl
再一路安回车OK
2、由于在装载xorg-x11-drv-vmmouse驱动时的一个bug,在客户虚拟机的显示中,鼠标位置可能不正确。直到被更新前,在客户机
中添加Option NoAutoAddDevices到/etc/X11/xorg.conf文件的ServerFlags节中。如果需要,创建这个节:
Section "ServerFlags"
Option "NoAutoAddDevices"
EndSection
3、第一,安装JDK
第一,到http://java.sun.com下载最新JDK,当前本人下载的是jdk1.6.0_02!下载文件:jdk-6u2-linux-i586-rpm.bin.注意是
rpm.bin的!
第二,给下载回来的文件增加执行权限:chmod 755 jdk-6u2-linux-i586-rpm.bin.
第三,执行文件:./jdk-6u2-linux-i586-rpm.bin.
第四,执行文件产生一个rpm文件,可直接双击执行也可以在shell下执行:rpm -ivh jdk-6u2-linux-i586-rpm.
第五:配置环境变量,环境变量配置可在全局文件/etc/profile下修改,这样所有linux系统的用户都可以用JDK,如果只是特定的
用户用可修改/root/.bashrc文件,本人的修改为:
#java set
set JAVA_HOME=/usr/java/jdk1.6.0_02
export JAVA_HOME
export JRE_HOME=/usr/java/jre1.6.0_02
set JAVA_BIN=/usr/java/jre1.6.0_02
export JAVA_BIN
第五,当环境变量修改完后,重起系统,在shell下输入java,看是否输入相关JAVA帮助信息,如果有,说明已经安装成功!如果没有,
检查一下变量环境设置是否有误!
2,安装Eclipse,Eclipse不需要安装,只要解压缩就行了
运行Google app Engine不需要Tomcat
3,安装tomcat的方法跟安装eclipse的一样,也是下一个tar.gz的文件按安装eclipse方法和步骤就行了!进入tomcat/bin
下./startup.sh,如果在shell出现jdk的相关信息说明已经安装成功启动了,在firefox下打http://localhost:8080/出现tomcat页就
大成功了!
在以上的安装过程之中,出现了小插曲,就是tomcat找不到JDK,后来我又到JAVA网站下了一个JRE回来安装,并建JRE_HOME,重起
TOMCAT,成功了!
4、运行Google App Engine的应用,提示
** Unable to load Mozilla for hosted mode **
java.lang.UnsatisfiedLinkError:
/home/dhofmann/development/ide/gwt-linux-1.4.61/mozilla-1.7.12/libxpcom.so:
libstdc++.so.5: cannot open shared object file: No such file or directory
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
解决办法:
Search for stdc++5 in synaptic package manager (System->Administration->Synaptic) and then mark and install it. Or
use this console command:
yum install libstdc++.so.5
停止进程命令:
就是kill 比较不错,如果kill不了. 加上-9
如#kill -9 1778
注1778 为进程pid
pid可以通过ps aux|grep 服务名查得
启动Eclipse时,提示错误:
eclipse.buildId=M20090211-1700
java.version=1.6.0
java.vendor=Sun Microsystems Inc.
BootLoader constants: OS=linux, ARCH=x86, WS=gtk, NL=zh_CN
Command-line arguments: -os linux -ws gtk -arch x86
!ENTRY org.eclipse.ui.workbench 4 0 2009-04-18 02:12:18.085
!MESSAGE Widget disposed too early!
!STACK 0
java.lang.RuntimeException: Widget disposed too early!
at org.eclipse.ui.internal.WorkbenchPartReference$1.widgetDisposed(WorkbenchPartReference.java:171)
在网上搜索得知:
eclipse.ini文件加个参数
-vmargs
-Dorg.eclipse.swt.browser.XULRunnerPath=
在Fedora9中安装拼音输入法
保证Fedora 9联网的状态下
在application->system tools->terminal 应用程序->系统工具->终端
输入
su 回车
提示输入root密码
yum install scim 回车
系统会自动从一个镜uy像站点检索scim,并询问是否下载,选择y
下载完成后输入
yum install scim-pinyin 回车
提示和操作如上
然后输入
scim 回车
(笔者的电脑运行到starting SCIM后就没有反应了,不过没关系这时候可以按ctrl+c中断)
选择Fedora 9
System->Preference->Personal->Input Method
系统->首选项->个人->输入法
选择启用新特性,然后选择里面的SCIM,然后选择配置SCIM,
在进入后的界面中选择Global Set 全局设置,在这里设置激活热键即可,然后重新启动电脑,就可以在Fedora 9下面使用中文输入
法了 虽然有点麻烦 但毕竟fedora等众多linux桌面系统还很年轻,有很多不足之处。
参考资料:
http://www.5dlinux.com/article/6/2007/linux_9042.html
http://zhidao.baidu.com/question/62290384.html
http://www.linuxidc.com/Linux/2008-09/16011.htm
备案:
java.lang.IllegalStateException: No data type for node: org.hibernate.hql.ast.tree.IdentNode
hibernate查询时报上面的异常,仔细检查hql写的有不对的地方,我就是把逗号,写成点.
给你一个日期2009-01-01 00:00:00 获取这个月的最后一天。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date=null;
try {
date = sdf.parse("2009-12-01 00:00:00");
} catch (ParseException e) {
e.printStackTrace();
}
Calendar calendar = new GregorianCalendar();
calendar.setTime(date);
calendar.set(Calendar.DATE, calendar
.getActualMaximum(Calendar.DATE));
Date d = calendar.getTime();
System.out.println(sdf.format(d));
好久没写了,过了个年,过了七天猪的日子,吃了睡睡了吃中间偶尔看看电视,为假期准备了几个电影都没看,唉:-(忙,上了几天班了,怎么感觉这周过的这么慢呢,刚刚刚周四
昨儿看了一集struts2
总结几点
1、struts.xml中的package标签有个abstract="true"属性,如果为true,则这个package中不能有<action>标签,为true表示这个package为一个抽象package,就像java中的接口中不能有方法实现似的。
2、package标签还有个namespace属性,它关系到这个package中的action访问路径,默认是"",比如
<package name= "capinfo" extends= "struts-default" namespace="/hello">
<action name= "HelloWorld"
class= "com.capinfo.struts2.action.HelloWordAction" >
<result>/HelloWorld.jsp</result>
</action>
</package>
则jsp中则应为<form action="/hello/HelloWorld.action" method="post">,如果没有找到hello/HelloWorld.action则会寻找namespace为""的,也就是HelloWorld.action,如果再没有,就会抛出异常。
3、在struts1中可以有多个struts-config.xml的文件,只要在web.xml配置org.apache.struts.action.ActionServlet时加到config参数中,以逗号分隔,在struts2中也可以有多个struts.xml形式的文件,这次不需要修改web.xml了,在struts.xml中添加诸如
<include file=""/>就Ok了
4、关于struts各种参数的配置信息位于struts2-core.jar/org.apache.struts2/default.properties中,如果要修改里面的配置,有两种方式,一是在struts.xml中配置,例如<constant name="struts.devMode" value="true" />,二是在classess中建一个struts.properties,在里面配置比如struts.i18n.encoding=GBK,在struts2-core.jar/org.apache.struts2/default.properties中有一下这句注释,说明了struts.properties将覆盖default.properties中的配置
### Struts default properties
###(can be overridden by a struts.properties file in the root of the classpath)
###
就总结这么些先。
前两天实践了关于拦截器的具体实现,说实话关于底层实现还没有看明白,看jdk的源码中的
public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces)
方法,好长啊
迂回一下,今儿看struts2的具体拦截器Interceptor怎么配置
配置可比自己写实现拦截器容易多了
1、首先写一个拦截器类,拦截器类有两只写法(目前俺知道的)
一种是显示com.opensymphony.xwork2.interceptor.Interceptor接口,com.opensymphony.xwork2.interceptor.Interceptor接口有三个方法destroy()、init()和String intercept(ActionInvocation actionInvocation),跟过滤器差不多
这里指出的是init初始化方法将在容器启动是调用这个方法。
package com.test.interceptor;
/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-15
* Time: 16:34:17
* To change this template use File | Settings | File Templates.
*/
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.ActionInvocation;
public class MyInterceptor implements Interceptor{
public void destroy() {
}
public void init() {
}
public String intercept(ActionInvocation actionInvocation) throws Exception {
System.out.println("test intercept begin");
String result = actionInvocation.invoke();
System.out.println("test intercept finish");
return result;
}
}
另一种就是继承com.opensymphony.xwork2.interceptor.AbstractInterceptor,这是个抽象类,并实现了com.opensymphony.xwork2.interceptor.Interceptor接口,分别实现了init和destroy方法,但什么都没做,继承AbstractInterceptor后,实现intercept方法就行了,
这里指出的是在intercept方法中执行actionInvocation.invoke();执行所拦截的action中的方法;
2、拦截器写完了剩下就是配置了,这里要用到struts.xml的组织结构<struts>中有<package>包的的概念,包与包之间可以继承extends,就像子类继承父类一样,子类将拥有父类的属性和配置,我们一般都继承extends="struts-default",而struts-default定义在struts2-core.jar 中的struts-default.xml中,struts-default包中定义了很多struts2提供的拦截器和拦截器栈(拦截器栈可以包含多个拦截器或拦截器栈),struts2的好多功能都是实现在这些拦截器中,其中有个<default-interceptor-ref name="defaultStack"/>标签定义了默认的拦截器,如果<action>配置中没有拦截器配置,那就调用默认拦截器,如果有拦截器配置,要么同时加上默认拦截器,要么在自己的package中加入设置默认拦截器的标签。
<package name="capinfo" extends="struts-default">
<interceptors>
<interceptor name="myInterceptor" class="com.test.interceptor.MyInterceptor">
</interceptor>
</interceptors>
<action name="HelloWorld"
class="com.capinfo.struts2.action.HelloWordAction">
<result>/HelloWorld.jsp</result>
<interceptor-ref name="myInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
<!-- Add your actions here -->
</package>
说是struts2的核心就是拦截器
先看看拦截器的实现
实现拦截器有这么几个东西构成
1、目标对象-将被拦截的对象,这个对象中的方法被调用是将被拦截
要求目标对象面向接口编程,首先要定义接口
package com.test.interceptor;
/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:37:23
* 面向接口编程
* 目标对象的接口
*/
public interface TargetInterface {
public void doSomething();
}
目标对象实现
package com.test.interceptor;
/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:36:26
* 目标对象
*/
public class Target implements TargetInterface{
public void doSomething(){
System.out.println("do something");
}
}
2、拦截器对象-里面包含在调用目标对象前或后要调用的方法
package com.test.interceptor;
/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:39:32
* 拦截器
*/
public class Interceptor {
public void before(){
System.out.println("before");
}
public void after(){
System.out.println("after");
}
}
3、处理器-处理器决定拦截器如何拦截目标对象
package com.test.interceptor;
/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:41:08
*/
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 处理器
* 在这里将目标对象Target和拦截器Interceptor联系在了一起
*/
public class MyHandler implements InvocationHandler{
/**
* 目标对象
* 将来目标对象的方法将被注入interceptor
*/
private Object object;
/**
* 拦截器
* MyHandler负责将Interceptor这个拦截器注入到传入的目标对象object
*/
private Interceptor interceptor = new Interceptor();
public void setObject(Object object){
this.object = object;
}
/**
* 实现InvocationHandler接口的方法
* @param o 在其上调用方法的代理实例
* @param method 对应于在代理实例上调用的接口方法的 Method 实例
* @param objects 包含传入代理实例上方法调用的参数值的对象数组
* @return 从代理实例的方法调用返回的值
* @throws Throwable
*/
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
Object result = null;
interceptor.before();
result = method.invoke(object,objects);
interceptor.after();
return result;
}
}
4、代理对象-用于得到目标对象的代理对象
package com.test.interceptor;
/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:50:52
* 代理类
*/
import java.lang.reflect.Proxy;
public class MyProxy {
/**
* 返回obj的,处理器为MyHandler的代理对象
* @param obj 目标对象
* @return 目标对象的代理对象
*/
public Object getProxy(Object obj){
MyHandler myHandler = new MyHandler();
myHandler.setObject(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),myHandler);
}
}
5、最后客户调用代码
package com.test.interceptor;
/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:55:45
* 客户调用
*/
public class Client {
public static void main(String[] args){
//目标对象
TargetInterface target = new Target();
//代理对象
MyProxy myProxy = new MyProxy();
//通过代理对象得到目标对象的代理
TargetInterface proxy = (TargetInterface)myProxy.getProxy(target);
//通过目标对象的代理调用目标对象的方法
proxy.doSomething();
}
}
//输出:
//before
//do something
//after
将自己的理解写了注释,现在只理解到这个程度,像
Proxy.
newProxyInstance
里面是怎么实现的,还没深入考究
继续努力
关于类型转换还有一种写法:
public class ConverterPoint extends StrutsTypeConverter {
// @Override
// public Object convertValue(Map context, Object value, Class toType) {
// if(Point.class == toType){
// String[] params = (String[])value;
// params = params[0].split(",");
// Point point = new Point();
// point.setX(Integer.parseInt(params[0]));
// point.setY(Integer.parseInt(params[1]));
// return point;
//
// }else if(String.class == toType){
// Point point = (Point)value;
// return "x=" + point.getX() + ",y=" + point.getY();
// }
// return super.convertValue(context, value, toType);
// }
@Override
public Object convertFromString(Map arg0, String[] arg1, Class arg2) {
String[] params = arg1;//(String[])value;
params = params[0].split(",");
Point point = new Point();
point.setX(Integer.parseInt(params[0]));
point.setY(Integer.parseInt(params[1]));
return point;
}
@Override
public String convertToString(Map arg0, Object arg1) {
Point point = (Point)arg1;
return "x=" + point.getX() + ",y=" + point.getY();
}
}
原来是继承ognl.DefaultTypeConverter类,现在改成继承org.apache.struts2.util.StrutsTypeConverter类了,看org.apache.struts2.util.StrutsTypeConverter的源码可知道org.apache.struts2.util.StrutsTypeConverter是个抽象类,并实现了ognl.TypeConverter,org.apache.struts2.util.StrutsTypeConverter中有两个要实现的方法一个convertFromString,一个convertToString,看方法名字就知道一个从字符串转换成Object,一个是将Object转换成String,这样好像更加清晰
另外还有一种全局转换的配置,就是建立一个统一的属性文件,文件名为xwork-conversion.properties,与struts.xml位于统一目录下,里面的配置改成了
com.test.struts2.data.Point=com.test.struts2.action.ConverterPoint
意思是所有com.test.struts2.data.Point类型的对象都要通过com.test.struts2.action.ConverterPoint来转换
struts2局部类型转换
需求为:在页面的文本框输入一个x、y坐标,之间用","隔开,Action中有一个Point类型的属性,Point类里面有两个字段,分别是x,y,int型,要求当页面提交时将文本框中的字符串转换成Point对象,当Action返回到页面时将Point转换成字符串显示
1、首先做一个jsp用于输入和提交:point.jsp
<s:form action="Converter">
<s:textfield name="point" label="Point"></s:textfield>
<s:textfield name="point.x" label="Point.X"></s:textfield>
<s:textfield name="point.y" label="Point.Y"></s:textfield>
<s:submit label="submit"></s:submit>
</s:form>
2、再建一个用于显示的jsp-converter.jsp
<body>
<s:property value="point"/><br>
<s:property value="point.x"/><br>
<s:property value="point.y"/><br>
</body>
3、Action类 ConverterAction
public class ConverterAction extends ActionSupport{
private Point point;
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
}
public String execute()throws Exception {
return "success";
}
}
4、struts.xml
<action name="Converter"
class="com.test.struts2.action.ConverterAction">
<result name="success">/converter.jsp</result>
<result name="input">/point.jsp</result>
</action>
5、转换类 ConverterPoint
public class ConverterPoint extends DefaultTypeConverter {
@Override
public Object convertValue(Map context, Object value, Class toType) {
if(Point.class == toType){
String[] params = (String[])value;
params = params[0].split(",");
Point point = new Point();
point.setX(Integer.parseInt(params[0]));
point.setY(Integer.parseInt(params[1]));
return point;
}else if(String.class == toType){
Point point = (Point)value;
return "x=" + point.getX() + ",y=" + point.getY();
}
return super.convertValue(context, value, toType);
}
}
6、配置转换
在ConverterAction 类的同一目录下定义属性文件ConverterAction-conversion.properties,注意文件名,-conversion.properties为固定不变,ConverterAction为Action的名字,文件内容:
point=com.test.struts2.action.ConverterPoint
Ok了,这样就完工了
前两天初步认识了一下struts2
今儿看来教程的第二三讲,搞清了一些前面的一些猜测或是疑问
1、struts2是不用<html:...>标签了,统一成了<s:...>
如下这样:
<s:form action="Converter">
<s:textfield name="point" label="Point"></s:textfield>
<s:submit label="submit"></s:submit>
</s:form>
显示效果:
注意到<s:textfield name="point" label="Point"></s:textfield>
中的label属性,它指定了文本框前面显示的内容,还自动加了冒号,哈哈,挺聪明的嘛,但是担心这样在复杂的页面设计中是不是好使。
哦对了,要想这么写,要在页面上方加上这个:<%@ taglib prefix="s" uri="/struts-tags" %>
2、Action
前面说的Action不再需要继承任何struts类,现在看来要失望了,为了方便起见还是建议集成ActionSupport类,目前觉得有用的是ActionSupport中定义了几个static的result name,比如SUCCESS、ERROR,原来的return "success";现在可以写成return super.SUCCESS;,将标识用的字符串常量定义成static的是一直提倡的,还有就是validate()方法,验证有错误可以调用addFieldError()方法,好像就是struts1 ActionForm里的东西,有所改进的是super.addFieldError("username", "username is null");将在页面中显示的效果为:错误信息"username is null"将在名字为"username"文本框的上面显示,这些如果能用ajax实现就好了。
对于Action解耦,可能在于它不再需要HttpServletRequest 、HttpServletResponse这样的容器运行时参数吧
Powered by Zoundry Raven
今天第一次感觉到经济危机在我身边了,部门现在没有在做的项目了
经济危机中,赶紧为自己充充电,好到时候柳暗花明又一村,哈哈
学struts2
据说struts2基于webwork,基本上跟struts1没啥关系,如果有webwork的经验上手会很迅速
我没接触过webwork,就知道有这么个东西
今儿开始第一个struts
见过好多blog写有struts2的入门步骤,俺也写一个,为自己造个轮子,加深印象。
首先下载struts2的jar包,到http://struts.apache.org/,右上角有个struts2的链接,今天下到的是
struts2的2.0.14,昨天在javaeye上看到发布
Struts2.1.3
发布了,只是主页还没看到,不止一次听大拿们说过不要追求新版本,哈哈
下载后的目录:app--struts的例子
docs-doc文档
lib-struts的jar包或依赖包
src-源码
HelloWorld:
1、index.jsp
耳目一新的是,不需要用到struts html标签,这只是猜测,或许例子过于简单?今天工作中还感觉struts1的html标签真是不好用,想加个class、maxlength、size都不好使,让我很是郁闷。希望在继续学习中真的能耳目一新。
struts的action惯例后缀名改成了.action,不再像struts1的.do了,说是延续到webwork的惯例。
下面的页面代码submit的时候将提交到login.action
index.jsp
<body>
<form action="login.action" method="post">
username:
<input type="text" name="username"/>
password:
<input type="password" name="password"/>
<input type="submit" value="submit"/>
</form>
</body>
2、Action类
struts2的Action可是大进步,不用再继承任何类,实现了松耦合,它好像将struts1的ActionForm融合了进来,据说struts2不再用ActionForm,页面上对应的字段写在了Action中,struts2框架会自动调用get/set方法,在我印象里struts1中的Action对象不是线程安全的,会在不同线程间重用,所以谨慎在里面定义字段,在这看来struts2的Action不是这样的,只是猜测
package com.mystart.action;
public class LoginAction {
private String
username;
private String
password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.
username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.
password = password;
}
public String execute()
throws Exception{
return "success";
}
}
3、jsp、java类都定义了,现在要它们联系起来-struts配置文件
新的struts配置文件有个package包的概念,还没闹明白这个package的详细用法,有待继续深入
<action>标签有变化,type变成了class,path变成了name,struts1中name属性是制定ActionForm的,现在ActionForm没有了
forward变成了result,result的默认name=success
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="struts" extends="struts-default">
<action name="login" class="com.mystart.action.LoginAction">
<result name="success">/result.jsp
</result>
</action>
</package>
</struts>
4、最后启动struts2,配置web.xml
struts1的web.xml配置是放在<servlet>中,也就是是一个servlet
struts2变成了一个过滤器Filter
struts1中<url-pattern>被配置成拦截.do的链接
struts2变成了拦截所有链接 /*
<?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">
<filter>
<filter-name>struts2
</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2
</filter-name>
<url-pattern>/*
</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp
</welcome-file>
</welcome-file-list>
</web-app>
以上是驴了个struts的视频教程,今儿看了第一节课,看完后做了一下总结,里面有一些自己的理解,有不对的地方请兄弟们指正,别光光说我是猪,猪也要进步啊,嘿嘿,每一步都有疑问,明天带着问题接着看下一节,睡觉去。