基于bootstrap的web登陸實(shí)例

原文鏈接:基于bootstrap的web登陸實(shí)例

前情提要
之前已經(jīng)搭好的springMVC+myBatis項(xiàng)目骨架,詳情請(qǐng)看-->傳 送 門态贤。

獲取bootstrap

方法一

使用 Bootstrap 中文網(wǎng)提供的免費(fèi) CDN 加速服務(wù)(同時(shí)支持 http 和 https 協(xié)議)
將下面的代碼copy到自己的JSP頁面中即可舱呻。

<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" >

<!-- 可選的Bootstrap主題文件(一般不用引入) -->
<link rel="stylesheet" >

<!-- jQuery文件。務(wù)必在bootstrap.min.js 之前引入 -->
<script src="http://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>

<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="http://cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>

好處悠汽,不需要下載bootstrap的JS和CSS文件箱吕,只要有網(wǎng)絡(luò)就能引用到。

方法二

  • 到官網(wǎng)下載編譯好的bootstrap-->傳送門柿冲,它是編譯并壓縮后的 CSS茬高、JavaScript 和字體文件。不包含文檔和源碼文件假抄。當(dāng)然你也可以下載源碼版怎栽,源碼包含編譯好的文件。
  • 另外bootstrap是完全基于jQuery開發(fā)的宿饱,要使用bootstrap熏瞄,必須依賴jQuery。所以再把jQuery下載下來刑棵。
  • 把下載下來的文件copy到項(xiàng)目里面巴刻,如圖:


這樣我們就能使用bootstrap給我提供的前端框架開發(fā)漂亮的web應(yīng)用了愚铡。


添加JSP頁面

在此之前蛉签,為了避免重復(fù)勞動(dòng),我們先創(chuàng)建一個(gè)JSP模板沥寥。
點(diǎn)擊window-->搜索JSP-->templent-->new碍舍, Name隨便輸入,Context選擇New JSP邑雅,如圖:


  • JSP模板代碼
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://"+ request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE html><!--Bootstrap 使用到的某些 HTML 元素和 CSS 屬性需要將頁面設(shè)置為 HTML5 文檔類型-->
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- 上述3個(gè)meta標(biāo)簽*必須*放在最前面片橡,任何其他內(nèi)容都*必須*跟隨其后! -->
  <title>Document</title>
  
  <link rel="stylesheet" href="<%=basePath %>resources/css/bootstrap/bootstrap.css">
</head>
<body>

  <!--bootstrap需要依賴jQuery淮野,所以必須在他之前先引入jQuery-->
  <script src="<%=basePath %>resources/js/bootstrap/jquery-1.11.3.min.js"></script>
  <script src="<%=basePath %>resources/js/bootstrap/bootstrap.js"></script>
</body>
</html>

在webapp目錄下新建login.jsp

  • login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
  String path = request.getContextPath();
  String basePath = request.getScheme() + "://"
      + request.getServerName() + ":" + request.getServerPort()
      + path + "/";
%>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>login</title>
  
  <link rel="stylesheet" href="<%=basePath %>resources/css/bootstrap/bootstrap.css">
  <link rel="stylesheet" href="<%=basePath %>resources/css/myCss/login.css">
</head>
<body>
  <!--引入頭部JSP-->
  <jsp:include page="head.jsp" ></jsp:include>
  <!--使用模態(tài)框的方式模擬一個(gè)登陸框-->
  <div class="modal show" id="loginModal">
    <div class="modal-dialog">
      <div class="modal-content">
            <div class="modal-header">
              <button type="button" class="close">×</button>
              <h1 class="text-center text-primary">登錄</h1>
            </div>
            <div class="modal-body">
            <form class="form col-md-12 center-block" id="loginForm" action="main/successLogin.do" method="post">
            <div class="form-group-lg"  id="accountDiv">
              <label class="sr-only" for="inputAccount">賬號(hào)</label>
              <div class="input-group">
                <div class="input-group-addon"><span class="glyphicon glyphicon-user" aria-hidden="true"></span></div>
                <input class="form-control" id="inputAccount" name="accountNo" type="text" placeholder="賬號(hào)" required autofocus>
              </div>
              <div class="hidden text-center" id="accountMsg"><span class="glyphicon glyphicon-exclamation-sign"></span>用戶名不存在</div>
            </div>
            <br>
            <div class="form-group-lg" id="pwdDiv">
              <label class="sr-only" for="inputPassword">密碼</label>
              <div class="input-group">
                <div class="input-group-addon"><span class="glyphicon glyphicon-lock"></span></div>
                <input class="form-control" id="inputPassword" name="pwd" type="password" placeholder="密碼" required>
                <div class="input-group-addon"><span class="glyphicon glyphicon-eye-open"></span></div>
              </div>
              <div class="hidden text-center" id="pwdMsg"><span class="glyphicon glyphicon-exclamation-sign"></span>用戶名密碼錯(cuò)誤</div>
            </div>
            <div class="checkbox">
              <label> <input type="checkbox" value="remember-me">記住我</label>
            </div>
            <div class="form-group">
              <button class="btn btn-default btn-lg col-md-6" id="btn_register" type="submit">注冊(cè)</button>
              <button class="btn btn-primary btn-lg col-md-6" id="btn_login" type="button" >登錄</button>
            </div>
          </form>
        </div>
        <div class="modal-footer">
        
        </div>
      </div>
    </div>
  </div>
  <!-- /container -->
  <script src="<%=basePath %>resources/js/bootstrap/jquery-1.11.3.min.js"></script>
  <script src="<%=basePath %>resources/js/bootstrap/bootstrap.js"></script>
  <script src="<%=basePath %>resources/js/myJs/login.js"></script>
</body>
</html>

  • login.js
$("#btn_login").click(function(){
  var loginObj = new Object();
  loginObj.accountNo= $("#inputAccount").val();
  loginObj.pwd= $("#inputPassword").val();
  var loginJson = JSON.stringify(loginObj); //將JSON對(duì)象轉(zhuǎn)化為JSON字符  
  $.post('main/validateLogin.do',
      {"loginObj":loginJson},
      function(e){
        e=JSON.parse(e); //由JSON字符串轉(zhuǎn)換為JSON對(duì)象
        if(e.accountMsg){
          $("#accountDiv").addClass("has-error");
          $("#accountMsg").removeClass("hidden");
          
          $("#pwdDiv").removeClass("has-error");
          $("#pwdMsg").addClass("hidden");
        }else if (e.pwdMsg){
          $("#accountDiv").removeClass("has-error");
          $("#accountMsg").addClass("hidden");
          
          $("#pwdDiv").addClass("has-error");
          $("#pwdMsg").removeClass("hidden");
        }else if (e.user){
          //location.href="main/successLogin.do";
          $("#loginForm").submit();
        }
  });
});

  • login.css
#loginModal{
  position: absolute;
  top: 50%;
  -webkit-transform: translateY(-50%);
  -moz-transform:  translateY(-50%);
  -ms-transform:  translateY(-50%);
  -o-transform:  translateY(-50%);
  transform:  translateY(-50%);
  background-color: #eee;
}

完了之后效果基本就像這樣了:



接下來就得來寫后臺(tái)代碼了

在controller包下面新增一個(gè)LoginController.class

  • LoginController.class
package com.dimon.xwater.controller;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSONObject;
import com.dimon.xwater.dao.XUserMapper;
import com.dimon.xwater.pojo.XUser;
import com.dimon.xwater.utils.RequestUtils;
import com.dimon.xwater.utils.ResponseUtils;

@Controller
@RequestMapping("/main")
public class LoginController {
  @Resource
  private XUserMapper userDao;
  
  /**
   * 登陸跳轉(zhuǎn)
   * @param request
     * @param model
     * @return
   */
  @RequestMapping("/successLogin")
  public ModelAndView login(HttpServletRequest request,ModelAndView model){
      String accountNo = RequestUtils.getString(request, "accountNo");
      String pwd = RequestUtils.getString(request, "pwd");
      XUser user = new XUser();
      user.setAccountNo(accountNo);
      user.setPwd(pwd);
      model.addObject("user", user);
    //跳轉(zhuǎn)到/jsp/main.jsp頁面
    model.setViewName("main");
    return model;
  }
  
  /**
   * 登陸表單校驗(yàn)
   * @param request
   * @param response
   */
  @RequestMapping("/validateLogin")
  public void login(HttpServletRequest request, HttpServletResponse response){
    //獲取form表單數(shù)據(jù)
    String loginObj = RequestUtils.getString(request, "loginObj");
    //JSON字符串序列化成JSON對(duì)象
    JSONObject loginJosn = JSONObject.parseObject(loginObj);
    String accountNo = loginJosn.getString("accountNo");
    String pwd = loginJosn.getString("pwd");
    //根據(jù)賬號(hào)查詢用戶名是否存在
    XUser selectUser = userDao.selectByAcccountNo(accountNo);
    JSONObject result = new JSONObject();
    
    if (null == selectUser){
      result.put("accountMsg", "用戶名不存在");
    }else if (!pwd.equals(selectUser.getPwd())){
      result.put("pwdMsg", "用戶名密碼錯(cuò)誤");
    }else {
      result.put("user",selectUser);
    }
    String resultStr = result.toJSONString();
    
    ResponseUtils.send(response, resultStr);
  }
}


用到的兩個(gè)工具方法捧书,也記錄一下吹泡。

  • RequestUtils.getString();
    /**
     * 返回字符串,刪除了首尾空格,如果不存在則返回null
     * 
     * @param request
     * @param key
     * @return
     */
    public static String getString(HttpServletRequest request, String key) {
        String value = request.getParameter(key);
        if (StringUtils.isEmpty(value)) {
            return StringUtils.trimWhitespace(value);
        }
        return value;
    }
  • ResponseUtils.send();
    /**
     * 發(fā)送json格式數(shù)據(jù)到頁面
     * 
     * @param response
     * @param content
     */
    public static void send(HttpServletResponse response, String content) {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html");
        PrintWriter out = null;
        try {
            out = response.getWriter();
            //若發(fā)送數(shù)據(jù)為null 則默認(rèn)為""
            if(content == null){
                content = "";
            }
            out.write(content);
        }
        catch (IOException e) {
            log.error(e.getLocalizedMessage(), e);
        }
        finally {
            if (out != null){
                out.close();
            }
        }
    }

還有根據(jù)賬號(hào)去查詢用戶是否存在揍鸟,因?yàn)橘~號(hào)不是表的主鍵普筹,所以自動(dòng)生成的mapping.xml中沒有相應(yīng)的查詢SQL語句,需要我們手動(dòng)給它加上:

  <select id="selectByAcccountNo" resultMap="BaseResultMap" parameterType="java.lang.String" >
    <!--
      WARNING - @mbggenerated
      This element is automatically generated by MyBatis Generator, do not modify.
    -->
    select 
    <include refid="Base_Column_List" />
    from X_USER
    where ACCOUNT_NO = #{id,jdbcType=VARCHAR}
  </select>

同時(shí)再到XUserMapping.java中添加一個(gè)selectByAcccountNo接口:

XUser selectByAcccountNo(String accountNo);

這樣一個(gè)登陸頁面實(shí)例就算完成了橡疼,登陸驗(yàn)證一下:

  • 輸入錯(cuò)誤的賬號(hào)或密碼:



  • 輸入正確的賬號(hào)和密碼:


附上數(shù)據(jù)庫表結(jié)構(gòu):

--系統(tǒng)用戶表
truncate table xuser;
drop table xuser;
create table xuser(   
xuser_id number(10),
xuser_name varchar2(32),
xuser_realName varchar2(64),
xuser_acctno varchar2(64),
xuser_pwd varchar2(64),
xuser_email varchar2(64),
xuser_mphone varchar2(11),
xuser_addrId number(10),
xuser_lastLogin timestamp,
CONSTRAINT pk_xuser PRIMARY KEY (xuser_id),
CONSTRAINT uk_xuser UNIQUE (xuser_acctno)
);

COMMENT ON TABLE xuser IS '用戶表';
COMMENT ON COLUMN xuser.xuser_name IS '昵稱';
COMMENT ON COLUMN xuser.xuser_realName IS '真實(shí)姓名';
COMMENT ON COLUMN xuser.xuser_acctno IS '登陸賬號(hào)';
COMMENT ON COLUMN xuser.xuser_pwd IS '密碼';
COMMENT ON COLUMN xuser.xuser_email IS '郵箱';
COMMENT ON COLUMN xuser.xuser_mphone IS '手機(jī)號(hào)碼';
COMMENT ON COLUMN xuser.xuser_addrId IS '地址ID舆吮,外鍵關(guān)聯(lián)地址表';
COMMENT ON COLUMN xuser.xuser_lastLogin IS '最后登陸時(shí)間';

--創(chuàng)建序列
drop sequence xUser_seq;
CREATE SEQUENCE xUser_seq
INCREMENT BY 1
START WITH 1
NOMAXVALUE
NOCYCLE
NOCACHE;

--ID自增長的觸發(fā)器
CREATE OR REPLACE TRIGGER ins_xUser_triger
  BEFORE INSERT ON xuser
  FOR EACH ROW
  WHEN (new.xuser_id is null)
begin
  select xUser_seq.Nextval into :new.xuser_id from dual;
end;


--地址表
drop table xaddr;
create table xaddr(
xaddr_id number(10),
xaddr_prov varchar2(32),
xaddr_ctiy varchar2(32),
xaddr_dist varchar2(32),
xaddr_detail varchar2(100),
xaddr_type char,
CONSTRAINT pk_xaddr PRIMARY KEY (xaddr_id)
);

COMMENT ON TABLE xaddr IS '地址表';
COMMENT ON COLUMN xaddr.xaddr_prov IS '省';
COMMENT ON COLUMN xaddr.xaddr_ctiy IS '市';
COMMENT ON COLUMN xaddr.xaddr_dist IS '區(qū)';
COMMENT ON COLUMN xaddr.xaddr_detail IS '詳細(xì)地址';
COMMENT ON COLUMN xaddr.xaddr_type IS '地址類型';


--枚舉字典表
drop table xdic;
create table xdic(
xdic_id number(10),
xdic_tab varchar2(32) not null,
xdic_col varchar2(32) not null,
xdic_key char(2),
xdic_val varchar2(32),
constraint pk_xdic primary key (xdic_id)
);
COMMENT ON TABLE xdic IS '枚舉字典表';
COMMENT ON COLUMN xdic.xdic_id IS '所屬表';
COMMENT ON COLUMN xdic.xdic_col IS '所屬字段';
COMMENT ON COLUMN xdic.xdic_key IS '字典key';
COMMENT ON COLUMN xdic.xdic_val IS '字典值';

--登陸登出記錄
create table xlogin(
xlogin_id number(10),
xlogin_localip varchar2(32),
xlogin_netip varchar2(32),
xlogin_logintime timestamp,
xlogin_logouttime timestamp,
xlogin_ipaddr varchar2(32),
constraint pk_xlogin primary key (xlogin_id)
);

COMMENT ON TABLE xlogin IS '登陸記錄';
COMMENT ON COLUMN xlogin.xlogin_localip IS '本地地址';
COMMENT ON COLUMN xlogin.xlogin_netip IS '網(wǎng)絡(luò)地址';
COMMENT ON COLUMN xlogin.xlogin_logintime IS '登陸時(shí)間';
COMMENT ON COLUMN xlogin.xlogin_logouttime IS '登出時(shí)間';
COMMENT ON COLUMN xlogin.xlogin_ipaddr IS 'IP所在地';

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末揭朝,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子色冀,更是在濱河造成了極大的恐慌潭袱,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锋恬,死亡現(xiàn)場(chǎng)離奇詭異屯换,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)与学,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門趟径,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人癣防,你說我怎么就攤上這事蜗巧。” “怎么了蕾盯?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵幕屹,是天一觀的道長。 經(jīng)常有香客問我级遭,道長望拖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任挫鸽,我火速辦了婚禮说敏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘丢郊。我一直安慰自己盔沫,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布枫匾。 她就那樣靜靜地躺著架诞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪干茉。 梳的紋絲不亂的頭發(fā)上谴忧,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼沾谓。 笑死委造,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的均驶。 我是一名探鬼主播争涌,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼辣恋!你這毒婦竟也來了亮垫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤伟骨,失蹤者是張志新(化名)和其女友劉穎饮潦,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體携狭,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡继蜡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了逛腿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稀并。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖单默,靈堂內(nèi)的尸體忽然破棺而出碘举,到底是詐尸還是另有隱情,我是刑警寧澤搁廓,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布引颈,位于F島的核電站,受9級(jí)特大地震影響境蜕,放射性物質(zhì)發(fā)生泄漏蝙场。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一粱年、第九天 我趴在偏房一處隱蔽的房頂上張望售滤。 院中可真熱鬧,春花似錦台诗、人聲如沸完箩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嗜憔。三九已至秃励,卻和暖如春氏仗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國打工皆尔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呐舔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓慷蠕,卻偏偏與公主長得像珊拼,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子流炕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

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

  • 22年12月更新:個(gè)人網(wǎng)站關(guān)停澎现,如果仍舊對(duì)舊教程有興趣參考 Github 的markdown內(nèi)容[https://...
    tangyefei閱讀 35,181評(píng)論 22 257
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,098評(píng)論 25 707
  • 一 從上月開始工作驟然多了起來剑辫,幾乎每天都在加班,瞬間感覺回到了當(dāng)初某互聯(lián)網(wǎng)公司的錯(cuò)覺渠欺。最近加上快到年底妹蔽,常規(guī)工作...
    沅辰_chris閱讀 441評(píng)論 2 0
  • 1.做第一塊PCB出的錯(cuò) 1.電阻R1選錯(cuò)了(計(jì)算錯(cuò)誤),導(dǎo)致可調(diào)電壓最大只有13.53V挠将。 2.機(jī)械層(板子外形...
    冷面水手閱讀 552評(píng)論 0 2
  • 每個(gè)人都是一片獨(dú)特的葉子有屬于自己的脈絡(luò)別人只看到你普普通通并沒什么特別他卻能在人群中一樣認(rèn)出你知道你的善良體貼知...
    小生足跡閱讀 286評(píng)論 0 1