vue.js + restful + pageHelper + thymeleaf + springboot

2019-01-16 22:51:00     

本篇博客涉及到多方面的知识点,包括 Vue.js,Springboot, Restful风格, 分页 PageHelper 的使用, Thymeleaf 模板等

表结构

CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(30) DEFAULT NULL,
  `cid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6194 DEFAULT CHARSET=utf8;

pom.xml

加入springboot web支持、springboot tomcat支持、thymeleaf 模板支持、pageHelper分页支持、mybatis支持、tomcat的支持、热部署支持、mysql支持等

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>1.5.9.RELEASE</version>
</parent>

<dependencies>
	<!-- springboot web -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<!-- springboot tomcat 支持 -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-tomcat</artifactId>
	</dependency>
	<!-- thymeleaf -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-thymeleaf</artifactId>
	</dependency>
	<!-- thymeleaf legacyhtml5 模式支持 -->
	<dependency>
		<groupId>net.sourceforge.nekohtml</groupId>
		<artifactId>nekohtml</artifactId>
		<version>1.9.22</version>
	</dependency>
	<!-- 分页 -->
	<dependency>
		<groupId>com.github.pagehelper</groupId>
		<artifactId>pagehelper</artifactId>
		<version>4.1.6</version>
	</dependency>
	<!-- mybatis -->
	<dependency>
		<groupId>org.mybatis.spring.boot</groupId>
		<artifactId>mybatis-spring-boot-starter</artifactId>
		<version>1.1.1</version>
	</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>
	</dependency>
	<!-- mysql -->
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>5.1.21</version>
	</dependency>
</dependencies>

<properties>
	<java.version>1.8</java.version>
</properties>

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>

application.properties

在 src/main/resources 下新建 application.properties文件,配置数据库、mybatis、thymeleaf

#database
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/transaction?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#mybatis
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=top.bounds.pojo
 
#thymeleaf
spring.thymeleaf.mode=LEGACYHTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.cache=false

Application.java

启动类(包名:top.bounds)

package top.bounds;

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);
	}
}

PageHelperConfig.java

分页配置类(包名:top.bounds.config)

package top.bounds.config;

import java.util.Properties;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.github.pagehelper.PageHelper;

@Configuration
public class PageHelperConfig {

	@Bean
	public PageHelper pageHelper() {
		PageHelper pageHelper = new PageHelper();
		Properties p = new Properties();
		p.setProperty("offsetAsPageNum", "true");
		p.setProperty("rowBoundsWithCount", "true");
		p.setProperty("reasonable", "true");
		pageHelper.setProperties(p);
		return pageHelper;
	}
}

GlobalExceptionHandler.java

异常处理类(包名:top.bounds.config)

package top.bounds.exception;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

@ControllerAdvice
public class GlobalExceptionHandler {
	@ExceptionHandler(value = Exception.class)
	public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
		ModelAndView mav = new ModelAndView();
		mav.addObject("exception", e);
		mav.addObject("url", req.getRequestURL());

		mav.setViewName("errorPage");
		return mav;
	}

}

Student.java

实体类,对应表结构(包名:top.bounds.pojo)

package top.bounds.pojo;

public class Student {
	private int id;
	private String name;
	private int cid;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getCid() {
		return cid;
	}

	public void setCid(int cid) {
		this.cid = cid;
	}

}

StudentMapper.java

主要负责与数据库进行交互设计,用来处理数据的持久化工作(包名:top.bounds.mapper)

package top.bounds.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import top.bounds.pojo.Student;

@Mapper
public interface StudentMapper {

	public List<Student> findAll();

	public Student findById(int id);

	public int delete(int id);

	public int update(Student s);

	public int insert(Student s);
}

student.xml

这个文件就放在 src/main/resources/mapper 目录下,编写sql语句用的

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- 表示命名空间是config,在后续调用sql语句的时候,会用到它 -->
<mapper namespace="top.bounds.mapper.StudentMapper">
	<!-- 查询所有 -->
	<select id="findAll" resultType="Student">
		select * from student
	</select>
	<!-- 根据id查找 -->
	<select id="findById" resultType="Student" parameterType="_int">
		select
		* from student where id = #{id}
	</select>
	<!-- 修改一条记录 -->
	<update id="update" parameterType="Student">
		update student set
		name=#{name},cid=#{cid} where id=#{id}
	</update>
	<!-- 删除一条记录 -->
	<delete id="delete" parameterType="_int">
		delete from student
		where id=#{id}
	</delete>
	<!-- 插入一条记录 -->
	<insert id="insert" parameterType="Student">
		insert into
		student(name,cid)
		values(#{name},#{cid})
	</insert>
</mapper>

StudentService.java

与mapper层交互并把数据返回给controller层(包名:top.bounds.service)

package top.bounds.service;

import java.util.List;

import top.bounds.pojo.Student;

public interface StudentService {
	public List<Student> findAll();

	public Student findById(int id);

	public int delete(int id);

	public int update(Student s);

	public int insert(Student s);
}

StudentServiceImpl.java

StudentService的实现类(包名:top.bounds.service.impl)

package top.bounds.service.impl;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import top.bounds.mapper.StudentMapper;
import top.bounds.pojo.Student;
import top.bounds.service.StudentService;

@Service
public class StudentServiceImpl implements StudentService {

	@Resource
	StudentMapper studentMapper;

	@Override
	public List<Student> findAll() {
		return studentMapper.findAll();
	}

	@Override
	public Student findById(int id) {
		return studentMapper.findById(id);
	}

	@Override
	public int delete(int id) {
		return studentMapper.delete(id);
	}

	@Override
	public int update(Student s) {
		return studentMapper.update(s);
	}

	@Override
	public int insert(Student s) {
		return studentMapper.insert(s);
	}

}

StudentController.java

首先 StudentController 分为两部分:1. restful 部分 2. 页面跳转部分。restful 就提供 CRUD 等等操作,页面跳转主要用来跳转到 thymeleaf 对应的 html 文件(包名:top.bounds.controller)

package top.bounds.controller;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import top.bounds.pojo.Student;
import top.bounds.service.StudentService;

@RestController
public class StudentController {

	@Resource
	StudentService studentService;

	/* restful 部分 */
	@GetMapping("/student")
	public PageInfo<Student> findAll(@RequestParam(value = "start", defaultValue = "1") int start,
			@RequestParam(value = "size", defaultValue = "5") int size) throws Exception {
		PageHelper.startPage(start, size, "id desc");
		List<Student> hs = studentService.findAll();
		PageInfo<Student> page = new PageInfo<>(hs, 5); // 5表示导航分页最多有5个,像
		return page;
	}

	@GetMapping("/student/{id}")
	public Student findById(@PathVariable("id") int id) {
		Student s = studentService.findById(id);
		return s;
	}

	@PostMapping("/student")
	public String insert(@RequestBody Student s) {
		studentService.insert(s);
		return "success";
	}

	@DeleteMapping("/student/{id}")
	public String delete(@PathVariable("id") int id) {
		studentService.delete(id);
		return "success";
	}

	@PutMapping("/student")
	public String update(@RequestBody Student s) {
		studentService.update(s);
		return "success";
	}

	/* 页面跳转部分 */
	@RequestMapping(value = "/listStudent", method = RequestMethod.GET)
	public ModelAndView listStudent() {
		ModelAndView mv = new ModelAndView("listStudent");
		return mv;
	}

	@RequestMapping(value = "/editStudent", method = RequestMethod.GET)
	public ModelAndView editStudent() {
		ModelAndView mv = new ModelAndView("editStudent");
		return mv;
	}
}

js文件

在 src/main/resources下新建 static目录,里面放上3个要用到的 第三方 js 库: axios.min.js, jquery.min.js, vue.min.js

listStudent.html

数据展示页面

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<script src="../static/jquery.min.js" th:src="@{/jquery.min.js}"></script>
		<script src="../static/vue.min.js" th:src="@{/vue.min.js}"></script>
		<script src="../static/axios.min.js" th:src="@{/axios.min.js}"></script>
		<style type="text/css">
			td {
				border: 1px solid gray;
			}
			table {
				border-collapse: collapse;
			}
			div#app {
				margin: 20px auto;
				width: 400px;
				padding: 20px;
			}
			div#pagination {
				text-align: center;
				line-height: 100px;
			}
			div#pagination a {
				text-decoration: none;
			}
			.disableHref {
				cursor: default;
				color: #E5E0E0;
				text-decoration: none;
			}
		</style>
		<script>
			$(function(){
	    	$("a.disableHref").click(function(event){
	    		return false;
	    	});
	    });
    </script>
	</head>
	<body>
		<div id="app">
			<table id="heroListTable">
				<tr>
					<td colspan="3">
						<div id="pagination">
							<a :class="{ disableHref: pagination.pageNum==1 }" href="#nowhere" @click="jump('first')">[first]</a> <a :class="{ disableHref: !pagination.hasPreviousPage }"
							 href="#nowhere" @click="jump('pre')">[pre]</a> <a href="#nowhere" :class="{disableHref:pagination.pageNum==i}"
							 v-for="i in pagination.navigatepageNums" @click="jumpByNumber(i)">
								{{i}} </a> <a :class="{ disableHref: !pagination.hasNextPage }" href="#nowhere" @click="jump('next')">[next]</a>
							<a :class="{ disableHref: pagination.pageNum==pagination.pages }" href="#nowhere" @click="jump('last')">[last]</a>
						</div>
					</td>
				</tr>
				<tr>
					<td>英雄名称</td>
					<td>血量</td>
					<td>操作</td>
				</tr>
				<tr v-for="student in heros ">
					<td>{{student.name}}</td>
					<td>{{student.cid}}</td>
					<td><a :href="'editStudent?id=' + student.id ">编辑</a> <a href="#nowhere" @click="deleteHero(student.id)">删除</a></td>
				</tr>
				<tr>
					<td colspan="3"><br> 英雄名称: <input type="text" v-model="hero4Add.name" /> <br> 血量: <input type="number" v-model="hero4Add.cid" />
						<br> <br>
						<button type="button" v-on:click="add">增加</button> <br></td>
				</tr>
			</table>
		</div>
		<script type="text/javascript">
			var data4Vue = {
				heros: [],
				hero4Add: {
					id: 0,
					name: '',
					cid: 0
				},
				pagination: {}
			};
			//ViewModel
			var vue = new Vue({
				el: '#app',
				data: data4Vue,
				mounted: function() { //mounted 表示这个 Vue 对象加载成功了
					this.list(1);
				},
				methods: {
					list: function(start) {
						var url = "student?start=" + start;
						axios.get(url).then(function(response) {
							vue.pagination = response.data;
							console.log(vue.pagination);
							vue.heros = response.data.list;
						})
					},
					add: function(event) {
						var url = "student";

						axios.post(url, this.hero4Add).then(function(response) {
							vue.list(1);
							vue.hero4Add = {
								id: 0,
								name: '',
								cid: 0
							}
						});
					},
					deleteHero: function(id) {
						var url = "student/" + id;
						axios.delete(url).then(function(response) {
							vue.list(1);
						});
					},
					jump: function(page) {
						if ('first' == page && 1 != vue.pagination.pageNum)
							vue.list(1);

						else if ('pre' == page && vue.pagination.hasPreviousPage)
							vue.list(vue.pagination.prePage);

						else if ('next' == page && vue.pagination.hasNextPage)
							vue.list(vue.pagination.nextPage);

						else if ('last' == page && vue.pagination.pageNum != vue.pagination.pages)
							vue.list(vue.pagination.pages);

					},
					jumpByNumber: function(start) {
						if (start != vue.pagination.pageNum)
							vue.list(start);
					}
				}
			});
		</script>
	</body>
</html>

editStudent.html

修改页面

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<script src="../static/jquery.min.js" th:src="@{/jquery.min.js}"></script>
		<script src="../static/vue.min.js" th:src="@{/vue.min.js}"></script>
		<script src="../static/axios.min.js" th:src="@{/axios.min.js}"></script>
		<style type="text/css">
			div#app {
				margin: 20px auto;
				width: 400px;
				padding: 20px;
			}
		</style>
	</head>

	<body>
		<div id="app">
			<div id="div4Update">

				英雄名称: <input type="text" v-model="hero4Update.name" /> <br> 血量:
				<input type="number" v-model="hero4Update.cid" /> <input type="hidden" v-model="hero4Update.id" /> <br>
				<button type="button" v-on:click="update">修改</button>
				<button type="button" v-on:click="cancel">取消</button>

			</div>
		</div>

		<script type="text/javascript">
			//获取地址栏参数的函数
			function getUrlParms(name) {
				var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
				var r = window.location.search.substr(1).match(reg);
				if (r != null)
					return unescape(r[2]);
				return null;
			}

			var data4Vue = {
				heros: [],
				hero4Update: {
					id: 0,
					name: '',
					cid: 0
				}
			};

			//ViewModel
			var vue = new Vue({
				el: '#app',
				data: data4Vue,
				mounted: function() { //mounted 表示这个 Vue 对象加载成功了
					this.get();
				},
				methods: {
					get: function() {
						var id = getUrlParms("id");
						var url = "student/" + id;
						console.log(url);
						axios.get(url).then(function(response) {
							vue.hero4Update = response.data;
						})
					},
					update: function(event) {
						var url = "student";
						axios.put(url, vue.hero4Update).then(function(response) {
							location.href = "listStudent";
						});
					},
					cancel: function() {
						location.href = "listStudent";
					}
				}
			});
		</script>
	</body>
</html>

errorPage.html

异常页面

<html xmlns:th="http://www.thymeleaf.org">
	<body>
		<div style="width:500px;border:1px solid lightgray;margin:200px auto;padding:80px">
			系统 出现了异常,异常原因是:
			<div th:text="${exception}"></div>
			出现异常的地址是:
			<div th:text="${url}"></div>
		</div>
	</body>
</html>

启动测试

启动项目,然后访问测试地址: http://127.0.0.1:8080/listStudent

ps:本篇博客源码下载链接:https://pan.baidu.com/s/1WEGTKfYy0uYlhT9y1bxihQ 密码:izjw
Thymeleaf 基本用法总结

Thymeleaf是用于Web和独立环境的现代服务器端Java模板引擎。 Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。

Java数据结构和算法(二)——数组

本篇博客我们介绍数据结构的鼻祖——数组,可以说数组几乎能表示一切的数据结构,在每一门编程语言中,数组都是重要的数据结构,当然每种语言对数组的实现和处理也不相同,但是本质是都是用来存放数据的的结构,这里我们以Java语言为例,来详细介绍Java语言中数组的用法。

 发表评论