两亩三分地

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  17 随笔 :: 20 文章 :: 2 评论 :: 0 Trackbacks

2009年9月28日 #

     摘要: 之前项目有个模块要求用树形解决,附带要实现checkbox,增删修改以及copy/cut/paste等等功能; 因为之前写的人用了xloadTree,其他功能都实现了,但是客户要求要有cookie功能,实现不了麻烦啊~ 正巧现在在学习用Ext,发现Ext的tree本身就很强大基本的功能都可以实现。 Code highlighting produced by Actipro Cod...  阅读全文
posted @ 2010-08-08 23:17 Chucky 阅读(1955) | 评论 (0)编辑 收藏

Border布局作为Ext中整个框架的布局应该说很普遍,一般North放一个应用的Logo bar,West一般会作为导航栏的放置位置;
而Center(East)往往作为整个应用的核心部分,而South位置也往往放置一些应用的版权等信息。

而导航栏一般会采用的呈现方式一般无非是Treepanel或者根据模块放置多个Panel,而多数会采用的布局方式,往往是
Accordion的布局。比如像这样(偷个懒直接用设计器写的):
MyViewportUi = Ext.extend(Ext.Viewport, {
    layout: 'border',
    initComponent: 
function() {
        
this.items = [
            {
                xtype: 'panel',
                title: 'north',
                region: 'north'
            },
            {
                xtype: 'panel',
                title: 'west',
                region: 'west',
                width: 
201,
                split: 
true,
                layout: 'accordion',
                activeItem: 
0,
                items: [
                    {
                        xtype: 'panel',
                        title: 'panel1',
                        layout: 'column',
                        width: 
180,
                        items: [
                            {
                                xtype: 'button',
                                text: 'Button1',
                                scale: 'large'
                            },
                            {
                                xtype: 'button',
                                text: 'Button2',
                                scale: 'large'
                            },
                            {
                                xtype: 'button',
                                text: 'Button3',
                                scale: 'large'
                            },
                            {
                                xtype: 'button',
                                text: 'Button4',
                                scale: 'large'
                            },
                            {
                                xtype: 'button',
                                text: 'Button5',
                                scale: 'large'
                            },
                            {
                                xtype: 'button',
                                text: 'Button6',
                                scale: 'large'
                            }
                        ]
                    },
                    {
                        xtype: 'panel',
                        title: 'panel2'
                    },
                    {
                        xtype: 'panel',
                        title: 'panel3'
                    }
                ]
            },
            {
                xtype: 'panel',
                title: 'east',
                region: 'center'
            },
            {
                xtype: 'panel',
                title: 'south',
                region: 'south'
            }
        ];
        MyViewportUi.superclass.initComponent.call(
this);
    }
});
一个基本的框架就产生了,而问题也随之而来。最主要的问题是IE和FF显示不一样。应该说FF显示很正常,按键根据导航栏的大小,改变每一行显示的数量;
而IE呢,在第一次导航栏宽带变大的时候,一切正常;而当导航栏宽度缩小的时候,原来每行的按键数却并不变。想想这Ext都3.2了,不会还有这么脑残的bug吧;
google了下,国内似乎对这个问题也没有什么讨论的;于是直接去官网的论坛问。

最初别人的提议是,更改westPanel的属性
layout: {
    type: 'accordion',
    autoWidth: 
false
}
等于禁止westPanel的子栏目自动变化宽度,试了如果westPanel的子栏目只有一个工作正常,但是如果多个的话,又悲剧了~

因为每次只有1个子栏目的宽度在变化,所以产生这个问题也不足为奇了。

最后某个网友提供了一个自己写的补丁,问题解决了。
Ext.layout.AccordionPatch = Ext.extend(Ext.layout.Accordion, {
    
    inactiveItems: [],
//ADDED

    
// private
    onLayout : function(ct, target){//ADDED
        Ext.layout.AccordionPatch.superclass.onLayout.call(this, ct, target);
        
if(this.autoWidth === false) {
            
for(var i = 0; i < this.inactiveItems.length; i++) {
                
var item = this.inactiveItems[i];
                item.setSize(target.getStyleSize());
            }
        }
    },
    
// private
    beforeExpand : function(p, anim){//MODFIED
        var ai = this.activeItem;
        
if(ai){
            
if(this.sequence){
                
delete this.activeItem;
                ai.collapse({callback:
function(){
                    p.expand(anim 
|| true);
                }, scope: 
this});
                
return false;
            }
else{
                ai.collapse(
this.animate);
                
if(this.autoWidth === false && this.inactiveItems.indexOf(ai) == -1)//*****
                    this.inactiveItems.push(ai);//*****
            }
        }
        
this.activeItem = p;
        
if(this.activeOnTop){
            p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
        }
        
if(this.autoWidth === false && this.inactiveItems.indexOf(this.activeItem) != -1)//*****
            this.inactiveItems.remove(this.activeItem);//*****
        this.layout();
    }
    
});

Ext.Container.LAYOUTS['accordionpatch'] 
= Ext.layout.AccordionPatch; 
配合补丁,westPanel的属性也要有相应的变化
layout: {
    type:
'accordionpatch',
    autoWidth: false
}




posted @ 2010-08-07 13:24 Chucky 阅读(316) | 评论 (0)编辑 收藏

     摘要: 发表,浏览,回复之后,我们将讨论的是删除和编辑留言。 因为这个只是一个简单的留言板,没有用户认证之类繁琐的事情,所以对于编辑和删除留言,必须输入 正确的id号和password;如果在发表或回复留言的时候没有输入密码的话,就不能对留言进行编辑或者删除。 这里将写的EditAction class与之前的有所不同,extends org.apache.struts.actions.Dispat...  阅读全文
posted @ 2009-10-29 17:22 Chucky 阅读(235) | 评论 (0)编辑 收藏

整个项目第二个重点就是回复留言,我的思路是在浏览留言的时候,回复键传送主题的ID,一个Action Class处理这个请求,
将与这个ID相关的留言查询出来,写入ActionForm。
  1. 打开display.jsp文件,找到下面这几行,后面添加一个form,用来提交查询请求。
     1 <table>
     2     <tr>
     3         <td>
     4             <bean:write name="topic" property="post.subject"/> 留言者:<bean:write name="topic" property="post.name" /> 留言日:<bean:write name="topic" property="post.date" format="yyyy/MM/dd(E) HH:mm" />  No.<bean:write name="topic" property="post.id" />
     5         </td>
     6         <td>
     7             <html:form action="read">
     8                 <input type="hidden" name="id" value="<bean:write name='topic' property='post.id'/>"/>
     9               <html:submit value="回复" />
    10             </html:form>
    11       </td>
    12    </tr>
    13   </table>
    6-11行,就是新加入的对id的一个请求,这里我用了普通的html标志来提交请求,当然我们也可以用<html:hidden name="topic" property="post.id"/>,但是在处理请求的时候,相对的request.getParameter("id"),就要换成
    request.getParameter("post.id")了;或者我们可以在那个Topic类里,添加一个id字段,那么在浏览留言的时候(ListAction的execute方法,list.add(new Topic(post,replies)); 改成list.add(new Topic(post,replies,post.getId()));)<html:hidden name="topic" property="id"/>也可以这样用了。

  2. 添加一个ActionForm bean ThreadForm.java,除了记录一段留言外,还包括了行将用以回复的留言的预处理;
     1 public class ThreadForm extends org.apache.struts.action.ActionForm {
     2     
     3     private int id;
     4     private String name;
     5     private String subject;
     6     private String content;
     7     private String url;
     8     private String email;
     9     private int iconId;
    10     private String icon;
    11     private String password;
    12     private int replyId;
    13     private String font;
    14 
    15     private List icons;
    16 
    17     private Topic topic;
    18 
    19     // accessor methods..
    20     
    21 
    22     public ThreadForm() {
    23         super();
    24         // TODO Auto-generated constructor stub
    25         setUrl("http://");
    26         setFont("#800000");
    27         String sql = "select id,name,src from icon order by id";
    28         QueryRunner qr = DbHelper.getQueryRunner();
    29         List list = null;
    30         try {
    31             list = (List) qr.query(sql, new BeanListHandler(Icon.class));
    32             // TODO Auto-generated constructor stub
    33         } catch (SQLException ex) {
    34             Logger.getLogger(ThreadForm.class.getName()).log(Level.SEVERE, null, ex);
    35         }
    36         setIcons(list);
    37     }
    38     
    39   
    40 }
    41
    3-15行是负责对回复的预处理,ThreadForm()方法中主要也是处理图标。

  3. 这个回复过程其实是2部,1.预处理:包括列出与ID相关的留言,预设回复的默认标题以及对应的回复id (replyId);2.回复留言,添加记录。
    a.  PreReplyAction.java
    public class PreReplyAction extends org.apache.struts.action.Action {
        
        
    /* forward name="success" path="" */
        
    private static final String SUCCESS = "bbs.read";
        
        
    /**
         * This is the action called from the Struts framework.
         * 
    @param mapping The ActionMapping used to select this instance.
         * 
    @param form The optional ActionForm bean for this request.
         * 
    @param request The HTTP Request we are processing.
         * 
    @param response The HTTP Response we are processing.
         * 
    @throws java.lang.Exception
         * 
    @return
         
    */
        @Override
        
    public ActionForward execute(ActionMapping mapping, ActionForm form,
                HttpServletRequest request, HttpServletResponse response)
               {
            ThreadForm f 
    = (ThreadForm) form;
            String id 
    = (String) request.getParameter("id");
            String sql;
            QueryRunner qr 
    = DbHelper.getQueryRunner();
            
            List list 
    = null;
            sql 
    = "select * from guestbook where id = " + id;
            
    try {
                list 
    = (List) qr.query(sql, new BeanListHandler(Post.class));
            } 
    catch (SQLException ex) {
                Logger.getLogger(PreReplyAction.
    class.getName()).log(Level.SEVERE, null, ex);
            }
            Post post 
    = null;
            post 
    = (Post)list.get(0);
            List replies 
    = null;
            sql 
    = "select * from guestbook where replyId =" + id + " order by id";
            
    try {
                replies 
    = (List) qr.query(sql, new BeanListHandler(Post.class));
            } 
    catch (SQLException ex) {
                Logger.getLogger(PreReplyAction.
    class.getName()).log(Level.SEVERE, null, ex);
            }
            
            Topic topic 
    = new Topic(post,replies);
            f.setTopic(topic);
            f.setSubject(
    "Re :" + post.getSubject());
            f.setReplyId(post.getId());

            
    return mapping.findForward(SUCCESS);
        }
    }

    b. ReplyAction.java
     1 public class ReplyAction extends org.apache.struts.action.Action {
     2     
     3     /* forward name="success" path="" */
     4     private static final String SUCCESS = "bbs.reply";
     5     
     6     /**
     7      * This is the action called from the Struts framework.
     8      * @param mapping The ActionMapping used to select this instance.
     9      * @param form The optional ActionForm bean for this request.
    10      * @param request The HTTP Request we are processing.
    11      * @param response The HTTP Response we are processing.
    12      * @throws java.lang.Exception
    13      * @return
    14      */
    15     @Override
    16     public ActionForward execute(ActionMapping mapping, ActionForm form,
    17             HttpServletRequest request, HttpServletResponse response)
    18             throws Exception {
    19         ThreadForm f = (ThreadForm)form;
    20         String sql = "insert into guestbook (name,subject,email,url,content,iconId,password,font,replyId,date,lastReplyTime) " +
    21                 "values(?,?,?,?,?,?,?,?,?,now(),now())";
    22         String content = f.getContent();
    23         content = content.replaceAll(" ""&nbsp;");
    24         content = content.replaceAll("\n","<br>");
    25         String params[] = {f.getName(),f.getSubject(),f.getEmail(),f.getUrl(),content,new Integer(f.getIconId()).toString(),f.getPassword(),f.getFont(),new Integer(f.getReplyId()).toString()};
    26 
    27         QueryRunner qr = DbHelper.getQueryRunner();
    28         try {
    29             qr.update(sql, params);
    30         } catch (SQLException ex) {
    31             Logger.getLogger(ReplyAction.class.getName()).log(Level.SEVERE, null, ex);
    32         }
    33        sql = "update guestbook set lastReplyTime= now() where id = " + f.getReplyId();
    34         try {
    35             qr.update(sql);
    36         } catch (SQLException ex) {
    37             Logger.getLogger(ReplyAction.class.getName()).log(Level.SEVERE, null, ex);
    38         }
    39         return mapping.findForward(SUCCESS);
    40     }
    41 }
    这个基本和添加留言的一直,只是在insert回复记录以后,更新主题留言的最近的回复时间,可以保证浏览留言的时候,该主题能在最前端。

  4. reply.jsp 基本和之前写的jsp页面区别不大,省略了。

  5. 添加相应的forwarding信息。
    <global-forwards>
            
    <forward name="bbs.post" path="/result.jsp"/>
            
    <forward name="bbs.list" path="/display.jsp"/>
            
    <forward name="bbs.read" path="/reply.jsp" />
            
    <forward name="bbs.reply" path="/list.do" />
            
    <forward name="welcome"  path="/Welcome.do"/>
    </global-forwards>
    根据forward的指向,我们可以看到在reply.jsp按下回复键以后,直接转向list.do动作。
    至于action-mapping 没有什么要注意的。

  6. 整个回复过程就此完成。

posted @ 2009-10-28 13:14 Chucky 阅读(343) | 评论 (0)编辑 收藏

     摘要: 既然我们已经成功完成了第一个ActionForm Bean和与之相关的Action Class;后面的专题中将不再详细的去写与他们相关的开发步骤了。 现在我们开始写留言板的主体部分,即对整个留言就行浏览。因为每个post都有一个replyId字段,用来对应其所回复的留言id;如果这个 replyId等于-1的话,即该留言没有对应的回复。好了还是先从这个JSP页面写起。 displ...  阅读全文
posted @ 2009-10-23 17:40 Chucky 阅读(264) | 评论 (0)编辑 收藏

PostAction主要是处理留言添加工作。
  1. 和创建NewForm bean一样,点击Source Packages > com.bbs.struts,右键New > Java Package... 创建一个com.bbs.struts.action的package用于存放所有action类;

  2. 右键com.bbs.struts.action, New > Struts Action...如果New菜单里没有的话,选择other...,categories里选择
    Struts,File types一栏里选择Struts Action ...;

  3. 在New Struts Action面板里面,Class Name填PostAction;Action Path 填/post;按Next


  4. 按照下面的设置,完成对Action的设置


  5. 在struts-config.xml的文档中,IDE自动添加了对PostForm的声明。
    <action-mappings>
            
    <action input="/post.jsp" name="NewForm" path="/post" scope="request" type="com.bbs.struts.action.PostAction"/>
            
    <action path="/Welcome" forward="/welcomeStruts.jsp"/>
    </action-mappings>

  6. 右边的Source Editor中,新建的PostAction.java已经打开了;接下来我们要把记录在NewForm bean里的数据保存进数据库,为了测试的需要,在添加数据以后,将添加成功与否的结果显示在result.jsp上面。
     1     public ActionForward execute(ActionMapping mapping, ActionForm form,
     2             HttpServletRequest request, HttpServletResponse response) {
     3         NewForm f = (NewForm) form;
     4         String sql = "insert into guestbook (name,subject,email,url,content,iconId,password,font,replyId,date,lastReplyTime) " +
     5                 " values(?,?,?,?,?,?,?,?,-1,now(),now())";
     6 
     7         String content = f.getContent();
     8         content = content.replaceAll(" ""&nbsp;");
     9         content = content.replaceAll("\n""<br>");
    10 
    11         String params[] = {f.getName(), f.getSubject(), f.getEmail(), f.getUrl(), content, new Integer(f.getIconId()).toString(), f.getPassword(), f.getFont()};
    12 
    13         QueryRunner qr = DbHelper.getQueryRunner();
    14 
    15         String result = null;
    16         try {
    17             if (qr.update(sql, params) == 1){
    18                 result = "更新成功";
    19             }else{
    20                 result = "更新失败";
    21             }
    22         } catch (SQLException ex) {
    23             Logger.getLogger(PostAction.class.getName()).log(Level.SEVERE, null, ex);
    24         }
    25         f.setResult(result);
    26         return mapping.findForward(SUCCESS);
    27     }
    7,8,9行主要是将content里的空格和回车符号转成html中所对应的空格和回车。

  7. 在PostAction.java,IDE自动给我们设置了一个 private static final String SUCCESS = "success"; 这是为action forward所设置的forward标志,success的名称我们可以自己取,比如我们可以把它改成bbs.post。关键是在结束对这个action class的编程以后,我们需要在struts-config.xml中添加forward声明。在source editor中打开struts-config.xml,右键菜单Struts > Add Forward,在Add Forward的面板里如下设置,按Add完成添加。

按F6 运行项目,浏览器输入:http://localhost:8080/BBS/post.jsp对程序进行测试。如果添加成功的话,下一页将有更新成功的字样。
posted @ 2009-10-23 00:31 Chucky 阅读(445) | 评论 (0)编辑 收藏

ActionForm Bean在Struts里用来保存网页request传递之间的数据。比如我们现在写的NewForm Bean用来收集表格内的信息,
类似于servlet的request.getParamenter()的作用;当用户提交以后,数据将保存在bean内,然后再做处理。
  1. 点击Source Packages > com.bbs.struts,右键New > Java Package... 创建一个com.bbs.struts.form的package用于存放
    所有form;

  2. 右键com.bbs.struts.form, New > Struts ActionForm Bean...如果New菜单里没有的话,选择other...,categories里选择
    Struts,File types一栏里选择Struts ActionForm Bean...;

  3. 为这个ActionForm取名叫NewForm,然后按Finish完成。
    IDE将创建一个NewForm bean,并在右边的Source Editor里面打开它。默认的话,IDE将创造2个一个String型的name和int型的number,2个属性;并且定义了它们的accessor方法。另外IDE将在struts-config.xml里面,添加对这个bean的声明;
    <form-beans>
            
    <form-bean name="NewForm" type="com.bbs.struts.form.NewForm"/>
    </form-beans>

  4. 在Source Editor里面,将原来的name,number字段删除,并删除与之相关的accessor方法。然后为NewForm添加以下字段,这些字段与之前的post.jsp所用到的字段一一对应。
        private String name;
        
    private String subject;
        
    private String content;
        
    private String url;
        
    private String email;
        
    private int iconId;
        
    private String password;
        
    private String font;

        
    private List icons;
        
    private String result;
    利用insert code...功能,添加相应的accessor方法。

  5. 考虑到因为图标的列其实在生成这个网页的时候就自动添加的,所以在这个ActionForm bean的Constructor的方法里面,就要处理icon了,还有就是对字色,网络链接做一下预处理:
        public NewForm() {
            
    super();
            
    // TODO Auto-generated constructor stub
            setUrl("http://");
            setFont(
    "#800000");
            String sql 
    = "select id,name,src from icon order by id";
            QueryRunner qr 
    = DbHelper.getQueryRunner();
            List list 
    = null;
            
    try {
                list 
    = (List) qr.query(sql, new BeanListHandler(Icon.class));
                
    // TODO Auto-generated constructor stub
            } catch (SQLException ex) {
                Logger.getLogger(NewForm.
    class.getName()).log(Level.SEVERE, null, ex);
            }
            setIcons(list);
        }

  6. 同样在validate方法里,添加对subject验证,如果subject为空的话,改名“无题”。
       public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
            ActionErrors errors 
    = new ActionErrors();

            
    if (getSubject() == null || getSubject().length() < 1) {
                setSubject(
    "无题");
            }
            
    return errors;
        }

  7. 第一个ActionForm Bean就完成了。

posted @ 2009-10-22 23:15 Chucky 阅读(228) | 评论 (0)编辑 收藏


之前的准备工作完成,现在算是正式进入struts项目的环节了,首先我们写一个发表留言的jsp页面。
  1. 右键点击BBS项目, 选择 New > JSP, 命名新文件为post. 点击Finish. post.jsp将在右边的编辑器里打开了。

  2. 首先在编辑器中,将<title></title>中间的文字改成发表留言。

  3. 在文件顶部,添加以下2个taglib:
    <%@taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
    <%@taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
    bean tag为用户提供了若干tag,主要针对表单中form bean;html tag用来代替普通的html标签,达到简化操作的目的。

  4. 在<body>里面添加:
    <html:form action="post">

    </html:form>

  5. 从IDE的Palette面板的HTML的分类里将Table拉入<html:form action="post">之间,设置rows 8, columns 2。

  6. 在<td>之间添加数值
    <html:form action="post">
                
    <table border="1">
                    
    <tbody>
                        
    <tr>
                            
    <td>名字</td>
                            
    <td><html:text property="name" /></d>
                        
    </tr>
                        
    <tr>
                            
    <td>邮件</td>
                            
    <td><html:text property="email" /></td>
                        
    </tr>
                        
    <tr>
                            
    <td>题目</td>
                            
    <td><html:text property="subject" /> <html:submit value="发送"/><html:cancel value="重置"/></td>
                        
    </tr>
                        
    <tr>
                            
    <td colspan="2">正文<br>
                                
    <html:textarea cols="60" rows="8" property="content" />
                            
    </td>
                        
    </tr>
                        
    <tr>
                            
    <td>网站</td>
                            
    <td><html:text property="url"/></td>
                        
    </tr>
                        
    <tr>
                            
    <td>图标</td>
                            
    <td>
                                
    <html:select property="iconId">
                                    
    <logic:iterate id="icon" name="NewForm" property="icons">
                                     
    <option value="<bean:write name='icon' property='id'/>"><bean:write name="icon" property="name"/></option>
                                    
    </logic:iterate>
                                
    </html:select>
                            
    </td>
                        
    </tr>
                        
    <tr>
                            
    <td>密码</td>
                            
    <td><html:password property="password"/>(英数8文字内)</td>
                        
    </tr>
                        
    <tr>
                            
    <td>字色</td>
                            
    <td>
                                
    <html:radio property="font" value="#800000"><font color="#800000"></font></html:radio>
                                
    <html:radio property="font" value="#DF0000"><font color="#DF0000"></font></html:radio>
                                
    <html:radio property="font" value="#008040"><font color="#008040"></font></html:radio>
                                
    <html:radio property="font" value="#0000FF"><font color="#0000FF"></font></html:radio>
                                
    <html:radio property="font" value="#C100C1"><font color="#C100C1"></font></html:radio>
                                
    <html:radio property="font" value="#FF80C0"><font color="#FF80C0"></font></html:radio>
                                
    <html:radio property="font" value="#FF8040"><font color="#FF8040"></font></html:radio>
                                
    <html:radio property="font" value="#000080"><font color="#000080"></font></html:radio>
                            
    </td>
                        
    </tr>
                    
    </tbody>
                
    </table>
            
    </html:form>
        
    </body>

    第一个JSP页面就完成了。
考虑到后面的测试,再创建一个result.jsp页面;当post成功/失败的话,通过result.jsp来查看结果
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd"
>
<%@taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<html>
    
<head>
        
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        
<title>留言板</title>
    
</head>
    
<body>
        
<h1><bean:write name="NewForm" property="result" /></h1>
    
</body>
</html>



posted @ 2009-10-21 18:20 Chucky 阅读(223) | 评论 (0)编辑 收藏

正如之前所说的,开发一个struts应用和一般的web应用并没有什么两样。

1. 创建数据库
create database guestbook;

a. guestbook表:用于记录留言的所有信息
CREATE TABLE `guestbook` (
`id`  
int(11NOT NULL AUTO_INCREMENT ,
`name`  
varchar(40) ,
`email`  
varchar(60),
`url`  
varchar(60),
`subject`  
varchar(200),
`content`  
varchar(1024),
`font`  
varchar(100),
`date`  
datetime ,
`replyId`  
int(11)DEFAULT '-1' ,
`iconId`  
int(3),
`lastReplyTime`  
datetime ,
`password`  
varchar(16),
PRIMARY KEY (`id`)
);

 字段 说明
 id  留言编号
 name  留言人姓名
 email  email地址
 url  url地址
 subject  留言标题
 content  留言内容
 iconId  留言使用的表情图标编号
 font  内容字体颜色
 date  留言时间
 replyId  回复留言ID,默认为-1表示不是回复
 lastReplyTime  最近回复时间
 password  留言所用的密码(用于编辑)

b. ICON表:用于记录所有的图标记录
CREATE TABLE `icon` (
`id`  
int(11NOT NULL AUTO_INCREMENT ,
`name`  
varchar(20),
`src`  
varchar(200),
`alt`  
varchar(100),
PRIMARY KEY (`id`)
);

 字段 说明
 id  图标编号
 name  图标名称
 src  图标的位置
 alt  图标的说明

2. JDBC Resource与链接池
  • 给刚刚建的database建立一个连接,Services标签,点击Databases的MySql Server at localhost:3306;
  • 选择刚刚建的guestbook,按右键点击connect;我们可以看到在databases的列表里多了jdbc:mysql://localhost:3306/guestbook的链接;
  • 回到projects标签,点击项目名称BBS,按右键选择New > Other... 在Categories里面选择GlassFish;File types项目下面,选择JDBC Connection Pool,按Next;
  • 在New JDBC Connection Pool面板里,JDBC Connection Pool Name里输入GuestBookPool(随意),Extract from Existiong Connection的下拉菜单里选择刚刚建立的database连接jdbc:mysql://localhost:3306/guestbook,
    其他设置使用默认值即可,按finish结束连接池的创建。
  • 同样在Categories里面选择GlassFish;File types项目下面,选择JDBC Resource,按Next;
  • 在New JDBC Resource面板里,Using Existing JDBC Connection Pool里选择GuestBookPool(与之前创建的连接池对应);
    JNDI Name输入jdbc/bbs(随意),按finish,完成JDBC Resource配置。
3.中文乱码处理 
  记得在做上一个Servlet的项目的时候,在每个servlet处理request的时候(processRequest()方法),都做过一个request.setCharacterEncoding("UTF-8")的操作;将request的内容转成UTF-8的内码,以解决中文乱码问题。
  在Struts的项目里面,我们仍然会遇到中文乱码问题。而我们通过一个创建的CharacterEncodingFilter的辅助类来解决问题。
  •   CharacterEncodingFilter.java
    package com.bbs.struts.util;

    import java.io.IOException;
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;

    /**
     *
     * 
    @author Chucky
     
    */
    public class CharacterEncodingFilter implements Filter {

        
    public void init(FilterConfig filterConfig) throws ServletException {
        }

        
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            request.setCharacterEncoding(
    "UTF-8");
            chain.doFilter(request, response);
        }

        
    public void destroy() {

        }

    }
     
  • 打开web.xml,在Filters的面板中添加以下内容
中文乱码的问题解决了!

4. DbUtils
在处理数据连接的问题上,还是使用DbUtils这个类,详细请看Blog系统开发 5. JDBC的基本操作与DbUtils的使用 内容
这里还是写一个DbHelper的辅助类,来简化连接的操作。
DbHelper.java
package com.bbs.struts.util;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.apache.commons.dbutils.QueryRunner;

/**
 *
 * 
@author Chucky
 
*/
public class DbHelper {

    
public static QueryRunner getQueryRunner() {
        Context context 
= null;
        DataSource ds 
= null;
        
try {
            context 
= new InitialContext();
            ds 
= (DataSource) context.lookup("jdbc/bbs");
        } 
catch (NamingException ex) {
            Logger.getLogger(DbHelper.
class.getName()).log(Level.SEVERE, null, ex);
        }

        QueryRunner qr 
= new QueryRunner(ds);
        
return qr;
    }
}
注意context.lookup()中的数据源,要与之前的数据源匹配。

因为这个bbs的网页设计是按照日月星辰的留言板的页面制作的,所以类似icon之类的数据,直接添加到数据库(假设所有的icon都在
img 目录下,icon素材可以直接到星辰去抓的,sql的脚本)


posted @ 2009-10-21 17:31 Chucky 阅读(431) | 评论 (0)编辑 收藏

根据之前所建立的guestbook表和icon表;现在我们建立Icon类和Post类;
1. Icon类 Icon.java
public class Icon {
    
private int id;
    
private String name;
    
private String src;
    
private String alt;
}
在Icon.java的Source Editor上按右键,点击Insert Code... 选择Getter and Setter...;
在Generate Getter and Setter面板内,选择所有的属性;IDE将自动生成setter/getter方法。

同样建立一个Post类,除了原来guestbook里的字段以外,为了编程的方便再添加一个Icon的属性,相当于Icon类里的src值。
public class Post{
    private
 int id;
    
private String name;
    
private String subject;
    
private String content;
    
private String url;
    
private String email;
    
private int iconId;
    
private String icon;
    
private String password;
    
private Date date;
    
private Date lastReplyTime;
    
private int replyId;
    
private String font;
}
添加相应的getter/setter方法。

除了以上2个类,再建一个Topic类,这个类是一个post和它所有回复的一个集合。
public class Topic {
    
private Post post;
    
private List replies;
}
添加相应的getter/setter方法。




posted @ 2009-10-21 17:05 Chucky 阅读(219) | 评论 (0)编辑 收藏

在使用Netbeans的时候,除了Struts应用所需需要的Struts库文件与配置文件以外,创建一个Struts应用与
创建其他任何一个网络应用没有什么区别。其实创建一个Struts应用的方法和任何一个其他网络应用的方法
都一样。
  • 选择File > New Project. 在Categories里面选择Web。Projects项目下面,选择Web Application然后按Next。
  • 在输入项目名称和位置的面板里面,输入BBS作为项目名称,然后按Next;
  • 在服务器与设置面板里面,选择选择一个你准备用来deploy应用的服务器(如:GlassFish v2.1),同时注意面板下方的
    Context Path的路径与我们的项目名称一致,按Next;
  • 在Framework面板里,选择Struts

    将Application Resource里的名称com.myapp.struts.ApplicationResource改成com.bbs.struts.ApplicationResource .
  • 按下Finish,Struts的一个应用就建立完成了。
在项目管理器里面,所有的Struts指定的配置文件以及应用deploy所用的文件,都被放置在Configuration Files的目录里。
打开web.xml,我们可以看一下文件是如何管理Struts的。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation
="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    
<servlet>
        
<servlet-name>action</servlet-name>
        
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
        
<init-param>
            
<param-name>config</param-name>
            
<param-value>/WEB-INF/struts-config.xml</param-value>
        
</init-param>
        
<init-param>
            
<param-name>debug</param-name>
            
<param-value>2</param-value>
        
</init-param>
        
<init-param>
            
<param-name>detail</param-name>
            
<param-value>2</param-value>
        
</init-param>
        
<load-on-startup>2</load-on-startup>
        
</servlet>
    
<servlet-mapping>
        
<servlet-name>action</servlet-name>
        
<url-pattern>*.do</url-pattern>
    
</servlet-mapping>
    
<session-config>
        
<session-timeout>
            30
        
</session-timeout>
    
</session-config>
    
<welcome-file-list>
        
<welcome-file>index.jsp</welcome-file>
        
</welcome-file-list>
    
</web-app>

posted @ 2009-10-20 18:07 Chucky 阅读(200) | 评论 (0)编辑 收藏

到16节 和项目相关的东西,觉得已经没什么要写的了;基本还剩下一些css之类的页面设计和美化工作。
这方面没有什么感觉,总之把跟这个项目相关的东西放在一起(src和web相关的东西);有兴趣可以下来看看。
blog_servlet

Ok 跟blog_servlet相关的东西到这里结束了,下周开始做blog Struts相关的项目。

posted @ 2009-10-08 19:04 Chucky 阅读(109) | 评论 (0)编辑 收藏

     摘要: 对于表格数据处理的话,displayTag有很大的优势;但是有些时候还得自己动手做点工作; 我自己写了一个PageTag的类来处理一些简单的工作。 PageTag.java Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->&n...  阅读全文
posted @ 2009-10-07 18:58 Chucky 阅读(242) | 评论 (0)编辑 收藏

     摘要: 上一节谈了displaytag的基本用法,这一节就结合项目来看一下。按照常理,可能使用到displaytag的地方, 集中在管理页面里,譬如对博文的管理或者是针对comments的管理;相对而言category似乎并不需要使用分页; 很少会有人开几十个不同的分类吧 XD。 好吧,我们来比较一下,displaytag和原来的代码有什么不同。 这是原先的页面 网页的code: ...  阅读全文
posted @ 2009-10-07 16:37 Chucky 阅读(210) | 评论 (0)编辑 收藏

随着博文的增加或者评论的增加,是必要考虑一下分页问题。
在这个项目里,对于分页问题,我采取2种处理的方法。对于管理页面表格型的记录采用displayTag组件;
而对于那些博文或者评论采用自己写的PageTags类来管理。

1. displayTag组件

上面的图片可以看出:事实上这个display tag库就是用来显示表格的;给它一个对象的list,它将搞定类似显示列,排序,分页等等事务,并以表格的形式显示出来。

a. 安装:
   将displaytag-version.jar 文件与以下5个文件一起放置在应用的WEB-INF/lib目录里
  • commons-logging
  • commons-lang
  • commons-collections
  • commons-beanutils
  • log4j
   在使用的时候,在jps页面中,
<%@ taglib uri="http://displaytag.sf.net" prefix="display" %>

b. 使用:
   这里使用blog列表做例子
 <% List blogs = (List) request.getAttribute("blogs");%>
    
<h2>文章管理</h2>
<display:table name="blogs" htmlId="tab" pagesize="10" />
每页显示10条记录

对于每条记录我们可能有显示要求
<display:table name="blogs" id=" blog" htmlId="tab" pagesize="10" >
    
<display:column property="id" title="编号"/>
    
<display:column property="title" title="主题"/>
    
<display:column property="category" title="类别"/>
    
<display:column property="date" format="{0,date,yyyy-MM-dd  HH:mm:ss}" title="日期",sortable="true"/>
    
<display:column title="操作">
        
<href="/Blogs/BlogServlet?method=edit&id=${blog.id}"><img src="/Blogs/admin/img/edit.gif" border=0 /></a>
                
<href="/Blogs/BlogServlet?method=delete&id=${blog.id}" onclick="javascript:return del()"><img src="/Blogs/admin/img/delete.gif" border=0 /></a>|
                
<href="/Blogs/CommentServlet?method=list&bid=${blog.id}">管理评论</td> 
    
</display:column>
    
</display:table>
比如id字段显示为 标号;title主题;category类别;日期么安装年-月-日 小时:分钟:秒的格式显示;并且可以手动选择排序。
是不是很简单。

c.其他问题:
  配置文件displaytag.properties,需要放置在src目录的根部,主要显示一些文字之类的设置,支持localization,但是要注意的是,文件必须转换成unicode才可以正常显着。
以下是displaytag_Zh_CN.properties的示例:
 1 #sort.behavior=list
 2 #sort.amount=list
 3 #basic.empty.showtable=true
 4 #basic.msg.empty_list=No results matched your criteria.
 5 #paging.banner.placement=top
 6 #paging.banner.onepage=<span class="pagelinks"></span>
 7 export.types=csv excel xml pdf rtf
 8 export.excel=true
 9 export.csv=true
10 export.xml=true
11 export.pdf=true
12 export.rtf=true
13 export.excel.class=org.displaytag.export.excel.DefaultHssfExportView
14 export.pdf.class=org.displaytag.export.DefaultPdfExportView
15 export.rtf.class=org.displaytag.export.DefaultRtfExportView
16 # if set, file is downloaded instead of opened in the browser window
17 #export.[mymedia].filename=
18 paging.banner.placement=bottom
19 # messages
20 
21 basic.msg.empty_list=\u6CA1\u6709\u7B26\u5408\u6761\u4EF6\u7684\u8BB0\u5F55
22 basic.msg.empty_list_row=<tr class="empty"><td colspan="{0}">\u6CA1\u6709\u7B26\u5408\u6761\u4EF6\u7684\u8BB0\u5F55</td></tr>
23 error.msg.invalid_page=\u65E0\u6548\u9875\u9762
24 
25 export.banner=<div class="exportlinks">Export options: {0}</div>
26 export.banner.sepchar= |
27 
28 paging.banner.item_name=
29 paging.banner.items_name=
30 
31 paging.banner.no_items_found=
32 paging.banner.one_item_found=
33 paging.banner.all_items_found=
34 paging.banner.some_items_found=
35 
36 paging.banner.full=<span class="pagelinks"><font align>[<a href="{1}">|<</a>/<a href="{2}"><</a>] {0[<a href="{3}">></a>/<a href="{4}">>|</a>]</span>
37 paging.banner.first=<span class="pagelinks">[\u9996\u9875/\u4E0A\u4E00\u9875] {0[<a href="{3}">\u4E0B\u4E00\u9875</a>/<a href="{4}">\u5C3E\u9875</a>]</span>
38 paging.banner.last=<span class="pagelinks">[<a href="{1}">\u9996\u9875</a>/<a href="{2}">\u4E0A\u4E00\u9875</a>] {0[\u4E0B\u4E00\u9875/\u5C3E\u9875]</span>
39 paging.banner.onepage=<span class="pagelinks">{0}</span>
40 
41 paging.banner.page.selected=<strong>{0}</strong>
42 paging.banner.page.link=<a href="{1}" title="{0}">{0}</a>
43 paging.banner.page.separator=, \
38行paging.banner.placement=bottom 指定分页栏出现在表格的下面,当然还有top/both两个选择。
  
 

posted @ 2009-10-05 17:07 Chucky 阅读(266) | 评论 (0)编辑 收藏

到11节基本的东西都已经实现了,剩下的都是一点细节问题;比如由于注册用户和普通浏览用户权限不同,所以大家看的也有所不同;
在项目设计的时候,普通用户可以看博客,发表评论;为了避免不必要的麻烦,将普通用户的操作特别的写一个servlet,这样也比较容易控制。
HomeServlet主要就是负责这个任务。
在HomeServlet里面主要就是两个方法,为了配合以后的页面设计,相对之前的BlogServlet等等,相对复杂一点(其实还好)。

让我们来看看这个Sql语句的作用
sql= select b.id as id,b.title as title,b.content as content,b.date as date,c.name as category,categoryId,comments from
(
select blog.id as id ,blog.title as title,blog.category_id as categoryId,count(comment.blog_id) as comments,blog.content as content,blog.date as date from blog
left
 join comment on blog.id = comment.blog_id group by blog.id) as b, category c
where categoryId = c.id
order by date desc;
首先
select blog.id as id ,blog.title as title,blog.category_id as categoryId,count(comment.blog_id) as comments,blog.content as content,blog.date as date from blog
left join comment on blog.id = comment.blog_id group by blog.id
comment表中对blog_id一致的记录做统计,与blog表左连接;
然后再blog新表与category根据categoryId做连接。

然后修改一下Blog类,添加一个comments属性(记录此blog对象所包含的评论数目)。

2.对blog.content做下处理,在显示所有博文的时候,对blog.content的内容做一个简报。
很简单的一个getBriefContent()方法:
public String getBriefContent() {
        StringBuffer briefContent 
= new StringBuffer(content);
        
int length = 200;
        
if (briefContent.length() < length) {
            length 
= briefContent.length();
        }
        briefContent 
= briefContent.delete(length, briefContent.length());

        
//filter html mark;
        briefContent.append(" ..");
        
return briefContent.toString();
    }
限定200字符长度,如果博文内容多于200字符,那么取前200字符;否则直接贴上博文内容。

3.对blog.content另一个修改。因为写博文的时候,可能所选用的字体啊什么每次都不同,以至于在浏览所有博文的时候会很乱;
所以以下doFilter(StringBuffer sb)方法,主要对文字进行过滤,将充满HTML MARK的文章过滤一下。
private StringBuffer doFilter(StringBuffer source) {
        StringBuffer header 
= new StringBuffer(source);
        
while((header.indexOf("<")!=-1)&&(header.indexOf(">")!=-1)){
           
int startPos = header.indexOf("<");
           
int endPos = header.indexOf(">");
            header 
= header.delete(startPos, endPos+1);
        }
        
return header;
    }
因此getBriefContent()方法也要插上一句(Line 3):
 1 public String getBriefContent() {
 2         StringBuffer briefContent = new StringBuffer(content);
 3         briefContent = doFilter(briefContent);
 4         int length = 200;
 5         if (briefContent.length() < length) {
 6             length = briefContent.length();
 7         }
 8         briefContent = briefContent.delete(length, briefContent.length());
 9 
10         //filter html mark;
11         briefContent.append(" ..");
12         return briefContent.toString();
13     }



posted @ 2009-10-05 16:26 Chucky 阅读(146) | 评论 (0)编辑 收藏

我们大家都有使用博客或者其他类似系统的经验,往往都是通过用户验证以后,才进行其他的操作。
上一节,在处理完login事务以后,我们可以访问某个页面对自己的博文或者博文分类等等进行操作。
但是由于网页的关系,如果没有对每页进行用户认证,而我们知道准确的地址的话,我们可以直接访问地址来对数据进行操作。
比如:
http://localhost:8080/Blog/BlogServlet?method=list
可以查看所有的博文;而
http://localhost:8080/Blog/BlogServlet?method=delete&cid=1
这个地址可以对编号为1的博文进行删除操作。
所以我们必须对每一页或者没一次操作进行用户认证。因为user对象是放置在session中的,所有我们可以每次通过检测session内容来达到验证的效果。

在这里,我写了一个辅助类UserValidator,来简化操作。
package com.blog.utils;

import com.blog.User;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 *
 * 
@author Chucky
 
*/
public class UserValidator {
    
public static boolean isValid(HttpServletRequest request){
        HttpSession session 
= request.getSession();
        User user 
= (User) session.getAttribute("user");
        
return user!=null?true:false;
    }
}
一般Servlet的里面,可以直接把UserValidator的检验直接放置在processRequest方法里,如果检验失败的话,转到用户登录界面
 1 protected void processRequest(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3         response.setContentType("text/html;charset=UTF-8");
 4         request.setCharacterEncoding("UTF-8");
 5 
 6         String method = request.getParameter("method");
 7 
 8         if (!UserValidator.isValid(request)) {
 9             response.sendRedirect(request.getContextPath()+"/admin/");
10         } else {
11             if (method.equals("add")) {
12                 add(request, response);
13             } else if (method.equals("delete")) {
14                 delete(request, response);
15             } else if (method.equals("edit")) {
16                 preEdit(request, response);
17             } else if (method.equals("update")) {
18                 update(request, response);
19             } else if (method.equals("list")) {
20                 list(request, response);
21             } else if (method.equals("get")) {
22                 get(request, response);
23             } else if (method.equals("preAdd")) {
24                 preAdd(request, response);
25             }
26         }
27     }
而一些直接读取的jsp页面,也可以把验证直接写在页面里。
<% User user = (User)session.getAttribute("user");
   if (user == null){
   
response.sendRedirect(request.getContextPath()+"/admin/");
   }
%>


posted @ 2009-09-30 16:47 Chucky 阅读(216) | 评论 (0)编辑 收藏

UserServlet主要用于用户登录,退出以及密码修改方面的事务。鉴于对网络应用的安全性考虑,
所以user将被写在session里面,用以在某些管理页面达到认证作用。
 1 private void login(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3         String userName = request.getParameter("username");
 4         String password = request.getParameter("password");
 5         String sql = "select id,username,password from users where username = ? and password = ?";
 6         String params[] = {userName, password};
 7         List users = null;
 8 
 9         QueryRunner qr = DbHelper.getQueryRunner();
10         try {
11             users = (List) qr.query(sql, new BeanListHandler(User.class), params);
12         } catch (SQLException ex) {
13             Logger.getLogger(UserServlet.class.getName()).log(Level.SEVERE, null, ex);
14         }
15         if (users.size()!=0) {
16             User user = (User) users.get(0);
17             HttpSession session = request.getSession();
18             session.setAttribute("user", user);
19             response.sendRedirect(request.getContextPath()+"/BlogServlet?method=list");
20         } else {
21             request.setAttribute("message""错误的用户名或密码");
22             request.getRequestDispatcher("/admin/login.jsp").forward(request, response);
23         }
24     }

logout相对很简单,使session失效即可
1 private void logout(HttpServletRequest request, HttpServletResponse response)
2             throws ServletException, IOException {
3         HttpSession session = request.getSession();
4         session.invalidate();
5         response.sendRedirect(request.getContextPath());
6     }

modifyPassword
 1  private void modify(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3         String oldPassword = request.getParameter("oldPassword");
 4         String newPassword = request.getParameter("newPassword");
 5         String confirmPassword = request.getParameter("confirmPassword");
 6 
 7         HttpSession session = request.getSession();
 8         User user = (User) session.getAttribute("user");
 9         if (!user.getPassword().equals(oldPassword)) {
10             request.setAttribute("message""与原密码不匹配");
11         } else {
12             if (!newPassword.equals(confirmPassword)) {
13                 request.setAttribute("message""新密码与确认密码不匹配");
14             } else {
15                 String sql = "update users set password =? where id = "+ user.getId();
16                 QueryRunner qr = DbHelper.getQueryRunner();
17                 try {
18                     qr.update(sql, newPassword);
19                 } catch (SQLException ex) {
20                     Logger.getLogger(UserServlet.class.getName()).log(Level.SEVERE, null, ex);
21                 }
22                  request.setAttribute("message""密码修改成功");
23             }
24         }
25         request.getRequestDispatcher("/admin/modifyPassword.jsp").forward(request, response);
26     }


posted @ 2009-09-30 14:22 Chucky 阅读(203) | 评论 (0)编辑 收藏

为了让博文编辑更方便,这里介绍一下FCKeditor这个组件, 在这个项目里我们主要利用这个组件的工具栏
 

FCKeditor提供了很详细的文档,关于FCKeditor的安装,软件本身提供了对多种语言的支持,根据项目的需要,这里着重介绍javascript的安装方法。
首先在网页的表头添加下面的声明
<script type="text/javascript" src="fckeditor/fckeditor.js"></script>
接下来有3种不同的方法使用FCKeditor,
方法一. inline方式 在网页body部分,把编辑器放在你想放的地方(通常在表单里面),在该位置添加以下脚本:
<script type="text/javascript">
var oFCKeditor = new FCKeditor('FCKeditor1');
oFCKeditor.BasePath 
= "/fckeditor/";
oFCKeditor.Create();
</script>
方法一实例
<html>
<head>
<title>FCKeditor - Sample</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="robots" content="noindex, nofollow">
<script type="text/javascript" src="fckeditor/fckeditor.js"></script>
</head>
<body>
<form>
<script type="text/javascript">
var oFCKeditor = new FCKeditor('FCKeditor1');
oFCKeditor.BasePath 
= "/fckeditor/";
oFCKeditor.Create();
</script>
</form>
</body>
</html>

方法二 替换TextArea方式
1.先在Head部位添加onload方法
<script type="text/javascript">
window.onload 
= function()
{
var oFCKeditor = new FCKeditor( 'MyTextarea' ) ;
oFCKeditor.BasePath 
= "/fckeditor/" ;
oFCKeditor.ReplaceTextarea() ;
}
</script>
2.在<body>部分 添加并替换原先的TextArea
<textarea id="MyTextarea" name="MyTextarea">This is <b>the</b> initial value.</textarea>
注意 textarea的名字和FCKeditor的对象名称一致

现在我们就可以使用一个很漂亮方便的工具栏了


但是在个漂亮的工具栏Font里面是没有宋体,黑体之类的中文字体的,所以在使用前,我们还要做一定的修改。
打开fckeditor/fckconfig.js,找到并修改FCKConfig.FontNames如下
FCKConfig.FontNames        = '宋体;黑体;隶书;楷体_GB2312;幼圆;Arial;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana' ;

好了经过安装FCKeditor这个编辑器基本就可以使用了。
值得注意的是,FCKeditor的属性是case sensitive,所以在使用的时候千万注意。

posted @ 2009-09-29 17:16 Chucky 阅读(110) | 评论 (0)编辑 收藏

相对于上一篇的CategoryServlet,BlogServlet相对复杂一些。
不如在做添加博文的时候,我们要考虑的不仅仅是blog本身的主题,内容还要考虑blog所对应的类别;
一般我们把类别做成一个List以供选择。所以在blog添加的前,我们首先要处理category信息,那么
如果要添加blog的话,首先要做的是预处理category。
 1 private void preAdd(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3         List categories = null;
 4         String sql = "select id,name from category order by name";
 5         QueryRunner qr = DbHelper.getQueryRunner();
 6         try {
 7             categories = (List) qr.query(sql, new BeanListHandler(Category.class));
 8         } catch (SQLException ex) {
 9             Logger.getLogger(BlogServlet.class.getName()).log(Level.SEVERE, null, ex);
10         }
11         request.setAttribute("categories", categories);
12         request.getRequestDispatcher("/admin/addBlog.jsp").forward(request, response);
13     }
从code上看,预处理与blog类并没有关系,而是针对category的。

在list所有blog记录的时候,我们同样要考虑到category信息,
 1 private void list(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3         String sql = "select b.id as id,title,content,date,c.name as category, c.id as categoryId from blog b,category c where category_id=c.id order by b.date desc";
 4         QueryRunner qr = DbHelper.getQueryRunner();
 5         List blogs = null;
 6         try {
 7             blogs = (List) qr.query(sql, new BeanListHandler(Blog.class));
 8         } catch (SQLException ex) {
 9             Logger.getLogger(BlogServlet.class.getName()).log(Level.SEVERE, null, ex);
10         }
11         request.setAttribute("blogs", blogs);
12         request.getRequestDispatcher("/admin/adminBlogList.jsp").forward(request, response);
13     }
第3行的sql语句将blog表与category表关联起来,运行该SQL命令也成功找到相应的数据;但是在程序里,对应的JSP显示却不成功,与blog相关的数据正确,但是与categoryId对应的
category name(程序中的Blog类里的category)没有显示出来,数据显示是null。
这是因为DbUtils 在做表到对象的映射时要求列名和对象的属性名必须一致,也就是说对应blog类里的category属性正确的名称应该是name。
所以当
String sql = "select b.id as id,title,content,date,c.name as category, c.id as categoryId from blog b,category c where category_id=c.id order by b.date desc";
QueryRunner不能将数据映射到category属性里。在发现并解决了DbUtils项目的一个问题指出,问题的关键是DbUtils在处理数据表的时候是使用getColumnName()方法
BasicRowProcessor.java
 1 /** 
 2      * Convert a <code>ResultSet</code> row into a <code>Map</code>.  This 
 3      * implementation returns a <code>Map</code> with case insensitive column
 4      * names as keys.  Calls to <code>map.get("COL")</code> and 
 5      * <code>map.get("col")</code> return the same value.
 6      * @see org.apache.commons.dbutils.RowProcessor#toMap(java.sql.ResultSet)
 7      */
 8     public Map toMap(ResultSet rs) throws SQLException {
 9         Map result = new CaseInsensitiveHashMap();
10         ResultSetMetaData rsmd = rs.getMetaData();
11         int cols = rsmd.getColumnCount();
12 
13         for (int i = 1; i <= cols; i++) {
14             result.put(rsmd.getColumnName(i), rs.getObject(i));
15         }
16 
17         return result;
18     }
BeanProcessor.java
 1     /**
 2      * The positions in the returned array represent column numbers.  The 
 3      * values stored at each position represent the index in the 
 4      * <code>PropertyDescriptor[]</code> for the bean property that matches 
 5      * the column name.  If no bean property was found for a column, the 
 6      * position is set to <code>PROPERTY_NOT_FOUND</code>.
 7      * 
 8      * @param rsmd The <code>ResultSetMetaData</code> containing column 
 9      * information.
10      * 
11      * @param props The bean property descriptors.
12      * 
13      * @throws SQLException if a database access error occurs
14      *
15      * @return An int[] with column index to property index mappings.  The 0th 
16      * element is meaningless because JDBC column indexing starts at 1.
17      */
18     protected int[] mapColumnsToProperties(ResultSetMetaData rsmd,
19             PropertyDescriptor[] props) throws SQLException {
20 
21         int cols = rsmd.getColumnCount();
22         int columnToProperty[] = new int[cols + 1];
23         Arrays.fill(columnToProperty, PROPERTY_NOT_FOUND);
24 
25         for (int col = 1; col <= cols; col++) {
26             String columnName = rsmd.getColumnName(col);
27             for (int i = 0; i < props.length; i++) {
28 
29                 if (columnName.equalsIgnoreCase(props[i].getName())) {
30                     columnToProperty[col] = i;
31                     break;
32                 }
33             }
34         }
35 
36         return columnToProperty;
37     }
以上2段程序 读了就会发现问题所在了。DbUtils利用getColumnName()来处理列名,所以类似c.name as category, c.id as categoryId的语句并不适用与DbUtils。
解决的方法就是将以上2段程序中的getColumnName()方法改成getColumnLabel(),然后重新编译DbUtils源文件。然后将fixed的DbUtils文件重新加入库就可以解决问题了。
commons-dbutils-1.2_fixed.jar

BlogServlet中其他方法就不一一介绍了。





posted @ 2009-09-29 13:52 Chucky 阅读(119) | 评论 (0)编辑 收藏

     摘要: adminCategoryList.jsp 管理Category数据,对其进行修改或删除操作 Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --> 1 <%@ page language=...  阅读全文
posted @ 2009-09-28 18:47 Chucky 阅读(101) | 评论 (0)编辑 收藏

CategoryServlet,正如第4篇中提到的这个Servlet主要是针对Category数据的操作,包括添加,删除,修改,更新等等。
之所以拿CategoryServlet纯粹因为它比较简单。

对于CategoryServlet的基本思路是:接收requst传来的参数method,然后在根据method的要求来进行不同的操作。
 1 protected void processRequest(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3         response.setContentType("text/html;charset=UTF-8");
 4         request.setCharacterEncoding("UTF-8");
 5         String method = request.getParameter("method");
 6         if (method.equals("add")) {
 7             add(request, response);
 8         } else if (method.equals("delete")) {
 9             delete(request, response);
10         } else if (method.equals("edit")) {
11             preEdit(request, response);
12         } else if (method.equals("update")) {
13             update(request, response);
14         } else if (method.equals("list")) {
15             list(request, response);
16         }
17 }
直接添加这些方法,netbeans会有无法找到对应方法的提示,


点击黄色小灯泡,IDE自动生成对应的方法,建议在这些方法后面添加throws语句。例:
1 private void add(HttpServletRequest request, HttpServletResponse response)
2             throws ServletException, IOException {
3
4         }

a. add方法:接收分类名称(category.name),QueryRunner对象根据sql命令执行update操作,request传回结果(比如:转到对应页面)
 1 private void add(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3         String name = request.getParameter("name");
 4         String sql = "insert into category (name) values (?)";
 5         String params[] = {name};
 6         QueryRunner qr = DbHelper.getQueryRunner();
 7         try {
 8             qr.update(sql, params);
 9         } catch (SQLException ex) {
10             Logger.getLogger(CategoryServlet.class.getName()).log(Level.SEVERE, null, ex);
11         }
12         list(request,response);
13     }

b. delete方法:接收分类类别(category.id),QueryRunner对象根据sql语句执行update操作,request传回结果(比如:转到对应页面)
 1 private void delete(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3         String id = request.getParameter("id");
 4         String sql = "delete from category where id = "+id;
 5         
 6         QueryRunner qr = DbHelper.getQueryRunner();
 7         try {
 8             qr.update(sql);
 9         } catch (SQLException ex) {
10             Logger.getLogger(CategoryServlet.class.getName()).log(Level.SEVERE, null, ex);
11         }
12         
13         list(request,response);
14     }

c. preEdit方法:接收分类类别(category.id),QueryRunner对象根据sql语句执行query操作,request传回结果,转入对应编辑页面;
 1 private void preEdit(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3         String id = request.getParameter("id");
 4         String sql = "select id,name from category where id = "+id;
 5         List categories = null;
 6         Category category = null;
 7         
 8         QueryRunner qr = DbHelper.getQueryRunner();
 9         try {
10             categories = (List) qr.query(sql, new BeanListHandler(Category.class));
11         } catch (SQLException ex) {
12             Logger.getLogger(CategoryServlet.class.getName()).log(Level.SEVERE, null, ex);
13         }
14         
15         if (categories != null){
16             category = (Category)categories.get(0);
17         }
18         request.setAttribute("category", category);
19         request.getRequestDispatcher("/admin/editCategory.jsp").forward(request, response);
20     }

d. update方法:接收分类名称(name),编号(id),QueryRunner对象根据sql语句执行update操作,request传回结果(比如:转到对应页面);
 1  private void update(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3         String id = request.getParameter("id");
 4         String name = request.getParameter("name");
 5         String sql = "update category set name = ? where id = ?";
 6         String params[] = {name,id};
 7         
 8         QueryRunner qr = DbHelper.getQueryRunner();
 9         try {
10             qr.update(sql, params);
11         } catch (SQLException ex) {
12             Logger.getLogger(CategoryServlet.class.getName()).log(Level.SEVERE, null, ex);
13         }
14         list(request,response);
15     }

e. list方法:list所有相关的分类,request传回结果(比如:转到对应页面);
 1  private void list(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3         String sql = "select id, name from category order by name";
 4         List categories = null;
 5 
 6         QueryRunner qr = DbHelper.getQueryRunner();
 7         try {
 8             categories = (List) qr.query(sql, new BeanListHandler(Category.class));
 9         } catch (SQLException ex) {
10             Logger.getLogger(CategoryServlet.class.getName()).log(Level.SEVERE, null, ex);
11         }
12 
13         request.setAttribute("categories", categories);
14         request.getRequestDispatcher("/admin/adminCategoryList.jsp").forward(request, response);
15     }


posted @ 2009-09-28 17:12 Chucky 阅读(103) | 评论 (0)编辑 收藏

我们都知道一个数据系统的核心就是JDBC的编程,对数据进行操作,主要包括添加,删除,更新以及查询。
在对数据进行操作之前首先要做的是:
   
    1.加载jdbc驱动程序;
    2.建立到指定数据库的连接(连接池/数据源);
    3.提交数据库操作命令;
    4.取得结果。

下面看一下BlogServlet中关于add方法中的 code5-1
 1
 1 private void add(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException{
 3         response.setContentType("text/html;charset=UTF-8");
 4         request.setCharacterEncoding("UTF-8");
 5 
 6         String title = request.getParameter("title");
 7         String content = request.getParameter("content");
 8         String categoryId = request.getParameter("category");
 9 
10         String sql =  "insert into blog(title,content,category_id,date) values(?,?,?,now())";
11         String params[] = {title,content,categoryId};
12         QueryRunner qr = DbHelper.getQueryRunner();
13         int result = 0;
14 
15         try {
16           result = qr.update(sql, params);
17         } catch (SQLException ex) {
18             Logger.getLogger(BlogServlet.class.getName()).log(Level.SEVERE, null, ex);
19         }
20     }

在后面的文章中我们会提到apache提供的commons-dbutils-1.2jar有点小问题,这个我们以后还会提到。

由于每次对jdbc编程少不了建立数据源,获取数据源,建立连接的工作,所以这里再提供一个辅助类DbHelper来完成以上工作。
DbHelper.java (code 5-2)
 1 package com.blog.utils;
 2 
 3 import java.util.logging.Level;
 4 import java.util.logging.Logger;
 5 import javax.naming.Context;
 6 import javax.naming.InitialContext;
 7 import javax.naming.NamingException;
 8 import javax.sql.DataSource;
 9 import org.apache.commons.dbutils.QueryRunner;
10 
11 /**
12  *
13  * @author Chucky
14  */
15 public class DbHelper {
16 
17     public static QueryRunner getQueryRunner() {
18         DataSource ds = null;
19         Context context = null;
20         try {
21             context = new InitialContext();
22             ds = (DataSource) context.lookup("jdbc/Blog");
23         } catch (NamingException ex) {
24             Logger.getLogger(DbHelper.class.getName()).log(Level.SEVERE, null, ex);
25         }
26         QueryRunner qr = new QueryRunner(ds);
27         return qr;
28     }
29 }

现在通过DbUtils库和DbHelper辅助类的使用,原先code 5-1可以简化成
 1 private void add(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException{
 3         response.setContentType("text/html;charset=UTF-8");
 4         request.setCharacterEncoding("UTF-8");
 5 
 6         String title = request.getParameter("title");
 7         String content = request.getParameter("content");
 8         String categoryId = request.getParameter("category");
 9 
10         String sql =  "insert into blog(title,content,category_id,date) values(?,?,?,now())";
11         String params[] = {title,content,categoryId};
12         QueryRunner qr = DbHelper.getQueryRunner();
13         int result = 0;
14 
15         try {
16           result = qr.update(sql, params);
17         } catch (SQLException ex) {
18             Logger.getLogger(BlogServlet.class.getName()).log(Level.SEVERE, null, ex);
19         }
20     }
QueryRunner类是DbUtils的核心类,只要通过query()方法对数据查询或update()对数据删除delete/添加insert/更新update;
在后面的文章中,会详细解释。

posted @ 2009-09-28 16:24 Chucky 阅读(493) | 评论 (2)编辑 收藏

项目开发的准备工作已经差不多了,现在需要的是与数据表对应的数据类。
1. 数据类
按照编程习惯首先创建package,项目名称右键选择New->Java package; package name填写com.blog

在com.blog下面创建与数据表对应的Blog,Comment,Category以及User这4个类
blog.java
 1 /*
 2  * To change this template, choose Tools | Templates
 3  * and open the template in the editor.
 4  */
 5 
 6 package com.blog;
 7 
 8 import java.util.Date;
 9 
10 /**
11  *
12  * @author Chucky
13  */
14 public class Blog {
15     private int id;
16     private String title;
17     private String content;
18     private Date date;
19     private int categoryId;
20     private String category;
21 
22     public String getCategory() {
23         return category;
24     }
25 
26     public void setCategory(String category) {
27         this.category = category;
28     }
29 
30     public int getCategoryId() {
31         return categoryId;
32     }
33 
34     public void setCategoryId(int categoryId) {
35         this.categoryId = categoryId;
36     }
37 
38     public String getContent() {
39         return content;
40     }
41 
42     public void setContent(String content) {
43         this.content = content;
44     }
45 
46     public Date getDate() {
47         return date;
48     }
49 
50     public void setDate(Date date) {
51         this.date = date;
52     }
53 
54     public int getId() {
55         return id;
56     }
57 
58     public void setId(int id) {
59         this.id = id;
60     }
61 
62     public String getTitle() {
63         return title;
64     }
65 
66     public void setTitle(String title) {
67         this.title = title;
68     }
69     
70 }
71 
Category.java
 1 /*
 2  * To change this template, choose Tools | Templates
 3  * and open the template in the editor.
 4  */
 5 
 6 package com.blog;
 7 
 8 /**
 9  * This is category class which records id and name
10  * @author Chucky
11  */
12 public class Category {
13     private int id;
14     private String name;
15 
16     public int getId() {
17         return id;
18     }
19 
20     public void setId(int id) {
21         this.id = id;
22     }
23 
24     public String getName() {
25         return name;
26     }
27 
28     public void setName(String name) {
29         this.name = name;
30     }
31     
32 }
33 
Comment.java
 1 /*
 2  * To change this template, choose Tools | Templates
 3  * and open the template in the editor.
 4  */
 5 
 6 package com.blog;
 7 
 8 import java.util.Date;
 9 
10 /**
11  * this is comment class which records id,name,content,date and blog_id
12  * @author Chucky
13  */
14 public class Comment {
15     private int id;
16     private String name;
17     private String content;
18     private Date date;
19     private int blog_id;
20 
21     public int getBlog_id() {
22         return blog_id;
23     }
24 
25     public void setBlog_id(int blog_id) {
26         this.blog_id = blog_id;
27     }
28 
29     public String getContent() {
30         return content;
31     }
32 
33     public void setContent(String content) {
34         this.content = content;
35     }
36 
37     public Date getDate() {
38         return date;
39     }
40 
41     public void setDate(Date date) {
42         this.date = date;
43     }
44 
45     public int getId() {
46         return id;
47     }
48 
49     public void setId(int id) {
50         this.id = id;
51     }
52 
53     public String getName() {
54         return name;
55     }
56 
57     public void setName(String name) {
58         this.name = name;
59     }
60     
61 }
62 
User.java
 1 /*
 2  * To change this template, choose Tools | Templates
 3  * and open the template in the editor.
 4  */
 5 
 6 package com.blog;
 7 
 8 /**
 9  *
10  * @author Chucky
11  */
12 public class User {
13     private int id;
14     private String userName;
15     private String password;
16 
17     public int getId() {
18         return id;
19     }
20 
21     public void setId(int id) {
22         this.id = id;
23     }
24 
25     public String getPassword() {
26         return password;
27     }
28 
29     public void setPassword(String password) {
30         this.password = password;
31     }
32 
33     public String getUserName() {
34         return userName;
35     }
36 
37     public void setUserName(String userName) {
38         this.userName = userName;
39     }
40 
41 }
42 
值得注意的是为了开发的方便,在Blog.java里与数据表不同,多了一个category属性。


2. Servlet
考虑到如果按照以后jsp的功能来写servlet的话,文件多了既混乱也不便于管理,所以按照数据类创建
BlogServlet(与blog相关的Servlet,如:添加,删除,修改,浏览,查询), CommentServlet, CategoryServlet和UserServlet,4个Servlet。


因为默认添加servlet信息到deployment文件,所以打开web.xml,相应的servlet信息已经被添加进去了。

posted @ 2009-09-28 15:41 Chucky 阅读(119) | 评论 (0)编辑 收藏

1.连接池
a.点击项目名称,右键选择New(新建)->other...


b.在categories选框里选择:Glassfish   右边File types(文件类型)选择:JDBC Connection Pool


c.JDBC Connection Pool Name(JDBC连接池名称):输入BlogPool;连接之前创建的blogs库。


d.全部默认选项,按finish(完成),连接池算是创建完成了。


2. 数据源
按步骤1-a,1-b选择JDBC Resource

c.Gerneral Attributes(一般属性)Connection Pool选择Use Existing JDBC Connetion Pool(使用已有的连接池)
下拉单里选择刚刚创建的BlogPool,JNDI Name里填写:jdbc/Blog

Finish以后,在项目的Server Resources的sun-resources.xml文件里可以查看到连接池和数据源的信息。
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE resources PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 Resource Definitions //EN" "http://www.sun.com/software/appserver/dtds/sun-resources_1_3.dtd">
 3 <resources>
 4   <jdbc-resource enabled="true" jndi-name="jdbc/Blog" object-type="user" pool-name="BlogPool">
 5     <description/>
 6   </jdbc-resource>
 7   <jdbc-connection-pool allow-non-component-callers="false" associate-with-thread="false" connection-creation-retry-attempts="0" connection-creation-retry-interval-in-seconds="10" connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0" connection-validation-method="auto-commit" datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" fail-all-connections="false" idle-timeout-in-seconds="300" is-connection-validation-required="false" is-isolation-level-guaranteed="true" lazy-connection-association="false" lazy-connection-enlistment="false" match-connections="false" max-connection-usage-count="0" max-pool-size="32" max-wait-time-in-millis="60000" name="BlogPool" non-transactional-connections="false" pool-resize-quantity="2" res-type="javax.sql.DataSource" statement-timeout-in-seconds="-1" steady-pool-size="8" validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false">
 8     <property name="URL" value="jdbc:mysql://localhost:3306/blogs"/>
 9     <property name="User" value="root"/>
10     <property name="Password" value="()"/>
11   </jdbc-connection-pool>
12 </resources>
13 

posted @ 2009-09-28 15:05 Chucky 阅读(263) | 评论 (0)编辑 收藏

建表等工作完成(关于MySql在Netbeans的配置可以参考一下之前的文章)。开工。

打开Netbeans,新建项目,分类(categories)里面选择Java web,右边项目(projects)选框里 web application。



在第一个项目里,不使用任何frameworks;所以直接选择finish。



posted @ 2009-09-28 14:46 Chucky 阅读(136) | 评论 (0)编辑 收藏

Blog-又称博客,现在基本所有大大小小门户网站都有自己的博客园;大凡网民十之五六有自己的博客。
项目基本用到的几个元素:
blog:  记录博文信息,包括:博文编号(id),标题(title),内容(content),发布时间(date),分类编号(category_id)
category: 记录分类信息,包括:分类编号(id),名称(name)
comment: 记录评论信息,包括:评论编号(id),评论人名(name),评论内容(content),发布时间(date),博客编号(blog_id)
users: 记录用户信息,包括:用户编号(id),用户名(username),密码(password)
 1 -- ----------------------------
 2 -- Table structure for blog
 3 -- ----------------------------
 4 DROP TABLE IF EXISTS `blog`;
 5 CREATE TABLE `blog` (
 6   `id` int(11NOT NULL auto_increment,
 7   `category_id` int(11default NULL,
 8   `title` varchar(400) collate utf8_unicode_ci default NULL,
 9   `content` varchar(4000) collate utf8_unicode_ci default NULL,
10   `date` datetime default NULL,
11   PRIMARY KEY  (`id`),
12   KEY `FK_Relationship_1` (`category_id`)
13 ) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
14 
15 -- ----------------------------
16 -- Table structure for category
17 -- ----------------------------
18 DROP TABLE IF EXISTS `category`;
19 CREATE TABLE `category` (
20   `id` int(11NOT NULL auto_increment,
21   `name` varchar(200) collate utf8_unicode_ci default NULL,
22   PRIMARY KEY  (`id`)
23 ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
24 
25 -- ----------------------------
26 -- Table structure for comment
27 -- ----------------------------
28 DROP TABLE IF EXISTS `comment`;
29 CREATE TABLE `comment` (
30   `id` int(11NOT NULL auto_increment,
31   `blog_id` int(11default NULL,
32   `name` varchar(200) collate utf8_unicode_ci default NULL,
33   `content` varchar(1000) collate utf8_unicode_ci default NULL,
34   `date` datetime NOT NULL,
35   PRIMARY KEY  (`id`),
36   KEY `FK_Relationship_2` (`blog_id`)
37 ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
38 
39 -- ----------------------------
40 -- Table structure for users
41 -- ----------------------------
42 DROP TABLE IF EXISTS `users`;
43 CREATE TABLE `users` (
44   `id` int(11NOT NULL auto_increment,
45   `username` varchar(200) collate utf8_unicode_ci default NULL,
46   `password` varchar(200) collate utf8_unicode_ci default NULL,
47   PRIMARY KEY  (`id`)
48 ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
49 
利用PowerDesigner可以很容易的设计并创建出相应的实体模型,并建立个各个实体之间的关系; 最后转换生成相应的sql的脚本。
考虑到中文乱码问题,在生成Sql脚本的时候记得选择utf-8编码。

posted @ 2009-09-28 14:29 Chucky 阅读(146) | 评论 (0)编辑 收藏

最近很闲,闲到无所事事。偶尔看到之前下载的《v512工作室_Java高端培训系列视频》中关于J2EE博客系统开发的讲座,一口气把37章看完,也算是恶补了一下J2EE的知识吧;
基本整理了一下从前的知识,计划利用netbeans重新写一下这个项目,说是盗版也好,抄袭也好,反正I dont care;
计划是分别写3个不同的版本(Servlet/Struts/Hibernate,Springs),算是拾回自己早已忘记的那点Java的东西。
基本的开发工具包括: Netbeans 6.7,MySql5.1以及GlassFish v2.x。

希望在接下来的10月能顺利完成以上3个项目,在过去简直是小菜一碟,现在么。。。。。。
posted @ 2009-09-28 13:39 Chucky 阅读(78) | 评论 (0)编辑 收藏