序
本系列的寫作風格是第一人稱,目的是為了讓教程看起來更有意思一點,葉小凡是我某本JS書籍的主人公名字。以下經歷純屬虛構,如有雷同,純屬巧合!
01 兔哥,收我為徒吧
我叫葉小凡,即將畢業,正愁找工作。之前在網上關注了一位博主,網名叫剽悍一小兔,感覺文章寫的還可以,后來關注了他的公眾號,學會了基本的環境配置。可是,也就僅此而已了,我只會HelloWorld。
這一天,我微信上問他,你為啥叫剽悍一小兔啊?
“沒多想,我挺喜歡兔子的,應該很好吃,腦袋一熱,就取了這個名字!”
“兔哥,我剛畢業,想學Java,能不能收我為徒啊?”
“是么,你可要想好,跟我修行可是很辛苦的!”
“我已經想好了,我雖然只會HelloWorld,但是我願意學。”
“這樣,你先用SpringBoot幫我做一個系統出來,我打算做一個教育網站,正好要用,你什么時候給我做出來,我就什么時候收你為徒!”
我一聽就驚呆了,連忙說道:“可是我只會HelloWorld啊......”
“沒事,我可以指導你怎么寫,放心,只會HelloWorld也沒有關系,你一定可以的!”
“我明白了,兔哥,你是打算把修行的內容平攤到每一天中,讓我在做網站的時候,就學到了編程的技術,對嗎?”
“不是,我只是單純地不想自己寫而已!”
“。。。。。。額,最后一個問題,為什么你每說完一句話,都要加個感嘆號啊?”
“!”
02 先建表吧
根據兔哥的說法,他要做一個能發布教程的系統,教程,不就是文章嘛。emmm....
我先建一個文章表肯定沒錯的,SpringBoot啥的待會再說吧。
兔哥:“你先別着急建文章表,要不你先把我關於springboot的入門教程看了,其實你用spring data jpa的話,可以直接寫JavaBean,順便把表建了,很方便。”
路徑:打開公眾號
點擊經典博客,在這里:
“我靠,你從哪冒出來的,嚇死寶寶了!”我吃了一驚,然后就去看了一下教程,感覺其實也挺簡單的嘛。
03 搭建SpringBoot項目
ok,說干就干,先把系統給建起來。兔哥的文章里面講的是在線生成springboot項目,我偏不,我就自己建。
當然,我已經通過看這里的文章,把環境都搭建好了,maven也配置好了。
接下來就是擼起袖子加油干,打開eclipse,創建一個maven項目。
點擊Finish完成。
現在,修改一下pom文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tuzi</groupId>
<artifactId>edu</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>兔子編程</name>
<description>某個很水的在線教育平台</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- servlet依賴. -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- tomcat的支持.-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 這個需要為 true 熱部署才有效 -->
</dependency>
<!-- ORM 框架采用JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>
<!-- springboot test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.4.2.RELEASE</version>
</plugin>
</plugins>
<resources>
<resource>
<directory>${basedir}/src/main/webapp</directory>
<targetPath>META-INF/resources</targetPath>
<includes>
<include>**/**</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>**/**</include>
</includes>
</resource>
</resources>
</build>
</project>
基本的配置都有了,保存了以后maven會去自動下載對應的jar包的,不用我操心啦。
然后,這邊建一個簡單的目錄結構:
配置文件就用yml吧,兔哥的教程里面也是yml的,然后這邊我加了點mvc的配置,因為視圖層我只會jsp:
server:
port: 8080
context-path: /edu
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/edu?characterEncoding=UTF-8
username: root
password:
jpa:
database: mysql
hibernate:
ddl-auto: update
show-sql: true
resources:
static-locations: classpath:static/
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
先寫一個User類:
package com.edu.entity;
import javax.persistence.*;
@Entity
public class User {
@Id
@Column(length = 20)
private String userName;
@Column(length = 20)
private String password;
@Column(length = 30)
private String nickName;
@Column(length = 80)
private String headerPic;
@Column(length = 1)
private String isVip;
@Column(length = 1)
private String isLogined;
@Column(length = 2)
private String roleId;
@Column(length = 1)
private String isDelete;
@Column(length = 8)
private String createTime;
@Column(length = 8)
private String lastLoginTime;
@Column(length = 64)
private String ipAddr;
//無參構造方法,這個必須要有,不然會報錯
public User() {
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getHeaderPic() {
return headerPic;
}
public void setHeaderPic(String headerPic) {
this.headerPic = headerPic;
}
public String getIsVip() {
return isVip;
}
public void setIsVip(String isVip) {
this.isVip = isVip;
}
public String getRoleId() {
return roleId;
}
public void setRoleId(String roleId) {
this.roleId = roleId;
}
public String getIsDelete() {
return isDelete;
}
public void setIsDelete(String isDelete) {
this.isDelete = isDelete;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getIsLogined() {
return isLogined;
}
public void setIsLogined(String isLogined) {
this.isLogined = isLogined;
}
public String getLastLoginTime() {
return lastLoginTime;
}
public void setLastLoginTime(String lastLoginTime) {
this.lastLoginTime = lastLoginTime;
}
public String getIpAddr() {
return ipAddr;
}
public void setIpAddr(String ipAddr) {
this.ipAddr = ipAddr;
}
}
這個User類主要是用來做用戶的登錄的,嗯,反正他自己一個人用,我就做登錄功能,不注冊了。
然后,用mysql-front工具去新建一個叫做edu的數據庫。
這是啟動類:
package com.edu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
接下來就是見證奇跡的時刻,運行啟動類:
沒報錯欸!看下數據庫:
來了來了,真的來了,好高興哦,又吃成長快樂了!
03 訪問登錄頁面吧
既然是個系統,肯定得有一個登錄頁面撒,可是我html和css寫的很一般,美工又不會做,就只能網上找一找現成的登錄模板,才可以維持得了生活,這樣子。
兔哥:“別去亂搜了,我們得加快進度啊,我已經給你找好了,直接用這一套吧!”
“我靠,你能不能別總是一下子就跑出來嚇人好不啦!”我又吃了一驚。
於是,兔哥給我發了一個資料包,我根據他的要求把一系列文件放在了對應的地方。
這是公共的jsp和登錄頁面——login.jsp。
taglib.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
//獲取當前項目路徑
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;
}
pageContext.setAttribute("basePath", basePath);
%>
login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@include file="common/taglib.jsp"%>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus®">
<meta name="Author" content="">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>Document</title>
<style>
#canvas {
position: fixed;
top: 0;
z-index: -100;
opacity:0.6;
}
.box{
display: flex;
justify-content: center;
margin-top: 50px;
perspective: 500px;
transform-style: preserve-3d;
animation: fadeInUp 0.5s;
}
.font {
float: left;
width: 100px;
height: 100px;
background: #fff;
color: #16142B;
border: 1px solid #16142B;
font-family: consolas;
font-weight: bold;
font-size: 50px;
text-align: center;
line-height: 100px;
transition: 0.8s;
box-shadow: 0 5px 10px black, inset 0 5px 2px #777, inset 0 -5px 2px #333, inset 5px 0px 2px #444, inset -5px 0px 2px #444;
border-radius: 20px;
}
#mainContent {position:absolute;left:50%;margin-left:-220px;margin-top:20px;}
.box2 {position:relative;top:24px;color:#222;}
input {
display: inline-block;
width: 100%;
height: 28px;
padding: 6px 12px;
font-size: 14px;
line-height: 1.42857143;
color: #555;
background-color: #fff;
background-image: none;
border: 1px solid #ccc;
border-radius: 4px;
}
#message {color:red;}
</style>
</head>
<body>
<div class="box">
<div class="font" id="d">
小
</div>
<div class="font" id="k">
兔
</div>
<div class="font" id="p">
教
</div>
<div class="font" id="l">
育
</div>
</div>
<div id="mainContent" style="text-align:center;">
<div class="box2">
<div style="height:24px;"> <span id="message"></span> </div>
<form action="user/login" method="post">
<input type="text" class="inputs" id="account" name="account" autofocus="autofocus" placeholder="請輸入賬號" maxLength="20">
<input type="password" class="inputs" id="password" name="password" placeholder="請輸入密碼" maxLength="20">
<p class="btn"><input type="button" style="height:38px;width:106%;" id="loginbtn" hidden='true' onclick="tm_login(this)" class="submit" value="登陸"><p>
</form>
</div>
</div>
<canvas id="canvas" width="686" height="300"></canvas>
<script type="text/javascript" src="${basePath}/js/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="${basePath}/js/util.js"></script>
<script>
/**
* 獲取canvas對象,設置寬度高度自適應
* @type {[type]}
*/
var canvas = document.querySelector("#canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.globalAlpha = .1;
canvas.fillStyle = 'rgba(255, 255, 255, 0)';
var ctx = canvas.getContext("2d");
/**
* 屏幕鼠標坐標
* @type {Object}
*/
var mouse = {
x: undefined,
y: undefined
}
/**
* @param {鼠標移動事件,回調函數,賦值給鼠標坐標}
* @return {[type]}
*/
window.addEventListener("mousemove",function (event) {
mouse.x = event.x;
mouse.y = event.y;
// console.log(mouse);
});
/**
* @param {重新設置窗口大小,使canvas寬高自適應屏幕}
* @return {[type]}
*/
window.addEventListener("resize",function () {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
//初始化canvas
init();
})
//繪制圓的最大半徑
var maxRadius = 10;
// var minRadius = 2;
//圓的顏色數組
var colorArray = [
'#58D68D',
'#E67F22',
'#3598DB',
'#E84C3D',
'#9A59B5',
'#27AE61',
'#D25400',
'#BEC3C7',
'#297FB8'
]
/**
* @param {x圓中心的x坐標}
* @param {y圓中心的y坐標}
* @param {dx圓運動的x偏移量}
* @param {dy圓運動的y偏移量}
* @param {radius圓的半徑}
* minRadius圓的最小半徑
* bg圓的背景顏色
* draw繪制函數
* update圓運動偏移
*/
function Circle(x, y, dx, dy, radius) {
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
this.radius = radius;
this.minRadius = radius;
this.bg = colorArray[Math.floor(Math.random()*colorArray.length)];
this.draw = function() {
ctx.beginPath();
ctx.strokeStyle = "#777";
ctx.fillStyle = this.bg;
ctx.arc(this.x,this.y,this.radius,Math.PI/180*0,Math.PI/180*360,false);
// ctx.stroke();
ctx.fill();
}
this.update = function() {
//圓觸碰邊界時反彈,偏移值為負
if (this.x + this.radius > innerWidth || this.x - this.radius < 0 ) {
this.dx = -this.dx;
}
if (this.y + this.radius > innerHeight || this.y - this.radius < 0 ) {
this.dy = -this.dy;
}
//刷新繪制時圓的偏移運動
this.x += this.dx;
this.y += this.dy;
//鼠標半徑50像素范圍內的圓,它們的半徑逐步增加到最大值
if (mouse.x - this.x < 50 && mouse.x - this.x >-50 && mouse.y - this.y < 50 && mouse.y - this.y >-50) {
if (this.radius < maxRadius) {
this.radius += 1;
}
//其他的所有圓半徑減小到最小值
}else if (this.radius > this.minRadius) {
this.radius -= 1;
}
//根據更新的值進行繪制
this.draw();
}
}
//圓的對象數組
var circleArray = [];
/**
* 初始化函數,制造800個隨機坐標、偏移速度和半徑的圓,加入到對象數組
* @return {[type]}
*/
function init() {
circleArray = []
for (var i = 0; i < 800; i++) {
var x = Math.random()*window.innerWidth;
var y = Math.random()*window.innerHeight;
var dx = (Math.random()-0.5)*2;
var dy = (Math.random()-0.5)*2;
var radius = Math.random()*3 +1;
circleArray.push(new Circle(x, y, dx, dy, radius));
}
}
init();
/**
* 動畫函數
* @return {[type]}
*/
function animate() {
//更新前清楚畫布
ctx.clearRect(0,0,window.innerWidth,window.innerHeight);
requestAnimationFrame(animate);
//每個圓都調用update()方法
for (var i = 0; i < circleArray.length; i++) {
circleArray[i].update();
}
}
animate();
$(function(){
//敲入鍵盤的enter建進行提交登陸
$(document).keydown(function(e){
if(e.keyCode == 13){
//觸發登陸按鈕的事件
$("#loginbtn").trigger("click");
}
});
});
//已定義減少和服務器端的交互---靜態化
function tm_login(obj){
var account = $("#account").val();
var password = $("#password").val();
if(isEmpty(account)){
$("#account").focus();
tm_showmessage("請輸入賬號");
return;
}
if(isEmpty(password)){
$("#password").focus();
tm_showmessage("請輸入密碼");
return;
}
//$(obj).parent().css("paddingLeft",387);
$(obj).attr("value","登陸中...").removeAttr("onclick");
$.ajax({
type:"post",
url:"User/login.do",
error:function(){$(obj).attr("value","登陸").attr("onclick","tm_login(this)");},
data:{"account":account,"password":password},
success:function(data){
data = eval("("+data+")");
if(data.code == 0){
window.location.href = "view.do?path=index";
}else{
$("#account").select();
$("#password").val("");
$(obj).attr("value","登陸").attr("onclick","tm_login(this)");
tm_showmessage(data.msg);
}
}
});
}
//顯示錯誤信息
function tm_showmessage(message){
$("#message").show().html(message).stop(true,true).fadeOut(3000);
}
//找到文本框,並注冊得到焦點事件
/* $("input").focus(function(){
//讓當前得到焦點的文本框改變其背景色
$(this).css("background","skyblue").css("color","#fff");
});
//找到文本框,並注冊失去焦點事件
$("input").blur(function(){
//讓當前失去焦點的文本框背景色變為白色
$(this).css("background","white").css("color","#000");
}); */
</script>
</body>
</html>
兔哥說是網上隨便找的,看起來挺牛掰的,咱也不敢問,等以后學到前端知識的時候再說吧。
然后是static這里放靜態資源:
因為在application.yml里面已經配置靜態資源了,所以這樣就能直接訪問static文件夾里面的東西了。
resources:
static-locations: classpath:static/
接下來是java的部分
ViewController就是視圖訪問控制器,看下代碼:
package com.edu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ViewController {
@RequestMapping("/view/{page}")
public String view(@PathVariable(name = "page") String page) {
return page;
}
}
意思就是頁面訪問這個映射地址,直接返回 WEB-INF/jsp里面對應的文件。
啟動項目,然后我們訪問
http://localhost:8080/edu/view/login
看到了登錄頁面:
本章源碼已經上傳群文件,有需要的小伙伴直接去下載哦。