基於SSM的個人博客


1.前言

學習了SSM框架后練手,寫這個博客大概花了一個多星期。博客基本功能都有實現,后台代碼寫地比較簡單。前端頁面仿造Hexo博主的博客頁面(傳送門:https://jerryc.me/),由於本人前端技術有限,只能寫一個大概的頁面。

2.技術總結

前端:bootstrap+layui
(bootstrap主要用於實現響應式,layui寫后台管理系統頁面)
后台:SpringMVC+Spring+Mybatis
(Maven搭建環境)
數據庫:Mysql

3.主要功能

添加文章、管理文章、顯示/隱藏文章、添加標簽分類、管理標簽分類、評論文章、評論管理、分享文章、友鏈的管理、個人資料更新

4.數據庫設計

文章表
在這里插入圖片描述
分類表
在這里插入圖片描述
標簽表
在這里插入圖片描述
標簽-文章映射表
在這里插入圖片描述
評論表
在這里插入圖片描述
友鏈表
在這里插入圖片描述
用戶表
在這里插入圖片描述

5.項目結構

在這里插入圖片描述

6.部分頁面功能

(1)博客首頁

在這里插入圖片描述
首頁文章列表分頁功能用的是layui的分頁模塊

HTML代碼:
在這里插入圖片描述
JS代碼:

<script>
    window.onload = function() {
        loadData(); //請求文章數據 
        getPage(); //分頁操作 

    }
    var page = 1; //設置首頁頁碼 
    var limit = 5; //設置一頁顯示的條數 
    var count; //總條數 

    function loadData() {
        $.ajax({
                type : "post",
                url : "PostController/findByPageDesc",//對應controller的URL 
                async : false,
                dataType : 'json',
                data : {
                        "curr" : page,
                        "nums" : limit,
                    },
                success : function(msg) {
                    count = msg.count; //設置總條數 
                    var html = [];
                    var post = msg.data;

                    for (var i = 0; i < post.length; i++) {
                        html.push('<div class=" articleboder">'
                                    + '<div id="'
                                    + post[i].id
                                    +'" class="col-sm-6 col-xs-12 articleimg" οnclick="javascript:article(this)">'
                                    + '<img src="./upload/'+post[i].img+'"/></div>'
                                    + '<div class="col-sm-6 col-xs-12 articleintro">'
                                    + '<div class="hidden-xs articlehidden"></div>'
                                    + '<div class="visible-xs articlevisible"></div>'
                                    + '<div id="'
                                    + post[i].id
                                    + '" class="title" οnclick="javascript:article(this)">'
                                    + post[i].title
                                    + '</div>'
                                    + '<div class="articledate">'
                                    + ' <span><i class="fa fa-calendar" aria-hidden="true"></i><a>'
                                    + post[i].timeString
                                    + '</a></span>'
                                    + ' <span><a>|</a></span>'
                                    + ' <span><i class="fa fa-inbox article-meta__icon" aria-hidden="true"></i><a>'
                                    + post[i].typeString
                                    + '</a></span>'
                                    + '</div>'
                                    + '<div class="intro">'
                                    + post[i].summary
                                    + '</div>'
                                    + '</div>'
                                    + '</div>');
                    }
                    $(".content").empty().append(html);
                }
            });
    }

    function getPage() {
        layui.use('laypage', function() {
            var laypage = layui.laypage;
            //執行一個laypage實例 
            laypage.render({
                elem : 'demo2', //注意,這里的 demo2 是 ID,不用加 # 號 
                count : count, //數據總數,從服務端得到 
                limit : limit, //每頁條數設置 
                theme : '#1E9FFF',
                jump : function(obj, first) {
                    //obj包含了當前分頁的所有參數,比如: 
                    console.log(obj.curr); //得到當前頁,以便向服務端請求對應頁的數據。 
                    console.log(obj.limit); //得到每頁顯示的條數 
                    page = obj.curr; //改變當前頁碼 
                    limit = obj.limit;
                    //首次不執行 
                    if (!first) {
                        loadData(); //加載數據 
                    }
                }
            });
        });
    }		
</script>

后台代碼:

@RequestMapping("/findByPageDesc")
	public @ResponseBody String  findByPageDesc(Integer curr, Integer nums) throws JsonProcessingException{
		int pagenum=(curr - 1)*nums;
		List<Post> posts = postService.findByPageDesc(pagenum, nums);
		JSONObject object = new JSONObject();
		object.put("code", 0);
		object.put("msg", "");
		object.put("count", postService.count());
		object.put("data", posts);
		System.out.println(object.toJSONString());
		return object.toJSONString();		
	}

(2)隨機顏色大小標簽

在這里插入圖片描述
HTML代碼:
在這里插入圖片描述
JS代碼:

<script>
	//分頁
	window.onload = function() {
		loadData(); //請求數據 
		label();
	}

	function loadData() {
		$.ajax({
			type : "post",
			url : "TagController/selectAll",//對應controller的URL 
			async : false,
			dataType : 'json',
			success : function(msg) {
				var html = [];
				var tag = msg.data;
				for (var i = 0; i < tag.length; i++) {
					html.push('<a href="label_detail.jsp?tagid=' + tag[i].id
							+ '">' + tag[i].tag + '</a>');
				}
				$(".content").empty().append(html);
			}
		});
	}

	function label() {
		$(document).ready(function() {
			var obj = $("#wrap a");//獲取a標簽中的數據
			function rand(num) {
				//parseInt();將字符串轉為整數
				//Math.random();生成隨機數
				return parseInt(Math.random() * num + 1);
			}

			function randomcolor() {
				var str = Math.ceil(Math.random() * 16777215).toString(16);
				if (str.length < 6) {
					str = "0" + str;
				}
				return str;
			}

			for (len = obj.length, i = len; i--;) {
				obj[i].style.left = rand(600) + "px";//標簽左右間距
				obj[i].style.top = rand(400) + "px";//標簽上下間距
				obj[i].className = "color" + rand(5);
				obj[i].style.zIndex = rand(5);//設置元素的堆疊順序
				obj[i].style.fontSize = rand(5) + 18 + "px";//隨機字體大小這里是18-23
				obj[i].style.color = "#" + randomcolor();//字體顏色
				obj[i].style.padding = rand(15) + "px";
			}
		});
	}
</script>

后台返回標簽的Json字符串

(3)寫文章

在這里插入圖片描述
文章內容使用的是百度的ueditor,百度ueditor下載JSP版本,把解壓后的文件放進項目目錄里,查看官方文檔進行配置。

(4)文章管理頁面

在這里插入圖片描述
文章管理頁面用的是layui的table模塊,有編輯、刪除和顯示(隱藏)三個功能。
表格數據渲染:
HTML代碼:

<table id="test" lay-filter="test"></table>

JS代碼:

<script type="text/html" id="toolbarDemo">
	<div class="layui-btn-container">
		<button class="layui-btn layui-btn-sm" lay-event="getCheckData">獲取選中行數據</button>
        <button class="layui-btn layui-btn-sm" lay-event="getCheckLength">獲取選中數目</button>
        <button class="layui-btn layui-btn-sm" lay-event="isAll">驗證是否全選</button>
    </div>
</script>
         
<script type="text/html" id="barDemo">
	<a class="layui-btn layui-btn-sm layui-bg-blue" lay-event="edit">編輯</a>
	<a class="layui-btn layui-btn-sm layui-btn-danger" lay-event="del">刪除</a>
</script>

<script id="switchTpl" type="text/html">
	<input type="checkbox"  name="display"  value = {{d.display}} lay-skin="switch" lay-text="顯示|隱藏" lay-filter="display" {{ d.display == '1' ? 'checked' : '' }}>
</script>
<script src="${pageContext.request.contextPath}/resources/layui/layui.all.js"></script>
<script>
//JavaScript代碼區域
layui.use('element', function(){
  var element = layui.element; 
});

//顯示或隱藏文章
layui.use('form',function(){
	var form = layui.form
	form.on('switch(display)', function(obj){
		//根據業務判斷是開啟還是關閉
		var state = obj.elem.checked?0:1;
		//取數據(根據索引table.cache里面的行數據)
		var index  = obj.othis.parents('tr').attr("data-index");
		var id = tableData[index].id;
		$.ajax({
			url: '../PostController/display?id='+id+'&display='+state,
			type: "post",
			dataType:"json",
			success: function(suc) {
				if(suc.code === 1) {
					if(suc.msg === 0){
						layer.msg("文章已隱藏", {
							icon: 6
						});
					}else if(suc.msg === 1){
						layer.msg("文章已顯示", {
							icon: 6
						});
					}
				} else {
					layer.msg("設置失敗,請稍后再試!", {
						icon: 5
					});
				}
			}
		});	
	});
});

var tableData;

layui.use('table', function(){
    var table = layui.table;

    table.render({
      elem: '#test'
      ,url:'../PostController/findByPage'
      ,method:'post'         
      ,limits : [5,10,15,20]
      ,limit : 10
      ,request: {
        pageName: 'curr' ,//頁碼的參數名稱,默認:page
        limitName: 'nums' //每頁數據量的參數名,默認:limit
      }
      ,toolbar: '#toolbarDemo' //開啟頭部工具欄,並為其綁定左側模板
      ,defaultToolbar: ['filter', 'exports', 'print', { //自定義頭部工具欄右側圖標。如無需自定義,去除該參數即可
        title: '提示'
        ,layEvent: 'LAYTABLE_TIPS'
        ,icon: 'layui-icon-tips'
      }]
      ,title: '用戶數據表'
      ,cols: [[
        {type: 'checkbox', fixed: 'left'}
        ,{field:'id', title:'ID', width:70, unresize: true, sort: true}
        ,{field:'title', title:'標題',width:328}
        ,{field:'typeString', title:'分類',width:158}
        ,{field:'clickhit', title:'點擊數',width:125, sort: true}
        ,{field:'replyhit', title:'評論數',width:125, sort: true}
        
        ,{field:'timeString', title:'發表時間',width:188, sort: true}
        
        ,{field:'display', title:'顯示狀態',width:120,templet:"#switchTpl"}

        ,{fixed: '', title:'操作', fixed: 'right', width:132, toolbar: '#barDemo'}
      ]]
      ,page: true
      ,id:"tableIns"
      ,done:function(){
			tableData = table.cache.tableIns;
      }
    });
    
    //頭工具欄事件
    table.on('toolbar(test)', function(obj){
      var checkStatus = table.checkStatus(obj.config.id);
      switch(obj.event){
        case 'getCheckData':
          var data = checkStatus.data;
          layer.alert(JSON.stringify(data));
        break;
        case 'getCheckLength':
          var data = checkStatus.data;
          layer.msg('選中了:'+ data.length + ' 個');
        break;
        case 'isAll':
          layer.msg(checkStatus.isAll ? '全選': '未全選');
        break;
        
        //自定義頭工具欄右側圖標 - 提示
        case 'LAYTABLE_TIPS':
          layer.alert('這是工具欄右側自定義的一個圖標按鈕');
        break;
      };
    });
    
    //監聽行工具事件
    table.on('tool(test)', function(obj){
      var data = obj.data
      ,layEvent = obj.event; //獲得 lay-event 對應的值
      console.log(obj)
	  switch(layEvent){
	  		case 'del':
	  			var delIndex = layer.confirm('真的刪除"' + data.title + '"嗎?', function(delIndex) {
					$.ajax({
						url: '../PostController/delete?id='+data.id,
						type: "post",
						dataType:"json",
						success: function(suc) {
							if(suc.code === 1) {
								obj.del(); //刪除對應行(tr)的DOM結構,並更新緩存
								layer.close(delIndex);
								console.log(delIndex);
								layer.msg("刪除成功", {
									icon: 1
								});
							} else {
								layer.msg("刪除失敗", {
									icon: 5
								});
							}
						}
					});
					layer.close(delIndex);
				});
			break;
	  		case 'edit':	
	  				/* $.ajax({ url: '../PostController/editPost?id='+data.id, type: "get" }); */
	  				window.location.href="../PostController/editPost?id="+data.id;
				break;
	  }    
    });
});
</script>

后台查詢、刪除、顯示(隱藏)文章的Controller省略

(5)圖片上傳功能和回顯

在這里插入圖片描述
在這里插入圖片描述
“我的友鏈”和“基本資料”頁面都有圖片上傳,用的是layui的文件上傳功能。圖書上傳成功后,前端頁面會回顯圖片。
HTML代碼:
在這里插入圖片描述
JS代碼:

<script src="${pageContext.request.contextPath}/resources/layui/layui.all.js"></script>
<script>
//JavaScript代碼區域
layui.use('element', function(){
  var element = layui.element;
  
});

window.onload= function () { 
    loadImg();
}

layui.use('upload', function(){
	var upload = layui.upload;
    //普通圖片上傳
    upload.render({
        elem: '#test1'
        ,url: '../UserController/uploadImg'
        ,accept: 'images'
        ,acceptMime: 'image/*'
        ,size: '1024*5'
        ,before: function(obj){
            //預讀本地文件示例,不支持ie8
            obj.preview(function(index, file, result){
                $('#demo1').attr('src', result); //圖片鏈接(base64)
            });
        }
    	,done: function(res, input){
    		layer.msg('頭像上傳成功',{icon:6});
        console.log(res); //如:{"code":0 ,"msg":"","url":"http://cdn.abc.com/123.jpg"'} 
        document.getElementById("myimg").innerHTML=res.name;
        
    	}
});
});

function loadImg(){ 
    $.ajax({ 
        type:"post", 
        url:"../UserController/photo",//對應controller的URL 
        dataType: 'json', 
        success:function(msg){
        	 document.getElementById('demo1').src=msg.name;
        }
    }); 
}
</script>

(6)頁面加載動畫

加載動畫並不是真的會等待頁面數據加載完成后才隱藏,只是等待1000毫秒后隱藏。
在這里插入圖片描述
HTML代碼:
在這里插入圖片描述
JS代碼:

<script>
	window.onload = function() {
		setTimeout(function(){
			siteLoading.classList.remove('active')
		},1000);
}
</script>

CSS樣式:

.wrapper {
    height: 200px;
    width: 200px;
    border: 1px solid #fff;
    /* 將圓形動畫定位到正中 */
    position: relative;
 }
  
.wrapper::before,
.wrapper::after{
  content: '';
  height: 10px;
  width: 10px;
  background-color: black;
  border-radius: 100%;
  /* 將圓形動畫定位到正中 */
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
  margin: auto;
  animation: dada 2s linear infinite;
}
  
.wrapper::after {
  animation-delay: 1s;
}
  
@keyframes dada {
  0% {
    height: 0px;
    width: 0px;
    opacity: 1;
  }
  100% {
    height: 100px;
    width: 100px;
    opacity: 0;
  }
}

.loading {
    display: none;
    background-color: #fff;
    position: fixed;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    z-index: 999;
    justify-content: center;
    align-items: center;
 }
  
.loading.active {
  display: flex;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM