表关系比较简单,图书与图书分类为多对一关系,借阅书目与用户为多对一关系,借阅书目与书籍为多对一关系(实际上并没有用到这层关系,因为并没有做前台的借书功能(′Д`))
sql语句贴出一个借阅书目的,数据库用的是MySQL:
create table orderbook(
id int(11) not null auto_increment,
name varchar(255) default null,
uid int(11) default null,
bid int(11) default null,
borrowdate timestamp default CURRENT_TIMESTAMP,
constraint pk_orderbook_user foreign key (uid) references user (id),
constraint pk_orderbook_book foreign key (bid) references book (id),
primary key(id)
)engine=innodb default charset=utf8;
建立之后如图:
springboot的配置文件主要用来写入数据库驱动用户名密码和其他一些配置
#database
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/library_manage?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto = none
#thymeleaf
spring.thymeleaf.mode=LEGACYHTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.cache=false
#context,页面地址访问就以localhost:8080/开头,
#server.context-path=/library,则以localhost:8080/library开头
server.context-path=/
#设置上传文件大小,默认只有1 m
spring.http.multipart.maxFileSize=100Mb
spring.http.multipart.maxRequestSize=100Mb
#jpa对实体类的默认字段会把驼峰命名的属性,转换为字段名的时候自动加上下划线。 这个配置的作用就是去掉下划线
#比如属性名称是 createDate, jpa 默认转换为字段名 create_Date。 有了这个配置之后,就会转换为同名字段 createDate
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
#显示 hibernate运行的 sql 语句
spring.jpa.show-sql=true
前端部分采用的是thymeleaf模板引擎和vue.js渲染页面数据和绑定数据(vue这里仅仅是用到了这两个功能,没有用到脚手架),前端样式采用的bootstrap。
如图,页面目录如下:
admin目录下的页面分别:
include/admin目录下的页面分别为:
这样可以使得将页面中通用的部分单独拿出来,通过thymeleaf进行镶嵌
利用thymeleaf将include/admin中的页面嵌入到admin里的页面中,如下:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:include="include/admin/adminHeader::html('分类管理')" ></head> //在head中插入adminHeader.html
<body>
<div th:replace="include/admin/adminNavigator::html" ></div> //在body的一开头插入导航栏adminNavigator.html
<div id="workingplace">
此处省略一万行
<div th:replace="include/admin/adminPage::html" ></div> //插入分页
</div>
<div th:replace="include/admin/adminFooter::html" ></div>
</body>
adminHeader内包含所需要的外部js文件已经css文件,代码如下:
<template th:fragment="html(title)" >
<script src="js/jquery/2.0.0/jquery.min.js"></script>
<link href="css/bootstrap/3.3.6/bootstrap.min.css" rel="stylesheet">
<script src="js/bootstrap/3.3.6/bootstrap.min.js"></script>
<script src="js/vue/2.5.16/vue.min.js"></script>
<script src="js/axios/0.17.1/axios.min.js"></script>
<script src="js/moment/2.22.2/moment.js"></script> <!-- vue.js 格式化日期用的 -->
<link href="css/back/style.css" rel="stylesheet">
<script>
//判断是否为空
function checkEmpty(value,text){
if(null==value || value.length==0){
alert(text+ "不能为空");
return false;
}
return true;
}
...
//此处省略
...
</script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title th:text="${title}" ></title>
</template>
template标签配合th:include可以实现加载template模板中的内容,template标签加载后自动忽略。
而th:replace则是配合div标签自动将当前的div替换为th:replace的div标签
adminNavigator.html的代码
<div class="navitagorDiv" th:fragment="html">
<nav class="navbar navbar-default navbar-fixed-top navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<img style="margin-left:10px;margin-right:0px" class="pull-left navbar-brand" src="img/site/library.jpg" height="45px">
<a class="navbar-brand" href="/admin_login">图书馆管理后台</a>
<a class="navbar-brand" href="admin_category_list">分类管理</a>
<a class="navbar-brand" href="admin_user_list">用户管理</a>
<a class="navbar-brand" href="/admin_orderall_list">借阅管理</a>
</div>
</div>
</nav>
</div>
分类列表中的代码片段:
<head th:include="include/admin/adminHeader::html('分类管理')" ></head>
<body>
<div th:replace="include/admin/adminNavigator::html" ></div>
如上,通过镶嵌,这样每个页面就有一个导航栏
以listCategory.hmtl书籍分类列表页面为例:
上图部分html代码如下:
<div id="workingArea" >
<div class="listDataTableDiv">
<table class="table table-striped table-bordered table-hover table-condensed">
<thead>
<tr class="success">
<th>ID</th>
<th>分类名称</th>
<th>书籍管理</th>
<th>编辑</th>
<th>删除</th>
</tr>
</thead>
<tbody>
<tr v-for="bean in beans ">
<td>{{bean.id}}</td>
<td>
{{bean.name}}
</td>
<td>
<a :href="'admin_book_list?cid=' + bean.id "><span class="glyphicon glyphicon-shopping-cart"></span></a>
</td>
<td>
<a :href="'admin_category_edit?id=' + bean.id "><span class="glyphicon glyphicon-edit"></span></a>
</td>
<td>
<a href="#nowhere" @click="deleteBean(bean.id)"><span class=" glyphicon glyphicon-trash"></span></a>
</td>
</tr>
</tbody>
</table>
</div>
<div class="panel panel-warning addDiv">
<div class="panel-heading">新增分类</div>
<div class="panel-body">
<table class="addTable">
<tr>
<td>分类名称</td>
<td><input @keyup.enter="add" v-model.trim="bean.name" type="text" class="form-control"></td>
</tr>
<tr class="submitTR">
<td colspan="2" align="center">
<a href="#nowhere" @click="add" class="btn btn-success">提交</a>
</td>
</tr>
</table>
</div>
</div>
<div th:replace="include/admin/adminPage::html" ></div>
</div>
由一个存放书籍列表的表格table,和一个显示添加书籍的表格组成。
vue脚本部分:
<script>
$(function(){
var data4Vue = {
uri:'categories',
pagination:{},
beans: [],
bean:{id:0,name:""},
file:null,
keyword:''
};
//ViewModel
var vue = new Vue({
el: '#workingArea',
data: data4Vue,
mounted:function(){ //mounted 表示这个 Vue 对象加载成功了
this.list(0);
},
methods: {
list:function(start){
var url = this.uri+ "?start="+start;
axios.get(url).then(function(response) {
vue.pagination = response.data;
vue.beans = response.data.content;
});
},
listSearch:function () {
var url = "search?keyword="+vue.keyword;
axios.post(url).then(function (response) {
vue.beans = response.data;
})
},
jump: function(page){
jump(page,vue); //定义在adminHeader.html 中
},
jumpByNumber: function(start){
jumpByNumber(start,vue);
},
add: function () {
var url = this.uri;
axios.post(url,vue.bean).then(function () {
vue.list(0);
vue.bean = {id:0,name:'',hp:'0'};
})
},
deleteBean:function (id) {
if(!checkDeleteLink())
return;
var url = this.uri+"/"+id;
axios.delete(url).then(function (response) {
if (0!=response.data.length) //rest规范删除数据要求要会返回空字符串(控制器中delete返回null),所以进行判断
alert(response.data);
else
vue.list(0); //是空字符串则调第一页
})
}
}
});
});
</script>
页面渲染流程如下:
其中:
$(function () {。。。})
{% codeblock lang:JavaScript %}
var data4Vue = {
uri:'categories',
pagination:{},
beans: [],
bean:{id:0,name:""},
keyword:''
};
- vue里的el:#workingArea表示该vue对象是对id为workingArea的html标签区域进行数据渲染
- mounted表示对象加载完毕时自动执行mounted里面的函数
- methods在里面编写页面所需要的函数
- methods里的list函数中
{% codeblock lang:JavaScript %}
list:function(start){
var url = this.uri+ "?start="+start;
axios.get(url).then(function(response) {
vue.pagination = response.data;
vue.beans = response.data.content;
});
},
url为请求的地址,?后面为请求参数,服务器后端程序能通过注解自动识别?后的参数。
axios请求函数可以是get,post,delete等依情况定,请求成功后才会执行then里面的函数。then里面函数将返回的数据赋值给vue的数据变量中,vue通过在html标签中绑定的数据变量从而将数据渲染到页面中(请求的具体流程图在之后的后端部分给出),如下,beans变量
<tbody>
<tr v-for="bean in beans ">
<td>{{bean.id}}</td>
<td>
{{bean.name}}
</td>
<td>
<a :href="'admin_book_list?cid=' + bean.id "><span class="glyphicon glyphicon-shopping-cart"></span></a>
</td>
<td>
<a :href="'admin_category_edit?id=' + bean.id "><span class="glyphicon glyphicon-edit"></span></a>
</td>
<td>
<a href="#nowhere" @click="deleteBean(bean.id)"><span class=" glyphicon glyphicon-trash"></span></a>
</td>
</tr>
</tbody>
输入框等表单用v-model双向绑定,即输入的内容会绑定到v-model后的数据变量里,同时数据变量值的改变也会改变表单中的值。
样式主要采用bootstrap,在adminHeader.html引入
<nav class="navbar navbar-default navbar-fixed-top navbar-inverse">
<div class="navbar-header">
<img style="margin-left:10px;margin-right:0px" class="pull-left navbar-brand" src="img/site/library.jpg" height="45px">
<a class="navbar-brand" href="/admin_login">图书馆管理后台</a>
<a class="navbar-brand" href="admin_category_list">分类管理</a>
<a class="navbar-brand" href="admin_user_list">用户管理</a>
<a class="navbar-brand" href="/admin_orderall_list">借阅管理</a>
</div>
</nav>
nav标签中的属性navbar navbar-default nvarbar-fixed-top navbar-inverse分别就是bootstrap样式中的导航栏,导航栏默认样式,固定不随页面滑动,颜色反转(本来是白色的)
<table class="table table-striped table-bordered table-hover table-condensed">
<tr class="success">
table:普通表格,table-striped:斑马线(颜色交替),table-border:列与列之间的分割线,table-hover:鼠标经过有效果,table-condensed:响应式效果,根据页面大小变换。
行标签中有集中颜色可选,其中success为绿色
<div class="panel panel-warning addDiv">
<div class="panel-heading">新增分类</div>
<div class="panel-body">
.....
...
panel:一个面板, panel-warning:颜色警告色(黄色)
panel-heading:面板标题,body为面板内容
面板里的内容为一个2x2的table构成
登录页面采用bootstrap中的栅格化布局(网上物色的登录界面,在css中改了背景)。基本思想是bootstrap将页面分成了12份利用class属性col-lg-xx来配置个标签所占位置 ,如图:
所以标题输入框以及按钮class中都设置超过6的数值就会一行的一行的排列。
input中的required属性表示不能为空,autofocus表示页面加载后自动获得焦点
<div id="form">
<form>
<div class="mycenter">
<div class="mysign">
<div class="col-lg-12 text-center text-info">
<h2>
图书馆管理系统
</h2>
</div>
<div class="col-lg-11">
<input v-model="user.name" type="text" name="username" placeholder="请输入账户名" required autofocus/>
</div>
<div class="col-lg-10">
</div>
<div class="col-lg-10">
<input v-model="user.passWord" type="password" name="password" placeholder="请输入密码" required/>
</div>
<div class="col-lg-10">
</div>
<div class="col-lg-10">
</div>
<div class="col-lg-10">
<button @click="login" type="button" id="btn" class="btn btn-success col-lg-12">
登录</button>
</div>
</div>
</div>
</form>
</div>
改写css,图片,以及前端框架js文件的路径到resource/webapp路径下,在idea中如下设置
setting -> project structure ->facets设置web resource directory
这样外部静态文件能采用如下相对路径的方式引入:
<script src="js/jquery/2.0.0/jquery.min.js"></script>
<link href="css/bootstrap/3.3.6/bootstrap.min.css" rel="stylesheet">
<script src="js/bootstrap/3.3.6/bootstrap.min.js"></script>
<script src="js/vue/2.5.16/vue.min.js"></script>
<script src="js/axios/0.17.1/axios.min.js"></script>
<script src="js/moment/2.22.2/moment.js"></script> <!-- vue.js 格式化日期用的 -->
<link href="css/back/style.css" rel="stylesheet">
online slot games free slots slots games free free slots [url=http://onlinecasinouse.com/# ]casino blackjack [/url]
[url=https://silagrarx.com/]silagra tablets[/url]
[url=http://phenergansr.com/]phenergan 25mg tablets[/url] [url=http://elimitep.com/]order elimite online[/url] [url=http://cialisz.com/]purchase cialis 20 mg[/url] [url=http://hydroxychloroquina.com/]hydroxychloroquine cost[/url] [url=http://ahydroxychloroquine.com/]plaquenil 400 mg[/url]
[url=http://tadalafilhit.com/]generic tadalafil 5mg price[/url] [url=http://baclofen365.com/]how to get baclofen[/url] [url=http://periactinmed.com/]buy periactin appetite stimulant[/url] [url=http://zestoretic24.com/]zestoretic 5 mg[/url] [url=http://wellbutrin15.com/]zyban pills[/url]
[url=https://sildenefil.com/]sildenafil 20 mg tablet cost[/url] [url=https://sildenafilt.com/]sildenafil 50 mg buy online india[/url] [url=https://trimoxx.com/]amoxicillin 500 mg buy online[/url] [url=https://cephalexinlab.com/]cephalexin best price[/url] [url=https://glucophaghe.com/]can i buy metformin over the counter in australia[/url] [url=https://plavixm.com/]plavix[/url] [url=https://buyhydroxychloroquine.us.com/]hydroxychloroquine sulfate tab 200 mg[/url] [url=https://zoviraxz.com/]acyclovir cream singapore[/url] [url=https://sildenafil240.com/]where to buy generic sildenafil[/url] [url=https://lasixfuro.com/]furosemide uk[/url] [url=https://kamagrasr.com/]kamagra 50 mg oral jelly[/url] [url=https://benicar911.com/]generic benicar pills[/url] [url=https://buyviagaonline.com/]viagra tablet online india[/url] [url=https://ciprotab.com/]cipro cost usa[/url] [url=https://lanoxin24.com/]digoxin brand name[/url] [url=https://furosemide3.com/]furosemide brand name in india[/url] [url=https://elimitep.com/]where to buy elimite cream[/url] [url=https://albenzarx.com/]buy albendazole tablets[/url] [url=https://cytotectab.com/]cheap cytotec pills online[/url] [url=https://tadacialis.com/]cheap 5 mg tadalafil[/url]
[url=https://sildenafilt.com/]sildenafil 90 mg[/url] [url=https://tadalafilcs.com/]cialis usa pharmacy[/url] [url=https://plavixm.com/]price of plavix in india[/url] [url=https://ataraxmed.com/]atarax 25mg tab[/url] [url=https://suhagra1.com/]suhagra 50mg buy online india[/url] [url=https://dapoxetine360.com/]dapoxetine prescription[/url] [url=https://anafraniltab.com/]anafranil 25 mg tablet[/url] [url=https://buyhydroxychloroquine.us.org/]hydroxychloroquine 70 mg[/url]
[url=https://silagrarx.com/]silagra 100mg tablets[/url] [url=https://sildenaviagra.com/]sildenafil otc uk[/url] [url=https://viagraphrm.com/]viagra tablets in india price[/url] [url=https://buyhydroxychloroquine.us.com/]plaquenil 800 mg[/url] [url=https://vardemafil.com/]levitra uk buy[/url]