推荐文章:
springboot整合redis并在项目中使用
vue+springboot 登录注册功能
目录
- 一、创建数据库
- 二、后端环境搭建
- 三、实现验证码功能
- CreateImageCode .java
- 新建UserController.java
- 编写接口:/user/getImage
- 效果:
- 四、开发
- 1、创建前端项目
- 2、注册登录前端开发
- 3、注册登录后端开发
- 4、省份增删改查及分页后端开发
- 5、省份增删改查及分页前端开发
- 6、效果
一、创建数据库
数据库名:travels
用户表 SQL:
CREATE TABLE t_user(id INT(6) PRIMARY KEY AUTO_INCREMENT,username VARCHAR(60),password VARCHAR(60),email VARCHAR(60)
);
省份表 SQL:
CREATE TABLE t_province(id INT(6) PRIMARY KEY AUTO_INCREMENT,name VARCHAR(60),tags VARCHAR(80),placecounts INT(4)
);
景点表 SQL:
CREATE TABLE t_place(id INT(6) PRIMARY KEY AUTO_INCREMENT,name VARCHAR(60),picpath MEDIUMTEXT,hottime TIMESTAMP,hotticket DOUBLE(7,2),dimticket DOUBLE(7,2),placedes VARCHAR(300),provinceid INT(6) REFERENCES t_province(id)
);
二、后端环境搭建
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.6.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.travel</groupId><artifactId>travels</artifactId><version>0.0.1-SNAPSHOT</version><name>travels</name><description>travels</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.3</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.19</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
server.port=8081
spring.application.name=travelsspring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/travels?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.datasource.name=root
spring.datasource.password=123456mybatis.mapper-locations=classpath:com/travel/mapper/*.xml
mybatis.type-aliases-package=com.travel.travels.entity
三、实现验证码功能
CreateImageCode .java
package com.travel.travels.utils;import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;public class CreateImageCode {// 图片的宽度。private int width = 160;// 图片的高度。private int height = 40;// 验证码字符个数private int codeCount = 4;// 验证码干扰线数private int lineCount = 20;// 验证码private String code = null;// 验证码图片Bufferprivate BufferedImage buffImg = null;Random random = new Random();public CreateImageCode() {creatImage();}public CreateImageCode(int width, int height) {this.width = width;this.height = height;creatImage();}public CreateImageCode(int width, int height, int codeCount) {this.width = width;this.height = height;this.codeCount = codeCount;creatImage();}public CreateImageCode(int width, int height, int codeCount, int lineCount) {this.width = width;this.height = height;this.codeCount = codeCount;this.lineCount = lineCount;creatImage();}// 生成图片private void creatImage() {int fontWidth = width / codeCount;// 字体的宽度int fontHeight = height - 5;// 字体的高度int codeY = height - 8;// 图像bufferbuffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics g = buffImg.getGraphics();//Graphics2D g = buffImg.createGraphics();// 设置背景色g.setColor(getRandColor(200, 250));g.fillRect(0, 0, width, height);// 设置字体//Font font1 = getFont(fontHeight);Font font = new Font("Fixedsys", Font.BOLD, fontHeight);g.setFont(font);// 设置干扰线for (int i = 0; i < lineCount; i++) {int xs = random.nextInt(width);int ys = random.nextInt(height);int xe = xs + random.nextInt(width);int ye = ys + random.nextInt(height);g.setColor(getRandColor(1, 255));g.drawLine(xs, ys, xe, ye);}// 添加噪点float yawpRate = 0.01f;// 噪声率int area = (int) (yawpRate * width * height);for (int i = 0; i < area; i++) {int x = random.nextInt(width);int y = random.nextInt(height);buffImg.setRGB(x, y, random.nextInt(255));}String str1 = randomStr(codeCount);// 得到随机字符this.code = str1;for (int i = 0; i < codeCount; i++) {String strRand = str1.substring(i, i + 1);g.setColor(getRandColor(1, 255));// g.drawString(a,x,y);// a为要画出来的东西,x和y表示要画的东西最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处g.drawString(strRand, i*fontWidth+3, codeY);}}// 得到随机字符private String randomStr(int n) {String str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";String str2 = "";int len = str1.length() - 1;double r;for (int i = 0; i < n; i++) {r = (Math.random()) * len;str2 = str2 + str1.charAt((int) r);}return str2;}// 得到随机颜色private Color getRandColor(int fc, int bc) {// 给定范围获得随机颜色if (fc > 255)fc = 255;if (bc > 255)bc = 255;int r = fc + random.nextInt(bc - fc);int g = fc + random.nextInt(bc - fc);int b = fc + random.nextInt(bc - fc);return new Color(r, g, b);}/*** 产生随机字体*/private Font getFont(int size) {Random random = new Random();Font font[] = new Font[5];font[0] = new Font("Ravie", Font.PLAIN, size);font[1] = new Font("Antique Olive Compact", Font.PLAIN, size);font[2] = new Font("Fixedsys", Font.PLAIN, size);font[3] = new Font("Wide Latin", Font.PLAIN, size);font[4] = new Font("Gill Sans Ultra Bold", Font.PLAIN, size);return font[random.nextInt(5)];}// 扭曲方法private void shear(Graphics g, int w1, int h1, Color color) {shearX(g, w1, h1, color);shearY(g, w1, h1, color);}private void shearX(Graphics g, int w1, int h1, Color color) {int period = random.nextInt(2);boolean borderGap = true;int frames = 1;int phase = random.nextInt(2);for (int i = 0; i < h1; i++) {double d = (double) (period >> 1)* Math.sin((double) i / (double) period+ (6.2831853071795862D * (double) phase)/ (double) frames);g.copyArea(0, i, w1, 1, (int) d, 0);if (borderGap) {g.setColor(color);g.drawLine((int) d, i, 0, i);g.drawLine((int) d + w1, i, w1, i);}}}private void shearY(Graphics g, int w1, int h1, Color color) {int period = random.nextInt(40) + 10; // 50;boolean borderGap = true;int frames = 20;int phase = 7;for (int i = 0; i < w1; i++) {double d = (double) (period >> 1)* Math.sin((double) i / (double) period+ (6.2831853071795862D * (double) phase)/ (double) frames);g.copyArea(i, 0, 1, h1, 0, (int) d);if (borderGap) {g.setColor(color);g.drawLine(i, (int) d, i, 0);g.drawLine(i, (int) d + h1, i, h1);}}}public void write(OutputStream sos) throws IOException {ImageIO.write(buffImg, "png", sos);sos.close();}public BufferedImage getBuffImg() {return buffImg;}public String getCode() {return code.toLowerCase();}//使用方法
// public void getCode3(HttpServletRequest req, HttpServletResponse response, HttpSession session) throws IOException{
// // 设置响应的类型格式为图片格式
// response.setContentType("image/jpeg");
// //禁止图像缓存。
// response.setHeader("Pragma", "no-cache");
// response.setHeader("Cache-Control", "no-cache");
// response.setDateHeader("Expires", 0);
// CreateImageCode vCode = new CreateImageCode(100,30,5,10);
// session.setAttribute("code", vCode.getCode());
// vCode.write(response.getOutputStream());
// }}
新建UserController.java
编写接口:/user/getImage
@RestController
@RequestMapping("/user")
@CrossOrigin // 允许跨域(前后端分离)
@Slf4j // 日志对象
public class UserController {/*** 生成验证码* @throws IOException*/@GetMapping("/getImage")public Map<String, String> getImage(HttpServletRequest request) throws IOException {Map<String, String> result = new HashMap<>();CreateImageCode createImageCode = new CreateImageCode();// 获取验证码String securityCode = createImageCode.getCode();// 验证码存入sessionString key = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());request.getServletContext().setAttribute(key, securityCode);// 生成图片BufferedImage image = createImageCode.getBuffImg();//进行base64编码ByteArrayOutputStream bos = new ByteArrayOutputStream();ImageIO.write(image, "png", bos);String string = Base64Utils.encodeToString(bos.toByteArray());result.put("key", key);result.put("image", string);return result;}
}
效果:
前端展示:
Base64:
四、开发
1、创建前端项目
参考这里的第一点:https://blog.csdn.net/m0_45234510/article/details/106414466
2、注册登录前端开发
- 先安装一下axios:
npm install axios --save
- 然后在main.js加入:
import axios from 'axios';Vue.prototype.axios = axios;
axios.defaults.baseURL = "/api"
axios.defaults.withCredentials = true
Vue.use(axios);
- 在config/index.js中的proxyTable加入下面的api解决跨域问题
proxyTable: {'/api': {target:'http://localhost:8081', // 你请求的第三方接口changeOrigin:true, // 在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题pathRewrite:{ // 路径重写,'^/api': '' // 替换target中的请求地址,也就是说以后你在请求 http://47.115.12.243 这个地址的时候直接写成/api即可。}},},
- 在router/index.js配置路由
- Register.vue
<template><div><div id="wrap"><div id="header"><div style="float: right;padding-top: 24px"><span v-text="time"/>   </div><h1>旅游信息管理系统</h1></div><div id="header-bar"></div><div id="content" style="height: 360px"><img src="img/timg.jpg" style="float: right;height: 320px"><h2>注册</h2><form action="province/provincelist.html" method="post"><label><div class="label-text">账 号:</div><input type="text" v-model="user.username" name="username"></label><label><div class="label-text">密 码:</div><input type="password" v-model="user.password" name="password"></label><label><div class="label-text">邮 箱:</div><input type="text" v-model="user.email" name="email"></label><!--前后端分离的架构, 动态访问验证码--><img :src="src" id="img-vcode" @click="getImage" :key="key"><label><div class="label-text">验证码:</div><input type="text" v-model="code" name="vcode" style="width: 100px"></label><button type="button" @click="saveUserInfo()">提 交</button> <a href="login.html">去登录</a></form></div><div id="footer">yusael~</div></div></div>
</template><script>export default {name: "Register",data() {return {user: {},code: "",src: "",key: "",time: "",}},methods: {saveUserInfo() {if (!this.user.username) {alert('用户名不能为空!');return;}if (!this.user.password) {alert('密码不能为空!');return;}if (!this.user.email) {alert('邮箱不能为空!');return;}// 发送axiosthis.axios.post("/user/register?code=" + this.code + "&key=" + this.key, this.user).then((res) => {console.log(res);alert("22")if (res.data.state) {alert(res.data.msg + ",点击确定跳转到登录页面!!!");// location.href = './login.html';} else {alert(res.data.msg);}});},getImage() {const _this = this;this.axios.get("/user/getImage").then((res) => {console.log(res);_this.src = "data:image/png;base64," + res.data.image;_this.key = res.data.key;})},},created() {this.getImage(); // 获取验证码let now = new Date();this.time = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`;}}
</script><style scoped>form {width: 270px;}input {width: 70%;background: #eee;}input:focus {background: #fff;}form {padding: 0 12px 12px;}label {display: block;padding-bottom: 12px;}#img-vcode {width: 56px;height: 21px;float: right;position: relative;top: 2px;left: -6px}.label-text {width: 30%;float: left;}
</style>
- Login.vue
<template><div><div id="wrap"><div id="header"><div style="float: right;padding-top: 24px"><span v-text="time"/> </div><h1>旅游信息管理系统</h1></div><div id="header-bar"></div><div id="content" style="height: 360px"><img src="img/timg.jpg" style="float: right;height: 320px"><h2>登录</h2><form action="province/provincelist.html" method="post"><label><div class="label-text">账 号:</div><input type="text" v-model="user.username" name="username"></label><label><div class="label-text">密 码:</div><input type="password" v-model="user.password" name="password"></label><!--前后端分离的架构, 动态访问验证码--><img :src="src" :key="key" @click="getImage" id="img-vcode" style="width: 80px;"><label><div class="label-text">验证码:</div><input type="text" v-model="code" name="vcode" style="width: 100px"></label><button type="button" @click="login">提 交</button> <!-- <a href="/register">去注册</a> --><button type="button" @click="toregister">去注册</button></form></div><div id="footer">yusael~</div></div></div>
</template><script>export default {name: "Login",data() {return {user: {},code: "",time: "",src: "",key: "",}},methods: {login() { // 登录if (!this.user.username) {alert('用户名不能为空!');return;}if (!this.user.password) {alert('密码不能为空!');return;}this.axios.post('/user/login?code=' + this.code + "&key=" + this.key, this.user).then((res) => {console.log(res.data);localStorage.setItem("userid", res.data.userId);if (res.data.state) {alert(res.data.msg + "点击确定进入主页!");location.href = './province/provincelist.html';} else {alert(res.data.msg);}});},getImage() {const _this = this;this.axios.get("/user/getImage").then((res) => {console.log(res.data);_this.src = "data:image/png;base64," + res.data.image;_this.key = res.data.key;})},toregister(){this.$router.push("/register")}},created() {this.getImage(); // 获取验证码let now = new Date();this.time = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`;},}
</script><style scoped></style>
3、注册登录后端开发
- 目录结构
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.6.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.travel</groupId><artifactId>travels</artifactId><version>0.0.1-SNAPSHOT</version><name>travels</name><description>travels</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.3</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.19</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency><!--redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
- User.java
package com.travel.travels.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {private String id;private String username;private String password;private String email;
}
- Result.java (将状态封装起来)
package com.travel.travels.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true) // 链式调用
public class Result {private Boolean state = true;private String msg;private String userId;
}
- UserDao.java
package com.travel.travels.dao;import com.travel.travels.entity.User;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface UserDao {// 注册用户void save(User user);// 根据用户名查询用户User findByUsername(String username);
}
- UserMapper.xml
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.travel.travels.dao.UserDao"><!--注册用户--><insert id="save" parameterType="User" useGeneratedKeys="true" keyProperty="id"> /*id自动生成, 生成之后放到id属性*/INSERT INTO t_userVALUES (#{id}, #{username}, #{password}, #{email})</insert><!--根据用户名查询用户|用户登录--><select id="findByUsername" parameterType="String" resultType="com.travel.travels.entity.User">SELECT * FROM t_userWHERE username = #{username}</select></mapper>
- UserService.java
package com.travel.travels.service;import com.travel.travels.entity.User;public interface UserService {void register(User user);User login(User user);
}
- UserServiceImpl.java
package com.travel.travels.service;import com.travel.travels.dao.UserDao;
import com.travel.travels.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
@Transactional
public class UserServiceImpl implements UserService{@Autowiredprivate UserDao userDao;@Overridepublic void register(User user) {if (userDao.findByUsername(user.getUsername()) == null) {userDao.save(user);} else {throw new RuntimeException("用户名已存在!");}}@Overridepublic User login(User user) {User userDB = userDao.findByUsername(user.getUsername());if (userDB != null) {if (userDB.getPassword().equals(user.getPassword())) {return userDB;}throw new RuntimeException("密码输入错误!");} else {throw new RuntimeException("用户名输入错误!");}}}
4、省份增删改查及分页后端开发
目录结构:
- Province.java
package com.travel.travels.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.Accessors;@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Accessors(chain = true) //chain 若为true,则setter方法返回当前对象
public class Province {private String id;private String name;private String tags;private Integer placecounts;}
- BaseDao.java(抽取出通用的CRUD)
package com.travel.travels.dao;import org.apache.ibatis.annotations.Param;import java.util.List;public interface BaseDao<T,K> {void save(T t);void update(T t);void delete(K k);T findOne(K k);List<T> findAll();List<T> findByPage(@Param("start") Integer start, @Param("rows") Integer row);Integer findTotals();}
- ProvinceDao.java
package com.travel.travels.dao;import com.travel.travels.entity.Province;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface ProvinceDao extends BaseDao<Province, String>{}
- ProvinceMapper.xml
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.travel.travels.dao.ProvinceDao"><!--分页查询所有--><select id="findByPage" resultType="Province">select id,name,tags,placecountsfrom t_provinceorder by placecountslimit #{start}, #{rows}</select><!--查询总条数,用于计算分页--><select id="findTotals" resultType="Integer">select count(id) from t_province</select><!--通过名称查询--><select id="findByName" resultType="Province" parameterType="String">select *from t_provincewhere name like "%" #{name} "%"</select><!--省份添加--><insert id="save" parameterType="Province" keyProperty="id" useGeneratedKeys="true">insert into t_province values (#{id},#{name},#{tags},#{placecounts})</insert><!--删除省份--><delete id="delete" parameterType="String">delete from t_province where id = #{id}</delete><!--查询一个--><select id="findOne" resultType="Province">select id,name,tags,placecountsfrom t_provincewhere id = #{id}</select><!--修改省份--><update id="update" parameterType="Province">update t_provinceset name = #{name}, tags = #{tags}, placecounts = #{placecounts}where id = #{id}</update></mapper>
- ProvinceService.java
package com.travel.travels.service;import com.travel.travels.entity.Province;import java.util.List;public interface ProvinceService {//page:当前页,rows:每页显示记录数List<Province> findByPage(Integer page,Integer rows);//查询List<Province> findByName(String name);//查询总条数Integer findTotals();//保存省份void save(Province province);//删除省份void delete(String id);//查询一个省份Province findOne(String id);//修改省份void update(Province province);
}
- ProvinceServiceImpl.java
package com.travel.travels.service;import com.travel.travels.dao.ProvinceDao;
import com.travel.travels.entity.Province;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;@Service
@Transactional //捕获异常时,要想使事务生效,需要手动抛出RuntimeException异常或者添加rollbackFor = Exception.class
public class ProvinceServiceImpl implements ProvinceService{@AutowiredProvinceDao provinceDao;//分页查找@Overridepublic List<Province> findByPage(Integer page, Integer rows) {// 传入的是当前页数, 以及页面显示的数量// 所以要根据这两个参数计算从mysql中查询数据要从第几行开始查几条int state = (page - 1) * rows; // 计算要查询的数据是从第几条数据开始的return provinceDao.findByPage(state,rows);}//查询所有@Overridepublic Integer findTotals() {return provinceDao.findTotals();}//添加省份@Overridepublic void save(Province province) {province.setPlacecounts(0);//新省份添加时景点数为0provinceDao.save(province);}//删除省份@Overridepublic void delete(String id) {provinceDao.delete(id);}//查询一个省份@Overridepublic Province findOne(String id) {return provinceDao.findOne(id);}/*** 通过名称查询* @param name* @return*/@Overridepublic List<Province> findByName(String name) {return provinceDao.findByName(name);}//修改省份@Overridepublic void update(Province province) {provinceDao.update(province);}}
- ProvinceController.java
package com.travel.travels.controller;import com.travel.travels.entity.Province;
import com.travel.travels.entity.Result;
import com.travel.travels.service.ProvinceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.List;
import java.util.Map;@RestController
@CrossOrigin
@RequestMapping("/province")
public class ProvinceController {@AutowiredProvinceService provinceService;@GetMapping("/findByPage")public Map<String,Object> findByPage(Integer page, Integer rows){page = page==null? 1 : page;rows = rows==null? 4 : rows;System.out.println(page+ " : " + rows);HashMap<String,Object> map = new HashMap<>();//分页查询出当前页面显示的数据List<Province> provinces = provinceService.findByPage(page,rows);//查询总数据条数Integer totals = provinceService.findTotals();// 计算总页数// 如果总数据条数可以整除每一页数据个数, 说明结果正好为总页数// 如果总数据条数无法整除每一页数据个数, 说明总页数需要结果 + 1Integer totalPage = totals % rows == 0 ? totals/rows : totals/rows + 1;map.put("provinces",provinces);map.put("page",page);map.put("totalPage",totalPage);map.put("totals",totals);map.forEach((k, v) -> {System.out.println(k + ": " + v);});return map;}/*** 添加省份* @param province* @return*/@PostMapping("/save")public Result save(@RequestBody Province province){Result result = new Result();try{provinceService.save(province);result.setMsg("添加省份成功");}catch (Exception e){e.printStackTrace();result.setState(false).setMsg("添加省份失败!");}return result;}/*** 删除省份* @param id* @return*/@GetMapping("/delete")public Result delete(String id){Result result = new Result();try{provinceService.delete(id);result.setMsg("删除省份成功");}catch (Exception e){e.printStackTrace();result.setState(false).setMsg("删除省份失败!");}return result;}/*** 修改省份* @param province* @return*/@PostMapping("/update")public Result update(@RequestBody Province province){Result result = new Result();try{provinceService.update(province);result.setMsg("修改省份成功!");}catch (Exception e){e.printStackTrace();result.setState(false).setMsg("修改省份失败");}return result;}/*** 查询一个省份* @param id* @return*/@GetMapping("/findOne")public Province findOne(String id){return provinceService.findOne(id);}/*** 通过名称查询* @param name* @return*/@GetMapping("/findByName")public List<Province> findByName(String name){return provinceService.findByName(name);}
}
5、省份增删改查及分页前端开发
- 新建组件main.vue
<template><div><div id="wrap"><div id="header"><div style="float: right;padding-top: 24px">{{time}}  <a @click="back_login" style="color:#fff;float: right">安全退出</a></div><h1>旅游信息管理系统</h1></div><div id="header-bar"></div><div id="content" style="height: 360px"><h2>省份列表</h2><input v-model="pname" @keyup.enter="search_ByPname" type="text" placeholder="请输入查询条件"><table><thead><tr><th width="15%">ID</th><th width="20%">省份</th><th width="25%">标签</th><th width="15%">景点个数</th><th width="25%">操作</th></tr></thead><tbody><tr v-for="province in provinces" :key="province.id"><td v-text="province.id"></td><td v-text="province.name"></td><td v-text="province.tags"></td><td v-text="province.placecounts"></td><td><a href="javascript:;" @click="deleteProvince(province.id)">删除省份</a><a :href="'../viewspot/viewspotlist.html?id=' + province.id">景点列表</a><!-- <a :href="'../update_province?id=' + province.id">修改省份</a> --><a href="javascript:;" @click="updateProvince(province.id)">修改省份</a></td></tr></tbody></table><a @click="to_addprovince"><button type="button">添加省份</button></a><div id="pages"><!--上一页, 只有当前所在页数>1才会显示--><a href="javascript:;" class="page" v-if="page > 1" @click="findAll(page - 1)"><上一页</a><!--页面--><a href="javascript:;" class="page" v-for="indexpage in totalPage" @click="findAll(indexpage)"v-text="indexpage"></a><!--下一页, 只有当前所在页数<总页数才会显示--><a href="javascript:;" class="page" v-if="page < totalPage" @click="findAll(page + 1)">下一页></a></div></div><div id="footer">yusael~</div></div></div>
</template><script>export default {name: "Main",data() {return {provinces: [],page: 1,rows: 4,totalPage: 0,totals: 0,time: "",pname:'广东',}},methods: {search_ByPname(){const _this = thisthis.axios.get("/province/findByName?name="+ this.pname ).then(res =>{console.log(res)_this.provinces = res.data;}) },to_addprovince(){this.$router.push("/add_province")},findAll(indexpage) { // 查询某一页的数据if (indexpage) {this.page = indexpage;}const _this = this; // 保存当前对象, 用于下面的作用域this.axios.get("/province/findByPage?page=" + this.page + "&rows=" + this.rows).then((res) => {console.log(res)_this.provinces = res.data.provinces;_this.page = res.data.page;_this.totalPage = res.data.totalPage;_this.totals = res.data.totals;});},deleteProvince(id) {if (confirm("确定要删除省份信息吗?")) {this.axios.get("/province/delete?id=" + id).then((res) => {if (res.data.state) {alert(res.data.msg + "点击确定跳转到省份列表页面!");location.reload(true); // 刷新当前页面} else {alert(res.data.msg);}});}},updateProvince(id){this.$router.push("/update_province?id="+ id);},back_login(){this.$router.push("/login")},},created() {this.findAll();let now = new Date();this.time = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`;}}
</script><style scoped>table {width: 100%;margin-bottom: 15px;border-collapse: collapse;table-layout: fixed;}th, td {border: 1px solid #CBD6DE;padding-left: 10px;line-height: 28px;}th {text-align: left;background: linear-gradient(#edf2f5, #dce9f2, #edf2f5);color: #467aa7;}tbody tr:nth-child(even) {background: #f2f2f2;}#pages {text-align: center;padding-top: 8px;}.page {min-width: 50px;display: inline-block;}
</style>
- add_province.vue
<template><div><div id="wrap"><div id="header"><div style="float: right;padding-top: 24px">{{time}}  </div><h1>旅游信息管理系统</h1></div><div id="header-bar"></div><div id="content" style="height: 360px"><img style="float: right;height: 320px"><h2>添加省份</h2><form action="provincelist.html" method="post"><label><div class="label-text">省 份:</div><input type="text" v-model="province.name"></label><label><div class="label-text">标 签:</div><input type="text" v-model="province.tags"></label><button type="button" @click="saveProvinceInfo">提 交</button> <a @click="back_main">返回</a></form></div><div id="footer">yusael~</div></div></div>
</template><script>export default{data() {return {province: {},time: "",}},methods: {saveProvinceInfo() {const _this = thisthis.axios.post("/province/save", this.province).then((res) => {if (res.data.state) {alert(res.data.msg + "点击确定跳转到省份列表页面!");_this.$router.push('/main')} else {alert(res.data.msg);}});},back_main(){this.$router.push("/main")}},created() {let now = new Date();this.time = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`;}}
</script><style scoped> form {width: 270px;}input {width: 70%;background: #eee;}input:focus {background: #fff;}form {padding: 0 12px 12px;}label {display: block;padding-bottom: 12px;}.label-text {width: 30%;float: left;}
</style>
- update_province.vue
<template><div><div id="wrap"><div id="header"><div style="float: right;padding-top: 24px">{{time}} </div><h1>旅游信息管理系统</h1></div><div id="header-bar"></div><div id="content" style="height: 360px"><img style="float: right;height: 320px"><h2>修改省份</h2><form action="provincelist.html" method="post"><label><div class="label-text">省 份:</div><input type="text" v-model="province.name"></label><label><div class="label-text">标 签:</div><input type="text" v-model="province.tags"></label><button type="button" @click="updateProvince">提 交</button> <a @click="back_main">返回</a></form></div><div id="footer">yusael</div></div></div>
</template><script>export default{data() {return {id: "",province: {},time: "",}},methods: {findOneProvince() {const _this = thisthis.axios.get("/province/findOne?id=" + this.id).then((res) => {_this.province = res.data;});},updateProvince() {const _this = thisthis.axios.post("/province/update", this.province).then((res) => {if (res.data.state) {alert(res.data.msg + "点击确定跳转到省份列表页面!");_this.$router.push("/main")} else {alert(res.data.msg);}});},back_main(){this.$router.push("/main")},},created() {this.id = location.href.substring(location.href.indexOf("=") + 1);this.findOneProvince();let now = new Date();this.time = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`;}}
</script><style scoped>form {width: 270px;}input {width: 70%;background: #eee;}input:focus {background: #fff;}form {padding: 0 12px 12px;}label {display: block;padding-bottom: 12px;}.label-text {width: 30%;float: left;}
</style>
- 在main.js中导入组件并配置路由
import Main from '../components/Main'
import Add_province from '../components/province/Add_province'
import Update_province from '../components/province/Update_province'//配置导出路由
export default new VueRouter({routes:[{path: '/main',name: Main,component: Main},{path: '/add_province',name: Add_province,component: Add_province},{path: '/update_province',name: Update_province,component: Update_province},]
})
6、效果
完成了功能,页面后续有空再作调整…
省份列表展示:
添加省份:
删除省份:
修改省份:
模糊查询:
推荐文章:
springboot整合redis并在项目中使用
vue+springboot 登录注册功能