两亩三分地

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

2008年8月28日 #

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

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

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

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

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

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

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

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

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

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



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



posted @ 2009-09-28 14:46 Chucky 阅读(131) | 评论 (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 阅读(141) | 评论 (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 阅读(75) | 评论 (0)编辑 收藏

1.
从公司大门出来,长叹了口气,面试不过就这样而已。不过我是还没有清楚,我面试到底是面的什么职位。

昨天接到推荐朋友email说是和Oracle相关的初级职位,可是鬼子看了我的resume,一个劲地问点C和C++的东西。

浦西到浦东尽管有地铁,可是到张江还是很远的。家里过去足足1个半小时。

面试的是两个技术人员,一中国女人和一个印度小伙。读书时候印度鬼子见多了,所以到也不怕,中国人的话底细倒是不清楚了。
不过一上来人家就开英文,我只想说 那女的英文SUCKS 。最后她倒是先投降讲中文了。不过后面的面试题我可以撞墙去了。
一个打印倒3角, 一个是递归;最惨的是之前表现太差,最后让我写个HELLO WORLD 没写出来~
可以买豆腐撞死了。

2.

在回家的地铁上 所以有时间重新思考一下 刚才的题目。
倒3角
         1
       22
     333
   4444
 55555
2个循环 第一负责打空格 第2个打数字可以吗?

递归算法 5! = 5 * 4 * 3 * 2 * 1
算法本身应该有RETURN 和 一个判断

Hello World 不说了 回家自己翻入门书吧 一般总在前面几章

3.

到家,先跟家里人汇报一下面试情况,少不了被老头子批一顿。
打开Netbeans, 5分钟不到把几道问题都给解了~
我真是可以撞墙了~

a. 倒三角 Netbeans 新建project
for (int i = 0; i < 5; i++) {
            for (int j = 4; j >= 0; j--) {
                if (j > i) {
                    System.out.print(" ");
                } else {
                    System.out.print(i + 1);
                }
            }
            System.out.println();
        }

b. Recursion (印度鬼在纸上写了这个单词,我第一反应是类似循环,中国女的竟然说Loop -_-!)
出了门才想起来 这个中文叫递归~
当时在纸上胡乱写了2笔,没有写return也没加判断;
static private int recursion(int x) {
        
if (x>1){
            
return x*recursion(x-1);
        }
else{
            
return 1;
        }
    }

c. Hello World!
自己都想笑了,
当时我在whitebroad上鬼画是
static public void main(){
    println("Hello world!");
}
其实错的还不算离谱。
public static void main (String[] args){
  System.out.println(
"Hello World!");
}

习惯了用IDE 工具以后很多超级基本的东西反而不会写了;
coding的时候 用纸笔和电脑效果也果然是差别巨大;
当用电脑的时候思路如泉涌,打字基本不用经过大脑就直接出来了~
 
下次面试的时候给我台PC就好了~

posted @ 2008-12-04 20:39 Chucky 阅读(191) | 评论 (0)编辑 收藏

Finally I would get a job interview for junior Java developer position. So these days I try to prepare as much as possible for that interview.

Now the question is what a junior Java developer should know? There are some suggestions.

As a junior Java developer you’d be expected to know the basics of the language.

(Try practice tests for the Sun Certification exams although I’m not convinced you need to do the exam itself).

 Then you should also know:

     *Basic design patterns, why you need them and how to implement them in Java.

     * MVC framework – know how Struts works

     * XML basics (how to parse, manipulate and create – SAX/DOM/XSLT)

     * JDBC

     * Know how to use an IDE such as Eclipse or IntelliJ IDEA (Eclipse is most common)

     * Know what Inversion of Control is and what are its advantages

     * Know how to write unit tests using JUnit

       * Know what is Continuous integration testing

       * Know what mock testing

     * Familiarize yourself with different components of J2EE, what they are and what they’re useful for.

     * Know Ant

This is a basic list of what I think would get you through most Junior/entry level Java job interview.
If you have more time, start playing with Spring, Hibernate, JSF etc and spend some time learning to build/package a WebApp and deploy it to a container.



posted @ 2008-11-22 16:10 Chucky 阅读(115) | 评论 (0)编辑 收藏

昨晚中刀了,系统不得不重装,好在Netbeans啊,MySQL, Tomcat之类的东西装在其他盘符,所以损失不大。

一早重灌系统后,试试Netbeans。Tomcat启动正常,MySQL倒是有点问题。
Services - Databases - Register MySQL database
因为MySQL安装目录什么都没有改变,所以MySQL Server Properties 安照之前配置;
但是配置完毕后MySQL Server at localhost:3306 显示not connected。
想想大概是重装系统后,没有添加服务的关系,于是在系统里添加路径,
然后在Start- command -cmd Dos窗口里直接输入
mysqld-nt --install MySQL50 --defaults-file="I:\Program Files\MySQL\MySQL Server 5.0\my.ini" (MySQL安装在I:\Program Files\MySQL\MySQL Server 5.0\)
提示Service installed。但是运行service提示:
ERROR 2003: Can't connect to MySQL server on 'localhost' (10061)
开始考虑到是不是防火墙关系,关闭防火墙问题依旧,并发现同样使用localhost的Java DB运行ok,
想来不是localhost的问题,检查services 发现MySQL50的服务并没有运行,再看MySQL服务属性
Path to executable的设置上,mysqld-nt的位置被设置在C:\了,问题就在这里,原来服务装错了。

发现问题了,可是如何删除(修改)服务又成了新问题,在dos窗口想用mysql-nt -remove来删除服务,提示服务没有安装。
最后只能直接在注册表里修改的方法:
Start - command - regedit
\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services、MySQL50
ImagePath 将错误的路径改成 
"I:\Program Files\MySQL\MySQL Server 5.0\bin\mysqld-nt"--defaults-file="I:\Program Files\MySQL\MySQL Server 5.0\my.ini"
 MySQL50
完了,服务里启动MySQL50 服务,Netbeans里MySQL连接测试ok!

总结: 所谓的ERROR 2003: Can't connect to MySQL server on 'localhost' (10061) 估计应该是MySQL服务没有正常运行造成的,
所以只要重新正确启动MySQL服务,问题就迎刃而解了!
posted @ 2008-08-30 14:02 Chucky 阅读(11516) | 评论 (0)编辑 收藏

I have been using Netbeans to write code, draw UML for one and half years. During the period, I can see the functions it provides are getting more and more powerful and the servers and frameworks it supports also become more and more.Rightnow I started to learn framework, since there are much tutorials about using frameworks to develop Web & J2EE applications. I decided to use Netbeans as IDE to learn frameworks. So the first thing I should face to is to install database and server.

I don't need to spend time on introducing Netbeans. Of course, comparing to Eclipse, Netbeans still has lots spaces need to improve. But to me, Netbeans is no doubted a good and powerful tool for me. The latest version is 6.5 beta, but I think 6.1 Final is enough for studying purpose.


To MySQL, there is a MySQL GlassFish Bundle Netbeans  on the web. Certainly, we can manually install MySQL community edition.  There is a windows installation pack and zip pack, and we can google many articles about how to install MySQL, normally about how to add MySQL to windows Services.  MySQL GUI Tools is also necessary. About MySQL Java Connector, it is essential as well. But I think Netbeans provides MySQL JDBC Driver - mysql-connector-java-5.1.5-bin.jar already.

If choose to install MySQL GlassFish Bundle edition,, we don't need to configure any more but to setup MySQL GUI Tools, as following figure. If manually install MySQL, we need to setup the path of start command and stop command which also can reference to following figure.

mysql configuration

Comparing to install MySQL, I think Tomcat is much easier to install.  The  full pack or Web & Java EE Pack Netbeans 6.1 Final edition already had bundled Tomcat 6.0.16。Manual installation is not hard either, and the latest version is Tomcat 6.x . The thing we should notice is that we have better not to install windows installation pack, since the pack missed some batch files. During the configuring server in Netbeans, there would be some warning display. I suggest downloading the zip pack to install. 

Step by step for configuring server.

Select Services - Servers - Add Server..  In Add Server Instance window, choose Tomcat 6.0, and  give the name for server then press Next button


Installation and Login Details dialog window, in Catalina Home field, specify the path of Tomcat and setup user and password. After that, press Finish button to finish the configuration.


select Tomcat Server, right-click Start, the information displayed in output window shows the server start successfully.


Alright, everything is done! How easy it is! Then let's start coding!
posted @ 2008-08-28 21:40 Chucky 阅读(595) | 评论 (0)编辑 收藏

用Netbeans已经一年半了吧,反正一直没办法习惯用Eclipse。 这netbeans一直在不停的开发,功能也越来越强大;对不同server 和framework的支持也越来越好。 因为开始学习framework的关系,因为netbeans社区有不少相关的tutorials,所以还是决定用netbeans作为学习用的IDE,自然一上来就是安装数据库和Server。大概是Netbeans的普及程度远不及Eclipse,或者是Netbeans整合的太好了,相对配置实在太简单了,所以相对Eclipse,和Netbeans相关的配置文章实在太少了。

Netbeans目前最新版本是6.5beta,一般开发的话6.1 Final很好用了~

MySQL的话,Netbeans提供了MySQL GlassFish Bundle的版本,当然也可以自己安装,Windows安装版的话很好用,zip手动安装包的话,google上面相关的文章不少,无非就是将 MySQL添加到windows的服务中去。MySQL GUI Tools也是不可以少的。嗯MySQL Java Connector的话,也是需要的。Netbeans里好像已经有这个MySQL JDBC Driver - mysql-connector-java-5.1.5- bin.jar这个lib了。
如果安装,配置什么基本没有什么, 只是在最后要配置一下 MySQL GUI Tools,如图;手动安装MySQL的话,MySQL启动和停止的命令也可以是按照这个配置。
mysql configuration

相对MySQL,感觉Tomcat还是很好安装的,首先6.1 Final的完全包和Web &  Java EE Pack中已经直接绑定了 Tomcat 6.0.16了。当然手动安装也是可以的,最新版本Tomcat 6.x 。值得注意的是,在下载的时候建议不要选择windows安装版本。因为windows安装版本缺少几个batch file,在配置 netbeans的时候会被warning的,本着尽量省心省力的原则,多一事不如少一事。

选中Services - Servers - Add Server..  在Add Server Instance 对话框中 选择Tomcat 6.0后,填写Server的名字,按 Next


Installation and Login Details 对话框, Catalina Home 指定Tomcat的安装目录,Login Details设置用户及密码。按Finish完成配置。

选中Tomcat Server,右键start; Output windows 显示Server Start 正常!

好了,Server和MySQL已经搞定了,后面就是framework的学习了~
posted @ 2008-08-28 16:09 Chucky 阅读(416) | 评论 (0)编辑 收藏