前情提要
之前已經(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所在地';