云自无心水自闲

天平山上白云泉,云自无心水自闲。何必奔冲山下去,更添波浪向人间!
posts - 288, comments - 524, trackbacks - 0, articles - 6
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

在table中,如果表格内容为空,那么显示的时候,表格的边框会少掉一块。在HTML的规范中,应该使用empty-cells: show这个style来解决,但是IE要到IE8之后才支持这个属性。而FireFox2是已经支持了。

那么在IE7之前的版本中要解决这个问题,好像是需要使用border-collapse:collapse;这个style.

<table style="border-collapse:collapse">

posted @ 2008-04-14 08:03 云自无心水自闲 阅读(526) | 评论 (0)编辑 收藏


首先,在web项目的页面根目录下建立目录template
然后创建目录simple和xhtml,以上的目录名是struts2缺省使用的,不同的主题使用相应的目录。然后再创建一个components目录,在这个目录下,创建一个property.ftl。 最后的目录结构如下:
template/simple/components/property.ftl
template/xhtml/components/property.ftl

然后在property.ftl中可以使用FreeMarker来定义新的模板(FreeMarker的具体语法可以查看FreeMarker的官方网站,相当的详细易懂):
<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
<@s.if test="${parameters.value} == null || ${parameters.value} == '' ">&nbsp;</@s.if>
<@s.else><@s.property value="${parameters.value}" /></@s.else>
<#include "/${parameters.templateDir}/xhtml/controlfooter.ftl" />

以上是一个我自定义的模板,检测结果是否为空字符串,如果是空的话,就输出一个&nbsp; 这样在输出结果时表格的边框线就是完整的了。

定义好之后,在jsp页面中就可以这样使用了:

<s:component template="/components/property.ftl" theme="simple">
  <s:param name="value" value="%{'bookName'}"/>
</s:component>

第一行中的目录名从自components开始,struts2会自动在template目录下去寻找,如是主题是simple, 就在simple目录下找。
另外,param的语法要注意一下,%{}里面需要加一对引号

posted @ 2008-04-11 16:09 云自无心水自闲 阅读(7539) | 评论 (4)编辑 收藏

在Struts2的官方网站上,有doubleselect的用法示例,但是那个例子比较简单。
<s:doubleselect label="doubleselect test2" name="menu" list="#{'fruit':'Nice Fruits', 'other':'Other Dishes'}" doubleName="dishes" doubleList="top == 'fruit' ? {'apple', 'orange'} : {'monkey', 'chicken'}" />
上面的例子演示了doubleselect的基本用法,但是其list和doubleList都是固定的。尤其是doublelist的切换使用了3目运算符 ? :,并没有太大的实际使用价值。在实际应用中,list往往是action返回的一个List<DataObject>,listKey和listValue来显示第一级下拉框,doubleList往往是一个Map<Integer, List<DataObject>>,其中Map中的Key值是第一级下拉框的listKey。
举个例子:
Data Object:
public class Book {
        
private int id;
        
private String name;
        
private int categoryId;

        
// getter and setter..
}


public class Category {
        
private int id;
        
private String name;

        
// getter and setter..
}


JSP:
<s:doubleselect list="categoryList" listKey="id" listValue="name"
   doubleName="bookId" doubleList="bookMap.get(top.id)" doubleListKey="id" doubleListValue="name" theme="simple"/>

此处要注意的是top的用法,开始我以为top就是指代list的值,所以使用的是bookMap.get(top),但是二级下拉框一直是空白,后来我突然想到说不定top是一个Category实例呢,尝试了一下top.id,果然成功了。

Action:

public class DemoAction {
        
private Map<Integer, List<Book>> bookMap;
        
private List<Category> categoryList;

        
public String execute() throws Exception {
                categoryList 
= new ArrayList<Cateogry>();

                Category category;
                category 
= new Category();
                category.setId(
1);
                category.setName(
"Fiction");
                categoryList.add(category);
                category 
= new Category();
                category.setId(
2);
                category.setName(
"Java");
                categoryList.add(category);

 

                bookMap 
= new HashMap<Integer, List<Book>>();

                List
<Book> bookList = new ArrayList<Book>();
                Book book;
                book 
= new Book();
                book.setId(
1);
                book.setName(
"Harry Porter");
                book.setCategoryId(
1);
                bookList.add(book);

                book 
= new Book();
                book.setId(
2);
                book.setName(
"Nightmare");
                book.setCategoryId(
1);
                bookList.add(book);

                bookMap.put(
1, bookList);

 

                bookList 
= new ArrayList<Book>();
                book 
= new Book();
                book.setId(
3);
                book.setName(
"Thinking in Java");
                book.setCategoryId(
2);
                bookList.add(book);
                book 
= new Book();
                book.setId(
4);
                book.setName(
"Head First Design Patterns");
                book.setCategoryId(
2);
                bookList.add(book);

                bookMap.put(
2, bookList);


                
return SUCCESS;
        }

        
// getter and setter..
}



posted @ 2008-03-27 22:08 云自无心水自闲 阅读(12127) | 评论 (16)编辑 收藏

对于jsp页面,为了防止页面被服务器缓存、始终返回同样的结果。

通常的做法是在客户端的url后面加上一个变化的参数,比如加一个当前时间。

我现在使用的方法是在jsp头部添加以下代码:

<%
    request.setAttribute("decorator", "none");
    response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
    response.setHeader("Pragma","no-cache"); //HTTP 1.0
    response.setDateHeader ("Expires", 0); //prevents caching at the proxy server
%>

这样如果有多个调用此页面的链接就不需要一个一个全部添加参数了。

posted @ 2008-03-18 14:06 云自无心水自闲 阅读(4286) | 评论 (2)编辑 收藏

在数据库的设计中,字典项是经常使用的技巧。
比如在一个图书馆系统中,书籍表(Book)会有一个分类字段,这时候我们一般会单独建立一张分类表(Category),在书籍表只保存分类表的ID。
在用户界面上显示书籍明细的时候,会要求显示CategoryID在Category表中对应的名称。
这样通常的做法是把Book和Category两张表进行关联。
但在实际应用中,Category一般都是Cache在应用服务器端,再使用数据表的连接就不够高效。
我的做法是这样的:在iBatis中使用SqlMap从表中将数据取出,此时不使用数据表的连接。
package com.demo;
public class Book {
      
/* 省略了getter和setter方法 */
        private int id;
        
private String name;
        
private int categoryId;
        
private String author;
}


package com.demo;

public class Category {
       
private static Map<Integer, Category> cacheMap;

        
/* 省略了这两个属性的getter和setter方法 */

        
private int id;
        
private String name;
       
public static Category getCategory(int id) {
             init();
            
return cacheMap.get(id);
        }
 
        
public static Map<Integer, Category> getCategoryMap() {
            init();
           
return cacheMap();
        }

       
private init() {
            
if ( cacheMap != null ) return;

            
// the code to load category from datebase
            
// 在这里为了演示的需要,使用以下代码

             cacheMap 
= new HashMap<Integer, Category>();
             Category category 
= new Category();
             category.setId(
1);
             category.setName(
"Fiction");
             cacheMap.put(
1, category);
 
             category 
= new Category();
             category.setId(
2);
             category.setName(
"Cartoon");
        }
}



package com.demo;

public class BookAction  {
        
/* 省略了属性的getter和setter方法 */
        Book book;

        
public String execute() {
                book 
= new Book();
                book.setId(
1);
                book.setName(
"Thinking in java");
                book.setCategoryId(
1);
                bookList.add(book);
                
                
return SUCCESS;                
        }
}

JSP:
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
 
<head>
  
<s:head />
 
</head>

 
<body>

  
<table border="1">
    
<tr>
     
<td>
      
<s:text name="page.label.userName" />
     
</td>
     
<td>
      
<s:property value="book.name" />
     
</td>
    
</tr>
    
<tr>
     
<td>
      
<s:text name="page.label.category" />
     
</td>
     
<td>
       
<s:property value="@com.demo.Category@getCategory(book.categoryId).getName()"/></td>
    
</tr>
 
</body>
</html>



posted @ 2008-03-17 12:09 云自无心水自闲 阅读(5773) | 评论 (8)编辑 收藏

2008年2月24日,Flex3正式发布了。分为标准版和Professional版。
两者差别不大,标准版没有advanced datagrid和一些性能分析工具。(advanced datagrid)可是我期盼好久的功能了。

另外,价钱也是相当的不菲。Standard is $249 US, Professional costs $699.
此外,还可以选择从flex2升级上去:升级到Standard的话,99美元,升级到professional要299美元。

posted @ 2008-02-27 06:52 云自无心水自闲 阅读(750) | 评论 (0)编辑 收藏

Tomcat在后台重起后,所有的session失效。如果客户端继续点击了一个菜单项,发出一个请求。会得到一个exception。

这时候,可以定义一个名为:sessionTimeout的global results

<result name="sessionTimeout">/WEB-INF/pages/session_timeout.jsp</result>

这样,所有Action的session timeout都会被定向到指定的页面

posted @ 2008-02-21 12:03 云自无心水自闲 阅读(1938) | 评论 (2)编辑 收藏

最近尝试用extjs来展示树状菜单。着实花了一番功夫。树状菜单的菜单项需要动态加载,而目前版本的extjs中只支持JSON格式的数据。查了一些资 料,决定使用struts2的json-plugin。首先按照例子做了一个,但是结果就是不成功,界面上只出来了一个js中生成的root节点,不能加 载从后台生成的数据。研究后发现是数据格式有问题。使用json-plugin生成的数据格式如下:
{"cls":"folder","id":10,"leaf":false,"children":[{"cls":"file","id":11,"leaf":true,"children":null,"text":"S600"},{"cls":"file","id":12,"leaf":true,"children":null,"text":"SLK200"}],"text":"Benz"}
而extjs需要的数据格式如下:
[{"cls":"folder","id":10,"leaf":false,"children":[{"cls":"file","id":11,"leaf":true,"children":null,"text":"S600"},{"cls":"file","id":12,"leaf":true,"children":null,"text":"SLK200"}],"text":"Benz"}]
区别很小,就只相差最外面的两个方括号。但是少了这两个方括号,在json中,含义迥然不同,前者表示一个对象,而后者表示一个数组。而extjs中 tree的dataloader需要的数据必须是一个数组。而这样的数据格式是json-plugin自动生成的,无法改变。所以,我最后放弃了json -plugin,转而使用json-lib来解决这个问题。
1. 下载json-lib, http://json-lib.sourceforge.net/
2. lib目录下的jar文件清单:
commons-beanutils-1.7.0.jar
commons-collections-3.2.jar
commons-digester-1.6.jar
commons-lang-2.3.jar
commons-logging-1.1.jar
dom4j-1.6.1.jar
ezmorph-1.0.4.jar
freemarker-2.3.8.jar
javassist-3.8.1.jar
json-lib-2.2.1-jdk15.jar
log4j-1.2.13.jar
ognl-2.6.11.jar
struts2-core-2.0.11.jar
xml-apis-1.0.b2.jar
xwork-2.0.4.jar


首先配置web.xml
<?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"
>
  
<welcome-file-list>
    
<welcome-file>index.jsp</welcome-file>
  
</welcome-file-list>
  
<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>
</web-app>

然后是struts.xml
<?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>
    
<constant name="struts.devMode" value="true"/>
    
<constant name="struts.i18n.encoding" value="UTF-8"/>
    
<package name="person" extends="struts-default">
        
<action name="menus" method="execute" class="com.lab.MenuAction">
            
<result>/menu.jsp</result>
        
</action>
    
</package>
</struts>

3. 树的节点模型(省略了getter,setter)
public class Menu {
    
private int id;
    
private String text;
    
private boolean leaf;
    
private String cls;
    
private List<Menu> children;
}

4. action
package com.lab;

import java.util.ArrayList;
import java.util.List;

import net.sf.json.JSONArray;

public class MenuAction {
    
private String menuString;
   
    
private List<Menu> menus;
   
    
public String execute() {

        menus 
= new ArrayList<Menu>();
       
        Menu benz 
= new Menu();
        benz.setText(
"Benz");
        benz.setCls(
"folder");
        benz.setLeaf(
false);
        benz.setId(
10);
        menus.add(benz);
       
        List
<Menu> benzList = new ArrayList<Menu>();
        benz.setChildren(benzList);
       
        Menu menu;
        menu 
= new Menu();
        menu.setText(
"S600");
        menu.setCls(
"file");
        menu.setLeaf(
true);
        menu.setId(
11);
        benzList.add(menu);
        menu 
= new Menu();
        menu.setText(
"SLK200");
        menu.setCls(
"file");
        menu.setLeaf(
true);
        menu.setId(
12);
        benzList.add(menu);
       
        Menu bmw 
= new Menu();
        bmw.setText(
"BMW");
        bmw.setCls(
"folder");
        bmw.setLeaf(
false);
        bmw.setId(
20);
        menus.add(bmw);
       
        List
<Menu> bmwList = new ArrayList<Menu>();
        bmw.setChildren(bmwList);
       
        menu 
= new Menu();
        menu.setText(
"325i");
        menu.setCls(
"file");
        menu.setLeaf(
true);
        menu.setId(
21);
        bmwList.add(menu);
       
        menu 
= new Menu();
        menu.setText(
"X5");
        menu.setCls(
"file");
        menu.setLeaf(
true);
        menu.setId(
22);
        bmwList.add(menu);
       
        JSONArray jsonObject 
= JSONArray.fromObject(menus);
        
try {
            menuString 
= jsonObject.toString();
        } 
catch (Exception e) {
            menuString 
= "ss";
        }

        
return "success";
    }

    
public String getMenuString() {
        
return menuString;
    }

    
public void setMenuString(String menuString) {
        
this.menuString = menuString;
    }
}

5. menu.jsp
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:property value="menuString" escape="false"/>

6. html页面和js
我使用的就是extjs的example中的reorder.html和reorder.js,更改了reorder.js中treeloader的dataurl: menus.action
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Reorder TreePanel</title>
<link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css" />

    
<!-- GC -->
     
<!-- LIBS -->
     
<script type="text/javascript" src="extjs/adapter/ext/ext-base.js"></script>
     
<!-- ENDLIBS -->
 
    
<script type="text/javascript" src="extjs/ext-all.js"></script>
<script type="text/javascript" src="reorder.js"></script>

<!-- Common Styles for the examples -->
<link rel="stylesheet" type="text/css" href="extjs/resources/css/example.css" />
</head>
<body>
<script type="text/javascript" src="../examples.js"></script><!-- EXAMPLES -->
<h1>Drag and Drop ordering in a TreePanel</h1>
<p>This example shows basic drag and drop node moving in a tree. In this implementation there are no restrictions and 
anything can be dropped anywhere except appending to nodes marked 
&quot;leaf&quot; (the files). <br></p>
<p>Drag along the edge of the tree to trigger auto scrolling while performing a drag and drop.</p>
<p>In order to demonstrate drag and drop insertion points, sorting was <b>not</b> enabled.</p>
<p>The data for this tree is asynchronously loaded with a JSON TreeLoader.</p>
<p>The js is not minified so it is readable. See <href="reorder.js">reorder.js</a>.</p>

<div id="tree-div" style="overflow:auto; height:300px;width:250px;border:1px solid #c3daf9;"></div>

</body>
</html>



js:
/*
 * Ext JS Library 2.0.1
 * Copyright(c) 2006-2008, Ext JS, LLC.
 * licensing@extjs.com
 *
 * http://extjs.com/license
 
*/

Ext.onReady(
function(){
    
// shorthand
    var Tree = Ext.tree;
   
    
var tree = new Tree.TreePanel({
        el:'tree
-div',
        autoScroll:
true,
        animate:
true,
        enableDD:
true,
        containerScroll: 
true,
        loader: 
new Tree.TreeLoader({
            dataUrl:'http:
//localhost:8080/lab/menus.action'
        })
    });

    
// set the root node
    var root = new Tree.AsyncTreeNode({
        text: 'Ext JS',
        draggable:
false,
        id:'source'
    });
    tree.setRootNode(root);

    
// render the tree
    tree.render();
    root.expand();
});

我已经上传了完整的War文件(包含所有源代码),见:Extjs Tree + JSON + Struts2 的所有示例源代码和war文件下载

posted @ 2008-02-19 09:27 云自无心水自闲 阅读(43620) | 评论 (49)编辑 收藏

Struts2中支持使用List在页面和Action之间直接传递表格数据。下面是一个示例:
public class Person {
int id;
String name;
int age;
float height;
}

这是一个POJO,getter和setting省略了。

action中可以这样使用:

public class MyAction {
public List getPeopleList() { … }
public void setPeopleList( List peopleList ) { … }

}
在我们使用Person类之前,需要添加一个配置文件,MyAction-conversion.properties,把这个文件和MyAction放在一起。
这个文件里只有一行内容:
Element_peopleList=Person
前缀Element_是一个常量,表明等号左边的表达式中跟在这个常量后面的是Action类中一个List类型的字段名。
等号右边的表达式是全类名(包含package)
下面是一个页面的代码片段:
<s:form action="update" method="post" >
<s:iterator value="peopleList" status="stat">
<s:hidden
name="peopleList[%{#stat.index}].id"
value
="%{peopleList[#stat.index].id}"/>
<s:textfield label="Name"
name
="peopleList[%{#stat.index}].name"
value
="%{peopleList[#stat.index].name}"/>
<s:textfield label="Age"
name
="peopleList[%{#stat.index}].age"
value
="%{peopleList[#stat.index].age}" />
<s:textfield label="Height"
name
="peopleList[%{#stat.index}].height"
value
="%{peopleList[#stat.index].height}"/>
<br/>
</s:iterator>
<s:submit value="Update"/>
</s:form>


使用这段代码,Struts2会创建一个Person类的ArrayList,并且用setPersonList这个方法把页面表格中的值传递回Action。
如果你是想从用户界面中动态创建列表值,需要允许Struts2给列表中类的实例。那么在配置文件MyAction-conversion.properties中添加一行:
CreateIfNull_peopleList = true

posted @ 2008-02-12 21:06 云自无心水自闲 阅读(3231) | 评论 (2)编辑 收藏

     摘要: Struts2和Struts相比,一个重大改进就是支持Ajax。 本文主要看一下Struts2中的Div是如何用来输出Ajax结果,其中主要使用了Dojo。 首先,我们先创建一个简单的用例,在这个用例中,将在屏幕上显示一个用户列表,点击列表中的userid时,列表的下方将显示用户的详细信息,显示用户详细信息的这个步骤我们将使用Ajax。 一、创建web.xml <?xml v...  阅读全文

posted @ 2008-02-10 20:56 云自无心水自闲 阅读(12215) | 评论 (8)编辑 收藏

仅列出标题
共29页: First 上一页 13 14 15 16 17 18 19 20 21 下一页 Last