##序
本系列的写作风格是第一人称,目的是为了让教程看起来更有意思一点,叶小凡是我某本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
看到了登录页面:
本章源码已经上传群文件,有需要的小伙伴直接去下载哦。