然后當然是要提出解決的辦法,其實挺簡單的(并不是和某些朋友說的那樣--
將jsp內的所有空格和回車符號所有都刪除掉),
在使用完輸出流以后調用以下兩行代碼即可:
out.clear();
out = pageContext.pushBody();
最后這里是一個輸出彩色驗證碼例子(這樣的例子幾乎隨處可見)
imag.jsp
<%@ page import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" %>
<%@ page import="java.io.OutputStream" %>
<%!
Color getRandColor(int fc,int bc){
Random random = new Random();
if(fc>255) fc=255;
if(bc>255) bc=255;
int r=fc+random.nextInt(bc-fc);
int g=fc+random.nextInt(bc-fc);
int b=fc+random.nextInt(bc-fc);
return new Color(r,g,b);
}
%>
<%
try{
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires", 0);
int width=60, height=20;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
OutputStream os=response.getOutputStream();
Graphics g = image.getGraphics();
Random random = new Random();
g.setColor(getRandColor(200,250));
g.fillRect(0, 0, width, height);
g.setFont(new Font("Times New Roman",Font.PLAIN,18));
g.setColor(getRandColor(160,200));
for (int i=0;i<155;i++)
{
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(12);
int yl = random.nextInt(12);
g.drawLine(x,y,x+xl,y+yl);
}
String sRand="";
for (int i=0;i<4;i++){
String rand=String.valueOf(random.nextInt(10));
sRand+=rand;
g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));
g.drawString(rand,13*i+6,16);
}
session.setAttribute("rand",sRand);
g.dispose();
ImageIO.write(image, "JPEG",os);
os.flush();
os.close();
os=null;
response.flushBuffer();
out.clear();
out = pageContext.pushBody();
}
catch(IllegalStateException e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}%>
如有不足之處,歡迎斧正!
BaseDAO.java
其實這一種方式也不是最好的方式,而且依賴tomcat的數據源,開啟了連接后一定要記得關閉連接,這樣管理起來容易出錯,建議可以是使用ibatis替代
public class PageManager
{
private List allRecords = null;//collection儲存同一類型的對象的集合
private int currentPage = 0;//當前頁碼
private int totalPage = 0;//總頁數
private int recordPerPage = -1;//每頁的對象數
private int totalCount=0;//總的對象數
//初始化
public PageManager(List allRecords, int recordPerPage)
{
if (allRecords == null || recordPerPage < 1) return;
this.allRecords = allRecords;
this.recordPerPage = recordPerPage;
this.totalCount=allRecords.size();
if (allRecords.size() % recordPerPage == 0)
this.totalPage = allRecords.size() / recordPerPage;
else
this.totalPage = allRecords.size() / recordPerPage + 1;
this.currentPage = 0;
}
//獲取所有對象集合
public List getAllRecords()
{
return this.allRecords;
}
//獲取當前頁的的對象集合
public List getCurrentPage()
{
return getPage(currentPage);
}
//根據序號獲取該對象所在的頁的對象集合
public List getThePage(int recordno)
{
if (this.allRecords == null || this.allRecords.size() == 0)
{
this.currentPage = 0;
return null;
}
int pageNo=1;
if (recordno < 1) pageNo = 1;
else if (recordno > this.allRecords.size())
pageNo = this.totalPage;
else
{
pageNo=recordno/this.recordPerPage+1;
}
this.currentPage = pageNo;
int pageStart = (pageNo - 1) * this.recordPerPage;
int pageEnd = pageStart + this.recordPerPage - 1;
if (pageEnd > this.allRecords.size() - 1) pageEnd = this.allRecords.size() - 1;
List result =this.allRecords.subList(pageStart, pageEnd+1);
return result;
}
//根據頁碼獲取改頁的對象集合
public List getPage(int pageNo)
{
if (this.allRecords == null || this.allRecords.size() == 0)
{
this.currentPage = 0;
return null;
}
if (pageNo < 1) pageNo = 1;
if (pageNo > this.totalPage) pageNo = this.totalPage;
this.currentPage = pageNo;
int pageStart = (pageNo - 1) * this.recordPerPage;
int pageEnd = pageStart + this.recordPerPage - 1;
if (pageEnd > this.allRecords.size() - 1) pageEnd = this.allRecords.size() - 1;
List result =this.allRecords.subList(pageStart, pageEnd+1);
return result;
}
//獲取下一頁的對象集合
public List getNextPage()
{
return getPage(this.currentPage + 1);
}
//獲取上一頁的對象集合
public List getPreviousPage()
{
return getPage(this.currentPage - 1);
}
//獲取第一頁的對象集合
public List getFirstPage()
{
return getPage(1);
}
//獲取最后一頁的對象集合
public List getLastPage()
{
return getPage(this.totalPage);
}
//獲取總頁數
public int getTotalPage() {
return totalPage;
}
//獲取當前頁碼
public int getCurrentPageCount()
{
return this.currentPage;
}
//獲取對象總數
public int getTotalCount() {
return totalCount;
}
}
在appfuse構建的項目中集成velocity的步驟和碰到的問題 :
1:修改web.xml使得項目支持velocity
(1)定義名為velocity的servlet:
---以上三步其實就是普通java web項目集成velocity的必須要做的工作了。
---下面是使用appfuse中的appgen生成velocity代碼的要做的工作,這里只做了從table出發的生成過程。
4:在項目中extras/appgen/src中創建模板,這里假設創建的兩個文件是List_vm.xdt和Form_vm.xdt
模板的具體內容就要結合xdoclet,velocity和html來編寫,不是一個簡單的工作!
5:編輯extras/appgen下的build.xml文件,使得在使用ant install-detailed的時候能生成數據表對應的vm文件.
(1):在名為gen的target中添加template,原文件有以下的代碼:
這里,templateFile里指定模板文件,destinationFile指定生成的臨時文件。
(2):在名字同樣為gen的target中添加move任務,原文件中有以下代碼:
這樣生成的臨時文件就會被重命名(有點懷疑這樣做的必要性,暫且先這樣做吧)。
(3):在名為merge-common的target中添加copy任務,原文件中有如下代碼
這樣在使用ant install-detailed命令時就會把生成的文件復制到項目的web/vms文件夾下了。
7:修改項目的根目錄下的build.xml:
(1)修改名為copy-web-files的target,使得運行ant deploy時可以將vm文件復制到部署項目的WEB-INFO文件夾下(放在WEB-INF下是為了防止直接訪問 )。
參考的源代碼:
另外,如果不再使用jsp做為view層可以把匹配jsp的fileset節點去掉,這樣就不會復制多余的文件到部署的項目中了。
(2)同名的target 中修改另外一個copy任務(順數第二個),源代碼:
8.如何使用velocity作為view層?
這個框架的優點是:如果熟悉了開發流程,可以大幅度的提高開發速度,如果業務不是很復雜,使用AppGen可以生成60%左右的代碼,而且程序可維護性好,因為作者使用了多個設計模式對各個層面進行了封裝,所以不同的模塊代碼風格出奇的一致,有利于開發人員快速上手,也有利于接收其他開發人員遺留的代碼。
在appgen中修改build.xml的target可以控制生成那些代碼,另外還可以修改模板,使得appgen生成更接近自己需要的代碼。要利用好這些優點的前提是,程序員本身對ant要有相當的了解。
ant new之后在用eclipse打開項目會有五個錯誤--原因是.classpath文件里面聲明了五個src類型的文件夾
碰到的數據庫相關問題----原因在于使用的是pgsql
在建立的項目文件夾里ant setup的時候會出錯,原因在于數據庫的設置錯誤:
解決的方法:
將build.properties里面關于數據庫設置的內容釋放出來,并根據自己的需要修改各個key對應的value
另外:如果還引用database.name還要添加database.name=postgres這樣一個屬性,否則會報錯說database.name不存在
運行 ant test-all
會出現另外一個錯誤:role "test" doesn't exist.
解決的方法:
將properties.xml中的
再運行 ant test-all
在開啟tomcat的時候會出錯(如果tomcat設置和默認的不同)
默認的定義在properties.xml的這幾項設置
另外切換到英文的時候也會找不到國際化的內容,反而裝載了中文的資源文件的內容;這里是因為
ApplicationResources_en.properties文件是空的,估計原因是在裝載資源文件的順序上的原因吧,
我發現ApplicationResources.properties并不是空的,原則上是不會去裝載中文的資源文件啊。
解決這個問題只要將ApplicationResources.properties的內容拷貝到ApplicationResources_en.properties
就可以了(這里有一種治標不治本的味道)。
在初生成版本的用戶列表里面也又亂碼的問題(中文的情況下),在表頭和表尾的地方!
這樣編輯另外一個文件:
displaytag_zh_cn.properties--路徑為web/WEB-INF/classes
切換到英文版的時候發現又裝載了中文的資源內容,檢查原來是缺失了這個文件:
displaytag_en.properties
創建一個文件并使用編輯之!
具體的內容可以參考
http://displaytag.sourceforge.net/configuration.html
現在在項目目錄下運行ant deploy然后訪問,就可以出現一個基本正常的期望站點了。
By the way:ant deploy命令有時候會出現tomcat使用cpu占用率非常高的現象(導致卡機),至少我自己就發生了幾次。:(
現在讓我們來嘗試一下新的工具:AppGen代碼生成:
創建數據表,生成代碼,關聯hibernate文件,這些都不累贅了,因為前面所說的入門文章里面都有說了,照做便是!
不過這里也出現了問題,在我們運行回到項目文件夾里ant deploy之后,去訪問剛生成的文件的添加頁面的時候,你會發現有問題。
No form found under 'mytablenameForm' in locale 'zh_CN'
解決這個問題有兩種方法:
(1)在build/yourapp/WEB-INF/pages/下找到你生成的文件中的form.jsp文件,去掉script標簽內的內容,并去除form的檢驗
(2)在build/yourapp/WEB-INF的validation.xml文件中加入你對應的那個form,當然這里需要至少檢查一個field!
選擇哪種方法依具體情況而定.
再運行ant deploy,在之前出錯的地方就不再出錯了!
關于新生成表的國際化:
AppGen生成代碼的時候只在 ApplicationResources.properties種添加了相關的元素
我們要做的工作就需要修改ApplicationResources_en.properties(直接拷貝)和
ApplicationResources_zh_CN.properties(拷貝并編輯)才能實現國際化
小小的總結一下:
Appfuse的優點:當然是快了,生成的代碼非常清晰,人工干預比較少,部署方便。
目前的現實:appfuse的模板(主要是在國際化方面)似乎本身還有有點問題,出現不少亂碼。
團隊的問題:使用ant,對程序員的要求比較高,特別是習慣了用可視化ide編程的程序員,對這種方式比較抵觸。
--后來我發現可以在AppFuse的目錄下(web/WEB_INF/classes)替換掉之前的原文件,在生成的件就不會亂碼了
哦啊啊啊啊--我打開解壓后appfuse一看,偶的神仙的,appfuse解壓之后就是一個eclipse項目----如果我之間去編輯解壓后的
appfuse,然后在用ant命令(或直接在eclipse用)生成項目,又會怎么樣呢?真又一種迫不及待要試一下的感覺!
Suggestion #2: change the default behaviour to not singularise tablenames. I think it's bad form for a tool to change the names of my data objects without my consent.
Workarounds: specify table names in build.xml, or if you're using the hibernate plugin, fix the table names in the <dbname>-prefs.properties generated by the plugin and re-run middlegen.
第二點中提到改變middlegen的默認行為讓其不去單數化數據表名。
我們要做的有幾個步驟(粗略的看了middlegen源碼做的修改):
1:下載middlegen源碼,下載地址
http://sourceforge.net/project/downloading.php?group_id=36044&use_mirror=jaist&filename=middlegen-2.1-src.zip
2:解壓并編輯MiddlegenTask.java中的代碼
把
private static boolean _singularize = true;
改成
private static boolean _singularize = false;
3:重新編譯并打包成jar,在middlegen的根目錄下輸入命令行命令:ant jar即可
4:將新的middlegen-2.1.jar替換目標項目(已生成)中extras\middlegen\lib\middlegen-2.1的middlegen-2.1.jar
這樣,在生成以S結尾的數據表名對應的代碼就不會出錯了!
但是這樣做始終有不好的地方:在表示對象復數的地方就會出現不盡人意的代碼了,但是不管怎么樣,代碼還是生成出來了,后期的工作就可以依靠手動去修改。
所以還是盡量去遵循不以S結尾的單詞作為數據表名。