小項目(留言板)

項目經驗: 程序框架、代碼書寫、bug調試

程序框架:

       程序模型:MVC模型

       M(model)-Dao->extends BaseDao(數據庫操作

                     CRUD代碼

       C(controller)-Servlet->url-class WebServlet(“/***”)(前端頁面與數據庫操作

  1. 獲得請求的數據
  2. 調用Dao層方法實現業務
  3. 輸出返回數據(DML 0 -1 1/DQL Obj  List<obj>)

V(view)-html

  1. ajax提交數據到web服務器
  2. 使用jquery實現頁面的動態佈局
  3. 表單驗證操作

代碼書寫:業務流、數據流(前端)

  1. 添加功能

填寫數據->單擊提交按鈕(click)->ajax

(url=”addMsg”\data{name:.val(),msg:.val()}\success{result==”1” layer 提示})

InsertMsgServlet->request.get…(“name”)(“msg”) 

New Message msg(name,msg) ->MsgDao.insert(msg) ->out.print(ret)

Int MsgDao.insert(msg) insert(){excuteUpdate(“insert..”,[msg])}

Msg entity

*****開發的順序是數據流逆序。

 

  1. 查看功能

$(ajax(url=”/showMsg”\success {result=List<Msg> for}))

ShowMsgServlet->List<Msg>MsgDao.showUser()->JSONArray(list) ->out()

MsgDao.ShowMsg()->{excuteQuery(“select ”)}

準備工作:導入jar包

導入靜態原型

只要有表單就一定要在瀏覽器中校驗

難點:1、前後端開發方式

自從參加了藍橋培訓以來,我做的第一個小項目留言板,使用的製作工具是idea,數據庫是mysql

  • 首先安裝mysql數據庫

安裝直接按下一步就行,但是一定要記住自己設置的密碼

  • 建message表

如下圖:

id不但要設置爲主鍵,還要設置它自動遞增。

username和msg要設置它們的字符集爲utf8

createtime要設置其默認CURRENT_TIMESTAMP

就這樣,一個數據庫的表就建好了。

  • 再所有的操作之前需要在pom.xml中導入之後所需要的包,必須在有網的情況下,纔可以完成。
<?xml version="1.0" encoding="UTF-8"?>



<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>



  <groupId>org.lanqiao</groupId>

  <artifactId>message</artifactId>

  <version>1.0-SNAPSHOT</version>

  <packaging>war</packaging>



  <name>message Maven Webapp</name>

  <!-- FIXME change it to the project's website -->

  <url>http://www.example.com</url>



  <properties>

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    <maven.compiler.source>1.7</maven.compiler.source>

    <maven.compiler.target>1.7</maven.compiler.target>

  </properties>



  <dependencies>

    <dependency>

      <groupId>junit</groupId>

      <artifactId>junit</artifactId>

      <version>4.11</version>

      <scope>test</scope>

    </dependency>

    <dependency>

    <groupId>javax.servlet</groupId>

    <artifactId>javax.servlet-api</artifactId>

    <version>3.1.0</version>

    <scope>provided</scope>

  </dependency>

     <dependency>

    <groupId>net.sf.json-lib</groupId>

    <artifactId>json-lib</artifactId>

    <version>2.3</version>

    <classifier>jdk15</classifier>

  </dependency>

    <dependency>

      <groupId>c3p0</groupId>

      <artifactId>c3p0</artifactId>

      <version>0.9.1.2</version>

    </dependency>

    <dependency>

    <groupId>mysql</groupId>

    <artifactId>mysql-connector-java</artifactId>

    <version>5.1.6</version>

  </dependency>

  </dependencies>



  <build>

    <finalName>message</finalName>

    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->

      <plugins>

        <plugin>

          <artifactId>maven-clean-plugin</artifactId>

          <version>3.0.0</version>

        </plugin>

        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->

        <plugin>

          <artifactId>maven-resources-plugin</artifactId>

          <version>3.0.2</version>

        </plugin>

        <plugin>

          <artifactId>maven-compiler-plugin</artifactId>

          <version>3.7.0</version>

        </plugin>

        <plugin>

          <artifactId>maven-surefire-plugin</artifactId>

          <version>2.20.1</version>

        </plugin>

        <plugin>

          <artifactId>maven-war-plugin</artifactId>

          <version>3.2.0</version>

        </plugin>

        <plugin>

          <artifactId>maven-install-plugin</artifactId>

          <version>2.5.2</version>

        </plugin>

        <plugin>

          <artifactId>maven-deploy-plugin</artifactId>

          <version>2.8.2</version>

        </plugin>

      </plugins>

    </pluginManagement>

  </build>

</project>
  • 首先要在maven中建好目錄

然後在entity下建一個message.java

package entity;



import java.util.Date;



public class message {

    private int id;

    private String username;

    private String msg;

    private Date createtime;

    public message(){}

    public message(String username, String msg) {

        this.username=username;

        this.msg=msg;

    }

    public int getId(){

        return id;

    }

    public void setId(int id){

        this.id=id;

    }

    public String getUsername(){

        return username;

    }

    public void setUsername(String username){

        this.username=username;

    }

    public String getMsg(){

        return msg;

    }

    public void setMsg(String msg){

        this.msg=msg;

    }

    public Date getCreatetime(){

        return createtime;

    }

    public void setCreatetime(Date createtime){

        this.createtime=createtime;

    }



}

五、Dao層,有BaseDao(這是老師寫的),messageDao(我寫的)

BaseDao中需要修改其數據庫名稱和之前設置的密碼

老師寫的BaseDao

package dao;



import com.mchange.v2.c3p0.ComboPooledDataSource;



import java.lang.reflect.Field;

import java.lang.reflect.ParameterizedType;



import java.sql.*;

import java.util.ArrayList;

import java.util.List;



public abstract class BaseDao<T> {

    private static ComboPooledDataSource dataSource;//連接池

    private Class<T> clazz;

    static {

        try {

            //加載配置文件,導入一個核心類。

            dataSource = new ComboPooledDataSource();

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

    //反射獲得clazz

    public BaseDao() {

        clazz = (Class<T>) ((ParameterizedType) this.getClass()

                .getGenericSuperclass()).getActualTypeArguments()[0];

    }



    //提供獲得數據源

    public static ComboPooledDataSource getDataSource() {

        return dataSource;

    }



    //提供獲得連接

    public static Connection getConnection() throws SQLException {

        return dataSource.getConnection();

    }



    //關閉資源

    public void closeAll(Connection conn, Statement stmt, ResultSet rs) {

        try {

            if (rs != null)

                rs.close();

            if (stmt != null)

                stmt.close();

            if (conn != null)

                conn.close();

        } catch (SQLException e) {

            e.printStackTrace();

        }

    }



    public void closeAll(Connection conn, Statement stmt) {

        try {

            if (stmt != null)

                stmt.close();

            if (conn != null)

                conn.close();

        } catch (SQLException e) {

            e.printStackTrace();

        }

    }



    // DML

    public int executeUpdate(String sql, Object[] obj) {

        Connection conn = null;

        PreparedStatement stat = null;

        int ret = 0;

        try {

            conn = getConnection();

            // 3、創建傳輸對象statmemnt

            stat = conn.prepareStatement(sql);// ?不確定:類型、數量

            // 3+、綁定替換數據

            for (int i = 0; i < obj.length; i++) {

                stat.setObject(i + 1, obj[i]);

            }

            // 4、發送sql語句,並且接收返回結果 : DML -> executeUpdate ; DQL -> executeQuery

            ret = stat.executeUpdate();

            //打印sql語句

            printSql(sql,obj);

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            closeAll(conn, stat);

        }

        return ret;

    }



    // DQL

    public List<T> executeQuery(String sql, Object[] obj) {

        Connection conn = null;

        PreparedStatement stat = null;

        ResultSet rs = null;

        List<T> list = new ArrayList<T>();

        try {

            conn = getConnection();

            // 3、創建傳輸對象statmemnt

            stat = conn.prepareStatement(sql);// ?不確定:類型、數量

            // 3+、綁定替換數據

            for (int i = 0; i < obj.length; i++) {

                stat.setObject(i + 1, obj[i]);

            }

            // 4、發送sql語句,並且接收返回結果 : DML -> executeUpdate ; DQL -> executeQuery

            rs = stat.executeQuery();

            // 5、如果返回rs類型的數據,需要將數據轉換成list

            ResultSetMetaData rsmd = rs.getMetaData();//列名信息

            int columuCount = rsmd.getColumnCount();//列的數量

            while (rs.next()) {

                T t = (T) clazz.newInstance();//創建對象

                for (int i = 0; i < columuCount; i++) {//封裝數據

                    Field f = clazz.getDeclaredField(rsmd.getColumnName(i + 1));//列名->屬性名->屬性對象

                    f.setAccessible(true);

                    //對日期類型進行處理

                    String typeName = f.getType().getName();

                    if (typeName.equals("java.sql.Timestamp") || typeName.equals("java.util.Date") || typeName.equals("java.sql.Date")) {

                        f.set(t, rs.getDate(i + 1));

                    } else {

                        f.set(t, rs.getObject(i + 1));//將rs列中的值賦給屬性

                    }

                }

                list.add(t);

            }

            //打印sql語句

            printSql(sql,obj);

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            closeAll(conn, stat, rs);

        }

        return list;

    }



    // DQL

    public List<T> executeQuery(String sql) {

        Connection conn = null;

        PreparedStatement stat = null;

        ResultSet rs = null;

        List<T> list = new ArrayList<T>();

        try {

            conn = getConnection();

            // 3、創建傳輸對象statmemnt

            stat = conn.prepareStatement(sql);// ?不確定:類型、數量

            // 3+、綁定替換數據

            // 4、發送sql語句,並且接收返回結果 : DML -> executeUpdate ; DQL -> executeQuery

            rs = stat.executeQuery();

            // 5、如果返回rs類型的數據,需要將數據轉換成list

            ResultSetMetaData rsmd = rs.getMetaData();//列名信息

            int columuCount = rsmd.getColumnCount();//列的數量

            while (rs.next()) {

                T t = (T) clazz.newInstance();//創建對象

                for (int i = 0; i < columuCount; i++) {//封裝數據

                    Field f = clazz.getDeclaredField(rsmd.getColumnName(i + 1));//列名->屬性名->屬性對象

                    f.setAccessible(true);

                    f.set(t, rs.getObject(i + 1));//將rs列中的值賦給屬性



                }

                list.add(t);

            }

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            closeAll(conn, stat, rs);

        }

        return list;

    }

    // DQL

    public int getRecordCount(String sql) {//select count(*) from msg;

        Connection conn = null;

        PreparedStatement stat = null;

        ResultSet rs = null;

        int count = 0;

        try {

            conn = getConnection();

            // 3、創建傳輸對象statmemnt

            stat = conn.prepareStatement(sql);// ?不確定:類型、數量

            // 3+、綁定替換數據

            // 4、發送sql語句,並且接收返回結果 : DML -> executeUpdate ; DQL -> executeQuery

            rs = stat.executeQuery();

            // 5、如果返回rs類型的數據,需要將數據轉換成list

            if (rs.next()) {

                count = rs.getInt(1);

            }

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            closeAll(conn, stat, rs);

        }

        return count;

    }



    // 輸出預編譯的sql語句的具體內容(便於調試)

    private void printSql(String sql, Object[] params) {

        StringBuffer sb = new StringBuffer(sql);

        int fromIndex = 0;

        if (params != null) {

            for (int i = 0; i < params.length; i++) {

                int index = sb.indexOf("?", fromIndex);

                if (index == -1) {

                    sb.append(" ---> error: value too many   ");

                    break;

                }

                if (params[i] instanceof String) {

                    sb.replace(index, index + 1, "'" + this.valueOf(params[i]) + "'");

                } else if (params[i] instanceof Number) {

                    sb.replace(index, index + 1, this.valueOf(params[i]));

                } else if (params[i] instanceof Character) {

                    sb.replace(index, index + 1, "'" + this.valueOf(params[i]) + "'");

                } else if (params[i] instanceof Boolean) {

                    sb.replace(index, index + 1, "'" + this.valueOf(params[i]) + "'");

                } else if (params[i] instanceof Object[]) {

                    sb.replace(index, index + 1, "'" + this.valueOf(params[i]) + "'");

                } else if (params[i] instanceof Date) {

                    sb.replace(index, index + 1, " date '" + this.valueOf(params[i]) + "'");

                } else if (params[i] instanceof java.util.Date) {

                    sb.replace(index, index + 1, "'java.util.Date'");

                }

                fromIndex = index + 1;

            }

        }

        System.out.println(sb.toString());

    }



    public String valueOf(Object obj) {

        return (obj == null) ? "" : obj.toString();

    }

}

 

然後我把它改成了c3p0-config.xml,同樣也是需要修改數據庫名稱和之前設置的密碼

<?xml version="1.0" encoding="UTF-8"?>

<c3p0-config>

    <!--默認配置-->

    <default-config>

        <!--mysql數據庫連接的各項參數-->

        <property name="driverClass">com.mysql.jdbc.Driver</property>

        <property name="jdbcUrl">jdbc:mysql://localhost:3306/mysql?characterEncoding=utf8</property>

        <property name="user">root</property>

        <property name="password">123</property>

        <!--配置數據庫連接池的最小連接數,最大連接數,初始連接數-->

        <property name="initialPoolSize">5</property>

        <property name="maxPoolSize">15</property>

        <property name="minPoolSize">5</property>

        <property name="maxIdleTime">10</property>

    </default-config>

</c3p0-config>

 

然後在messegeDao中,必須繼承BaseDao

package dao;

import
entity.message;

import
java.util.List;

public class
messageDao extends BaseDao<message> {

   
//留言插入數據庫
   
public int insert(message u) {
       
return executeUpdate("insert into message(username,msg) values(?,?)", new Object[]{u.getUsername(), u.getMsg()});
   
}

   
//展示留言並分頁
   
public  List<message> showMsg(int pageNum,int pageSize){
       
return executeQuery("select * from message limit ?,?",new Object[]{(pageNum-1)*pageSize,pageSize});
   
}
   
//分頁
   
public int getMsgCount(){
       
return getRecordCount("select count(*) from message");
   
}
}

六、老師上課時收了,要對界面進行什麼樣的操作,就要建幾個servlet。所以我需要對界面進行查詢和刪除的操作,所以我建了InsertServlet和ShowServlet

InsertMsgServlet的代碼如下:

package servlet;



import dao.messageDao;

import entity.message;



import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import java.io.PrintWriter;



@WebServlet("/InsertMsgServlet")

public class InsertMsgServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //1、獲得表單(頁面)數據

        String username=request.getParameter("username");

        String msg=request.getParameter("msg");

        System.out.println(username);

        //2、封裝對象

        message msgBean=new message(username,msg);

        //3、dao操作

        int ret=new messageDao().insert(msgBean);

        //4、輸出結果

        PrintWriter out=response.getWriter();

        out.print(ret);

        out.flush();

        out.close();

    }



    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        doPost(request,response);

    }

}

ShowMsgServlet的代碼如下:

package servlet;



import dao.messageDao;

import entity.message;

import net.sf.json.JSONArray;

import PeiZhi.JsonDateValueProcessor;

import net.sf.json.JsonConfig;





import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.Date;

import java.util.List;



@WebServlet("/ShowMsgServlet")

public class ShowMsgServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //1、頁數和每頁記錄

        int pageNum=1;

        String num=request.getParameter("num");

        if(num!=null&&!num.equals("")){

            pageNum=Integer.parseInt(num);//字符串轉換爲整數

        }

        //轉換格式

        response.setCharacterEncoding("utf-8");

        //3.dao操作

        messageDao msgDao=new messageDao();

        List<message> list=msgDao.showMsg(pageNum,3);

//        System.out.println(list.size());

        //日期

        JsonConfig jsonConfig = new JsonConfig();

        jsonConfig.registerJsonValueProcessor(Date.class , new JsonDateValueProcessor());

        //4、輸出結果

        JSONArray jsonArray=JSONArray.fromObject(list,jsonConfig);

        jsonArray.add(msgDao.getMsgCount());

        PrintWriter out=response.getWriter();

        out.print(jsonArray);

        out.flush();

        out.close();

    }



    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        doPost(request,response);

    }

} 

 

在顯示日期的時間時,需要自己寫一個JsonDateValueProcessor.java其中代碼如下(下面的代碼只能顯示出年月日,如果要顯示時間需要在後加上HH-mm-ss,HH代表的是24小時,hh代表的是12小時)

package PeiZhi;



import net.sf.json.JsonConfig;

import net.sf.json.processors.JsonValueProcessor;



import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Locale;



public class JsonDateValueProcessor implements JsonValueProcessor {

//    private String format ="%Y-%M-%D %h:%i:%s";

    private String format ="yyyy-MM-dd";



    public Object processArrayValue(Object value, JsonConfig config) {

        return process(value);

    }



    public Object processObjectValue(String key, Object value, JsonConfig config) {

        return process(value);

    }



    private Object process(Object value){



        if(value instanceof Date){

            SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.UK);

            return sdf.format(value);

        }

        return value == null ? "" : value.toString();

    }



}

七、接下來是最重要的地方了就是集齊html+ajax+jquery+layer(彈出框)

<!DOCTYPE html>

<html lang="en">

<head>

    <title>留言板</title>

    <meta charset="UTF-8">

    <style>

        div {

            margin: 0;

            padding: 0;

            font-size: 12px;

            margin: 0 auto;

        }



        h3 {

            text-align: center

        }



        #container {

            width: 500px;

        }



        .article {

            border: 1px solid #a6cbe7;

            margin-top: 5px;

        }



        .author {

            background-color: #0099FF;

            width: 100%;

            height: 24px;

            line-height: 24px;

        }



        .content {

            height: 40px;

            padding: 10px;

        }



        .author span {

            float: right;

            padding-right: 10px;

        }



        .time {

            border-top: solid 1px #a6cbe7;

        }



        .page {

            text-align: right;

            height: 30px;

            line-height: 30px;

            padding-right: 10px;

        }

    </style>

    <script src="js/jquery-3.3.1.js" type="application/javascript"></script>

    <script src="js/layer.js" type="text/javascript" rel="stylesheet"></script>

    <link href="css/layer.css" type="text/css" rel="stylesheet">

    <script src="js/jquery.validate.js"></script>

    <script>

        var num=1;

        var rsCount=0;

        var preList;

        var pageSize=3;

        var maxPage=0;

        function load() {

            $.ajax({

                url:"/ShowMsgServlet",

                type:"post",

                data:{"num": num},

                dataType:"json",

                success:function (list) {

                    //若當前顯示不出來,則說明當前是最後一頁,使用前一頁的信息顯示

                    if(list.length==0){

                        list=preList;

                        num--;

                    }else{

                        preList=list;

                    }

                    for(var i=0;i<list.length-1;i++){

                        var $node=$('<div class="article"><div class="author">用戶:'+list[i].username+'<span>#'+list[i].id+'</span></div><div class="content">'+list[i].msg+'</div><div class="time page">發表於:'+list[i].createtime+'</div></div>');

                        $("#show").append($node);

                    }

                    // alert(list[list.length-1]);

                    rsCount=list[list.length-1]

                }

            });

        }

        $(function () {

            load();

            $(".btn1:eq(0)").click(function () {

                num =num>1 ? --num:num;

                $("#show").children().remove();

                load();

            });

            $(".btn1:eq(1)").click(function () {

                // //計算最大頁數

                var  maxPage=Math.ceil(rsCount/pageSize);

                // alert(maxPage);

                // num++;

                num=num<maxPage?++num:maxPage;

                $("#show").children().remove();

                load();

            });

            $("#cForm").validate({

                onsubmit:true,// 是否在提交是驗證

                onfocusout:false,// 是否在獲取焦點時驗證

                onkeyup :false,// 是否在敲擊鍵盤時驗證



                rules: {    //規則

                    author: {  //要對應相對應的input中的name屬性

                        required: true

                    },

                    message: {

                        required: true

                    }

                },

                messages:{    //驗證錯誤信息

                    author: {

                        required: "請輸入用戶名"

                    },

                    message: {

                        required: "請輸入留言"

                    }

                },

                submitHandler: function(form) { //通過之後回調

                //進行ajax傳值

                    $.ajax({

                        url : "/ShowMsgServlet",

                        type : "post",

                        dataType : "json",

                        data: {

                            author: $("#user").val(),

                            password: $("#password").val()

                        },

                        success : function(msg) {

                            //要執行的代碼

                            //插入數據並彈出框

                            $("input[type='submit']").click(function (e) {

                                e.preventDefault();

                                $.ajax({

                                    url:"/InsertMsgServlet",

                                    type:"post",

                                    data:{"username":$("input[name='author']").val(),"msg":$("textarea[name='message']").val()},

                                    dataType:"text",

                                    success:function (ret) {

                                        if(ret=="1"){

                                            layer.msg('留言成功',{time:1000},function () {

                                                location.reload();

                                            });

                                        }else{

                                            layer.msg('留言失敗',{time:1000},function () {

                                                location.reload();

                                            });

                                        }

                                    }

                                });

                            });

                        }

                    });

                },

                invalidHandler: function(form, validator) {return false;}

            });

        })

    </script>

</head>



<body>

<div id="container">

    <div><h3>留言板</h3></div>

    <div id="show">





    </div>



    <div class="page">

        <input class="btn1" type="button" value="上一頁" onClick="">

        <input class="btn1" type="button" value="下一頁" onClick="">

    </div><br>

    <div>

        <form id="cForm">

            <div>

                用戶: <input type="text" name="author" value=""/>

            </div><br>

            <div>

                留言: <textarea name="message" rows="5" cols="72"></textarea>

            </div>

            <div align="center"><input type="reset" value="清除"/> <input type="submit" value="發表"/></div>

        </form>

    </div>

</div>

</body>

</html>
  1. 彈出框,需要導入layer.css和layer.js的包,但是在導入之前必須先導入jquery.js包,必須是1.8以上的纔可以。於是彈出框就做好了。
  2. 表單驗證,可以參考網址https://www.cnblogs.com/jingmin/p/6294982.html,其中的元素必須是頁面元素。

留言板截圖:

表單驗證:

留言成功,layer彈出框顯示,過一秒後頁面刷新

上一頁和下一頁截圖:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章