1. 程式人生 > 實用技巧 >我只會HelloWorld,但是我卻完成了一個SpringBoot專案!(1)

我只會HelloWorld,但是我卻完成了一個SpringBoot專案!(1)

本系列的寫作風格是第一人稱,目的是為了讓教程看起來更有意思一點,葉小凡是我某本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">&nbsp;&nbsp;&nbsp;&nbsp;
				<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

看到了登入頁面:

本章原始碼已經上傳群檔案,有需要的小夥伴直接去下載哦。