【手把手】JavaWeb 入門級項目實戰(zhàn) -- 文章發(fā)布系統(tǒng) (第四節(jié))

首先房匆,更正一下上一章中的一個小錯誤圾亏,就是在index.jsp中,banner部分沒有添加結(jié)束的標簽,加上去就OK了瓮床,我也是完善頁面的時候發(fā)現(xiàn)的芜茵。

另外叙量,index.jsp中引入的jQuery也需要換成本地的。

<script src="${basePath}/static/js/jQuery.js"></script>

今天我把頁面重構(gòu)了一下九串,添加了內(nèi)容區(qū)和底欄(footer)绞佩,我會把目前的代碼上傳的,有需要的自己去看就行了蒸辆,我們就不在前臺頁面花費太多的時間了征炼。div + css,布局等等躬贡,這些東西以后有時間的話谆奥,我單獨開貼分享吧。

都已經(jīng)寫了三篇文章了拂玻,還沒有寫Java代碼酸些,實在有些說不過去宰译。

1. 登陸頁面

登陸頁我已經(jīng)寫好了,現(xiàn)在看看效果魄懂,簡單說明一下沿侈。

點擊登陸按鈕,可以跳轉(zhuǎn)到登陸頁面市栗。

登陸按鈕就是一個超鏈接缀拭。

JSP頁面就是一個servlet,但是省去了很多寫Servlet的麻煩填帽,login.jsp已經(jīng)寫好了蛛淋,就放在WebContent目錄下。

昨天憋了一上午篡腌,總算寫好了登陸頁面褐荷。我不是專業(yè)做前端的,所以只做了一個大概樣子嘹悼。用了很多css3的屬性叛甫,所以IE678上瀏覽的效果是不好的。

關于這個頁面杨伙,今天我調(diào)整了一下其监,不想搞得那么復雜了,我去掉了所有的圖標和飄動白云限匣,關于css特效棠赛,h5的話呢,以后單獨拿出來說明吧膛腐,畢竟好多人都反應說太花哨了,因為是入門級的小項目鼎俘,我也不想弄得那么復雜了哲身。

雖然頁面單調(diào)了些,不過對于初學者來說贸伐,相對來說比較好理解勘天。之前的頁面的確有點太花哨了,還弄了幾朵云飄來飄去的捉邢,說不定還影響性能脯丝,所以我把這些都去掉了。

Paste_Image.png

2. 新的目錄結(jié)構(gòu)

之前的代碼有很多冗余的地方伏伐,比如標題欄宠进,每個頁面都需要寫一遍。而且js和css都是寫在本頁面的藐翎。實際開發(fā)一般都不會這么做材蹬。所以实幕,我把這些東西都分離出來了,放在各自的目錄里堤器。

以下是新的目錄結(jié)構(gòu):

header.jsp


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<div class="header">
    <div class='logo'>原創(chuàng)文字</div>
    <ul>
        <li class='first'><a href="index.jsp">首頁</a></li>
        <li class='item'><a href="javascript:void(0)">原創(chuàng)故事</a></li>
        <li  class='item'><a href="javascript:void(0)">熱門專題</li>
        <li  class='item'><a href="javascript:void(0)">欣賞美文</li>
        <li  class='item'><a href="javascript:void(0)">贊助</a></li>
    </ul>
    
    <div class='login'>
        <span><a href="login.jsp">登陸</a></span>  
        <span>|</span> 
        <span><a href="javascript:void(0)">注冊</a></span>
    </div>
</div>

這就是標題欄昆庇,以后新增的jsp頁面,只需要把這個header.jsp引入就可以了闸溃。注意整吆,這種引入就相當于把里面的代碼原封不動地拷貝進去,所以如果用相對路徑引用資源文件辉川,就還是以原本的頁面為準表蝙。

引入方式:

<!-- 頭部頁面 -->
<%@include file="common/header.jsp" %>

footer.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<div class='footer'>
    免責聲明:本站所有素材均來自網(wǎng)絡,僅供學習交流员串。如果侵犯了您的權(quán)益勇哗,請聯(lián)系我,我會第一時間刪除侵權(quán)內(nèi)容寸齐。
</div>

taglib.jsp (一些公共的配置等)


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
    String path = request.getContextPath();
    int port = request.getServerPort();
    String basePath  = null;
    if(port==80){
        basePath = request.getScheme()+"://"+request.getServerName()+path;
    }else{
        basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path;
    }
    request.setAttribute("basePath", basePath);
%>

basePath 就是項目的根路徑欲诺。這樣做的好處就是,使得JSP看起來很干凈渺鹦,沒有那么多冗余的代碼了扰法。

大概就是這個樣子,接下來毅厚,我們開始寫業(yè)務塞颁。

3. 登陸功能的MVC流程

登陸框中,目前只有用戶名和密碼這兩個選項吸耿。

我們首先要做的就是將這兩個值傳遞到后臺祠锣。所謂的后臺,其實就是Java代碼咽安。為了看起來比較清晰伴网,我們在WebContent目錄下新建一個controller包。

這是一個MVC分層的示意圖


意思就是說妆棒,用戶登錄之后澡腾,我們需要驗證它的用戶名和密碼是否正確,那么就需要將數(shù)據(jù)拿到數(shù)據(jù)庫里面去匹配糕珊《郑總體的流程大概是這樣:我先在前臺獲取用戶名和密碼,然后到controller層(控制層)红选,這一層需要接受你傳過來的用戶名和密碼澜公,進行一些基本的控制。

然后繼續(xù)將數(shù)據(jù)傳遞到service層纠脾,也就是業(yè)務層玛瘸,這一層會根據(jù)具體的業(yè)務對你的數(shù)據(jù)進行判斷和分析蜕青,最后,才傳遞到dao層糊渊,這一層原則上就是和數(shù)據(jù)庫進行交互的右核。多半是寫sql語句然后操作數(shù)據(jù)庫。

就比如說用戶登錄這個功能渺绒,我需要判斷的就是

  1. 你這個用戶是否存在贺喝?
  2. 用戶名和密碼是否正確?

最終宗兼,還需要將登錄的標志返回給前臺躏鱼。

dao -> servide -> controller -> JSP

這樣就是一個完整的流程。

4. 從JSP到controller層

讓我們打開login.jsp頁面殷绍,引入jQuery

<script src="${basePath}/static/js/jQuery.js"></script>

登錄框的HTML代碼:


<!-- 登陸框 -->
<div class='content'>
    <div class='logo'><i style='font-size:90px;' class="iconfont icon-denglu"></i></div>
    <div class='inputBox mt50 ml32'>
        <input type="text" id="username" autofocus="autofocus" autocomplete="off" maxlength="60" placeholder="請輸入賬號/郵箱/手機號">
        <i style='font-size:20px;margin-left:-32px;opacity:0.8;' class='iconfont icon-yonghuming'></i>
    </div>
    <div class='inputBox mt50 ml32'>
        <input type="password" id="password" autofocus="autofocus" autocomplete="off" maxlength="60" placeholder="請輸入密碼">
        <i style='font-size:20px;margin-left:-32px;opacity:0.8;' class='iconfont icon-mima'></i>
    </div>
    
    <div class='mt50 ml32'>
        <button class="login_btn" onclick="#">登陸</button>
    </div>
</div>

我們在下面寫一個script塊染苛,js代碼就全部寫在這里。

給登陸按鈕綁定一個點擊事件:

<div class='mt50 ml32'>
        <button class="login_btn" onclick="login()">登陸</button>
</div>

登陸方法

function login(){
    var username = $('#username').val();
    var password = $('#password').val();
    alert(username + "," + password);
}

當成功alert出來數(shù)據(jù)后主到,說明到此為止的代碼是正確的茶行。

接下來,利用jQuery的ajax方法登钥,將數(shù)據(jù)提交到controller層畔师。


function login(){
    var username = $('#username').val();
    var password = $('#password').val();
    $.ajax({
        type:"post",//請求方式
        url:"${basePath}/controller/loginController.jsp",//請求地址
        data:{"username":username,"password":password},//傳遞給controller的json數(shù)據(jù)
        error:function(){
            alert("登陸出錯!");
        },
        success:function(data){ //返回成功執(zhí)行回調(diào)函數(shù)牧牢。
            
        }
    });
    
}

我已經(jīng)都寫好注釋了看锉,ajax方法在web開發(fā)過程中,是被普遍使用的塔鳍。

新建一個loginController.jsp 伯铣,這就是所謂的服務器端。


<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%

    //設置請求的編碼
    //request.setCharacterEncoding("UTF-8");
    //獲取客戶端傳遞過來參數(shù)
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    System.out.println(username);
    System.out.println(password);
    //如果用戶名和密碼不為空
    
%>

從JSP頁面到controller轮纫,用戶名和密碼是被裝在一個叫做request的變量中懂傀,它其實也就相當于一個json,一個map蜡感,都是差不多的東西,這里就不詳細說明了恃泪。當然了郑兴,他也是JSP九大隱式對象中的一員。

Paste_Image.png

我們來測試一下贝乎,點擊登陸按鈕情连。

成功了!可以看到數(shù)據(jù)已經(jīng)成功傳遞到controller層了览效。

因為我們還沒有數(shù)據(jù)表和JavaBean却舀,所以我們先不急著寫service層虫几,先開始編寫JavaBean吧。

5. 從JavaBean到數(shù)據(jù)庫表挽拔。

我們在src目錄下新建一個存放JavaBean的包

關于JavaBean辆脸,如果不是很了解的話,可以看看這篇文章:

http://www.cnblogs.com/skyblue-li/p/5900216.html

一個記錄用戶信息的JavaBean螃诅,我想了以下這些屬性:

private String id;    //主鍵啡氢,采用UUID
private String username;  //用戶名
private String password;  //密碼
private String headerPic; //頭像
private String email;     //電子郵箱
private Integer male;     //性別 0男 1女 3保密
private String createTime;//創(chuàng)建時間
private String updateTime;//最后更新時間
private Integer isDelete; // 刪除狀態(tài)0未刪除1刪除
private String address;   //地址
private String telephone; //電話

當你的JavaBean設計好了,差不多對應的數(shù)據(jù)庫表也就出來了术裸。

之前寫過一篇關于注解的文章:

http://www.cnblogs.com/skyblue-li/p/5900228.html

現(xiàn)在可以用這個知識點做點有趣的事情了倘是,比如將一個JavaBean轉(zhuǎn)換成建表語句。

新建一個注解包袭艺,里面添加兩個注解

column.java

package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)      //注解的目標
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    
    public String field() ; //字段名稱
    public boolean primaryKey() default false;//是否為主鍵
    public String type() default "VARCHAR(80)";//字段類型
    public boolean defaultNull() default true; //是否允許為空
    
}

Table.java

package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)       //注解的目標是類
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {

    public String tableName();
}

我們創(chuàng)建了兩個注解搀崭。

接下來,在util包(也就是工具包)中新建兩個工具類

StringUtils 字符串工具類

package util;


public class StringUtils {
    
    public static boolean isEmpty(String str) {
        return null == str  || str.equals("")
                || str.matches("\\s*");
    }

    public static String defaultValue(String content,String defaultValue){
        if(isEmpty(content)){
            return defaultValue;
        }
        return content;
    }
}

isEmpty的作用是判斷字符串是否為空猾编。
defaultValue表示給字符串設置默認值瘤睹,有點類似于oracle數(shù)據(jù)庫中的nvl語法。

TableUtils 數(shù)據(jù)表工具類

package util;

import java.lang.reflect.Field;

import annotation.Column;
import annotation.Table;

public class TableUtils {
    
    
    public static String getCreateTableSQl(Class<?> clazz){
        StringBuilder sb = new StringBuilder();
        sb.append("create table ");
        //獲取表名
        Table table = (Table) clazz.getAnnotation(Table.class);
        String tableName = table.tableName();
        sb.append(tableName).append("(\n");
        
        Field[] fields = clazz.getDeclaredFields();
        String primaryKey = "";
        //遍歷所有字段
        for (int i = 0; i < fields.length; i++) {
            Column column = (Column) fields[i].getAnnotations()[0];
            String field = column.field();
            String type = column.type();
            boolean defaultNull = column.defaultNull();
            
            sb.append("\t" + field).append(" ").append(type);
            if(defaultNull){
                if(type.toUpperCase().equals("TIMESTAMP")){
                    sb.append(",\n");
                }else{
                    sb.append(" DEFAULT NULL,\n");
                }
            }else{
                sb.append(" NOT NULL,\n");
                if(column.primaryKey()){
                    primaryKey = "PRIMARY KEY ("+field+")";
                }
            }
        }
        
        if(!StringUtils.isEmpty(primaryKey)){
            sb.append("\t").append(primaryKey);
        }
        sb.append("\n) DEFAULT CHARSET=utf8");
        
        return sb.toString();
    }
    
}

getCreateTableSQl方法是利用反射和注解有關的知識袍镀,給一個JavaBean自動生成建表語句默蚌,目前只支持MySQL,因為這方面的知識我也是剛開始學苇羡,寫得不好的地方還請各位多多包涵绸吸。

接下來,給JavaBean添加注解设江。

@Table(tableName = "t_user")
public class User{
   //屬性
}

屬性如下:

@Column(type = "varchar(30)" ,field = "id" ,primaryKey = true ,defaultNull = false)
private String id;        //主鍵锦茁,采用UUID

@Column(type = "VARCHAR(20)", field = "username")
private String username;  //用戶名

@Column(type = "VARCHAR(20)", field = "password")
private String password;  //密碼

@Column(type = "VARCHAR(60)", field = "headerPic")
private String headerPic; //頭像

@Column(type = "VARCHAR(60)", field = "email")
private String email;     //電子郵箱

@Column(type = "VARCHAR(2)", field = "sex")
private Integer sex;      //性別 0男 1女 3保密

@Column(type = "datetime", field = "create_time")
private String createTime;//創(chuàng)建時間

@Column(type = "timestamp", field = "update_time")
private String updateTime;//最后更新時間

@Column(type = "int(1)", field = "is_delete")
private Integer isDelete; // 刪除狀態(tài)  0未刪除  1刪除

@Column(type = "VARCHAR(200)", field = "address")
private String address;   //地址

@Column(type = "VARCHAR(15)", field = "telephone")
private String telephone; //電話

創(chuàng)建一個測試包和測試類:

package test;

import bean.User;
import util.TableUtils;

public class TestMain {
    public static void main(String[] args) {
        String sql = TableUtils.getCreateTableSQl(User.class);
        System.out.println(sql);
    }
}

運行

OK,拿到sql語句了叉存。

我已經(jīng)安裝了mysql码俩,用root用戶登陸后,新建一個database

使用這個database

將剛才得到的sql語句復制進去歼捏,加分號稿存,回車。

這就表明數(shù)據(jù)庫表已經(jīng)建好了瞳秽,默認編碼是UTF-8瓣履。

本文結(jié)束。

我要下載源碼

您的支持是我寫作的最大動力:

最后說一下更新的問題练俐,最近事情比較多袖迎,無奈改為周更了,正常情況下每周日定時更新。至于源碼燕锥,我還沒有放到github上辜贵,打算以后寫得差不多了再發(fā)布吧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末归形,一起剝皮案震驚了整個濱河市托慨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌连霉,老刑警劉巖榴芳,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異跺撼,居然都是意外死亡窟感,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門歉井,熙熙樓的掌柜王于貴愁眉苦臉地迎上來柿祈,“玉大人,你說我怎么就攤上這事哩至□锖浚” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵菩貌,是天一觀的道長卢佣。 經(jīng)常有香客問我,道長箭阶,這世上最難降的妖魔是什么虚茶? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮仇参,結(jié)果婚禮上嘹叫,老公的妹妹穿的比我還像新娘。我一直安慰自己诈乒,他們只是感情好罩扇,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著怕磨,像睡著了一般喂饥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肠鲫,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天仰泻,我揣著相機與錄音,去河邊找鬼滩届。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的帜消。 我是一名探鬼主播棠枉,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼泡挺!你這毒婦竟也來了辈讶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤娄猫,失蹤者是張志新(化名)和其女友劉穎贱除,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體媳溺,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡月幌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了悬蔽。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扯躺。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蝎困,靈堂內(nèi)的尸體忽然破棺而出录语,到底是詐尸還是另有隱情,我是刑警寧澤禾乘,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布澎埠,位于F島的核電站,受9級特大地震影響始藕,放射性物質(zhì)發(fā)生泄漏蒲稳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一鳄虱、第九天 我趴在偏房一處隱蔽的房頂上張望弟塞。 院中可真熱鬧,春花似錦拙已、人聲如沸决记。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽系宫。三九已至,卻和暖如春建车,著一層夾襖步出監(jiān)牢的瞬間扩借,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工缤至, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留潮罪,地道東北人。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像嫉到,于是被迫代替她去往敵國和親沃暗。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容