springboot+mybatis+vue实战——旅游网站(一) 完成登录注册、验证码、省份增删改查功能

news/2024/5/20 15:48:03/文章来源:https://blog.csdn.net/m0_45234510/article/details/107087289

推荐文章:
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"/> &emsp; </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">&emsp;号:</div><input type="text" v-model="user.username" name="username"></label><label><div class="label-text">&emsp;码:</div><input type="password" v-model="user.password" name="password"></label><label><div class="label-text">&emsp;箱:</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>&emsp;<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"/>&emsp;</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">&emsp;号:</div><input type="text" v-model="user.username" name="username"></label><label><div class="label-text">&emsp;码:</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>&emsp;<!-- <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}} &emsp;<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)">&lt;上一页</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)">下一页&gt;</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}} &emsp;</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">&emsp;份:</div><input type="text" v-model="province.name"></label><label><div class="label-text">&emsp;签:</div><input type="text" v-model="province.tags"></label><button type="button" @click="saveProvinceInfo">提 交</button>&emsp;<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}}&emsp;</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">&emsp;份:</div><input type="text" v-model="province.name"></label><label><div class="label-text">&emsp;签:</div><input type="text" v-model="province.tags"></label><button type="button" @click="updateProvince">提 交</button>&emsp;<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 登录注册功能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_748392.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python爬虫网站图片并下载到本地

文章目录先看效果1、环境准备2、要爬取的网站3、程序源代码&#xff08;可直接运行&#xff09;先看效果 1、环境准备 import requests import re下载requests库&#xff1a; pip install requests2、要爬取的网站 https://www.hippopx.com3、程序源代码&#xff08;可直接运…

美国空军文化中心网站遭入侵 信息泄露

本文讲的是 : 美国空军文化中心网站遭入侵 信息泄露 , 日前&#xff0c;美国空军文化&语言中心(http://www.culture.af.mil)官方网站遭土耳其黑客Maxney入侵&#xff0c;并在网络公布了部分高度敏感的个人信息。 土耳其黑客组织Ajan的一位成员Maxney声称对此次入侵事件负…

威联通架设php网站_第14章 网站服务

一、概念HTML&#xff1a;HyperText Markup Language &#xff08; 超级 文本 标记 语言&#xff09;网页&#xff1a;使用HTML,PHP,JAVA语言格式书写的文件主页&#xff1a;网页中呈现用户的第一个页面网站&#xff1a;多个网页组合而成的一台网站服务器URL格式&#xff1a;在…

给自己的网站加入智能聊天功能

引言 现在突然发现有很多 QQ 群都开启了群机器人的功能&#xff0c;其中有两个角色&#xff0c;他们分别是&#xff1a;Baby Q 和 QQ 小冰。在 Q 群中&#xff0c;你可以对他们进行任意程度的调戏&#xff0c;不过&#xff0c;遗憾的是鱼和熊掌不可得兼&#xff0c;一个群只能进…

如何在IIS7上部署本地网站

首先打开计算&#xff0c;点击”卸载或更改程序“&#xff0c;如图&#xff1a; 然后点击&#xff1a; 之后就看到里面有个”Internet信息服务“将里面的所有选项最好都打上勾 勾完之后点击【确定】&#xff0c;会提示&#xff1a; 过几分钟就IIS安装好了 然后在【控…

怎样将IIS Express里面的网站能在局域网访问

先运行web项目&#xff0c;点击IIS Express里面运行的当前项目&#xff0c;然后能看到下面的配置路径&#xff0c;点击它&#xff0c;可以跳转到配置文件 修改配置文件的bindings节点&#xff0c;在原有的&#xff0c;比如“ <binding protocol"http" bindingInfo…

本地IIS浏览网站出现503错误

本地出现这个错误&#xff0c;修改IIS里面对应网站应用程序池的高级属性&#xff0c;改为如图所示的属性&#xff1a;

网站点击流数据分析项目----之现学现卖

1&#xff1a;网站点击流数据分析项目推荐书籍&#xff1a; 可以看看百度如何实现这个功能的&#xff1a;https://tongji.baidu.com/web/welcome/login 1 网站点击流数据分析&#xff0c;业务知识&#xff0c;推荐书籍&#xff1a; 2 《网站分析实战——如何以数据驱动决策&…

oracle网站爬数据,利用Powerquery,Excel也可以轻松网上爬取数据了

Powerquery在PowerBI和Excel种的操作类似&#xff0c;以下以PowerBI Desktop操作为例&#xff0c;你也可以直接从Excel种操作&#xff0c;数据的获取上不仅支持微软自己的数据格式&#xff0c;比如Excel、SQL Server、Access等;还支持SAP、Oracle、MySQL、DB2等几乎能见到的所有…

微羽网站服务器配置,微羽网站服务器(Plume Web Server) V0.4.6 官方正式安装版

微羽网站服务器欢迎您下载使用微羽网站服务器Plume Web Server是一款极速、高效、精致的Web服务器&#xff0c;方便、易用&#xff0c;是功能特色1、简单操作&#xff0c;轻松上手&#xff01;只要轻按上面的立即下载按钮&#xff0c;运行安装包&#xff0c;默认安装至D盘&…

刚6瓶啤酒4两56度白酒下肚,居然20分钟做了一手机版网站 !

刚6瓶啤酒4两56度白酒下肚,居然20分钟不到时间做了一手机版网站 !人有多大潜力你知道吗?大家有兴趣的可以用手机或微信打开http://xh.yunxunmi.com/ 看看俺这酒后之做! 为了做新闻APP&#xff0c;我居然短短一个月利用业余时间做了&#xff1a;一个通用新闻采集器、一个新闻后…

安装asp.net运行环境,为IIS网站配置环境

winr输入cmd进入控制台 然后输入命令&#xff1a; cd C:\Windows\Microsoft.NET\Framework\v4.0.30319 回车 然后输入命令aspnet_regiis.exe -i 回车&#xff0c;然后等待ASP.NET (4.0.30319.0)安装完毕… 效果图&#xff1a;

python+selenium实现网站图片批量下载保存

最近有一个需求&#xff0c;就是想批量下载网站的图片&#xff0c;刚开始想到的是用爬虫方式&#xff0c;但是尝试了一些网站&#xff0c;发现都有反爬虫&#xff0c;虽然也有修改Header、设置代理IP等方法可以解决&#xff0c;但是后续爬虫代码自我感觉写起来也挺麻烦。之后学…

[转]Asp.Net 网站多语言解决方案

本文转自&#xff1a;https://www.cnblogs.com/FredTang/archive/2013/01/23/2873231.html 最近领导要求实现PMSWeb应用程序的多区域语言的支持&#xff0c;所以在网搜集相关的信息&#xff0c;写出了解决方案文档&#xff0c;欢迎各位批评指正&#xff0c;谢谢&#xff01;废话…

从Linux服务器下载网站文件

最近公司迁来一个新客户&#xff0c;该客户的网站是别的网络服务商做的&#xff0c;放在linux主机上&#xff0c;因为客户跟之前的网络服务商合作的不愉快所以就把网站迁到我们公司&#xff0c;经理让我把网站文件和数据库download下来并在我们windows空间上进行部署之前的服务…

Bugku,Web:网站被黑

1. 进入场景 无法右键 f12查看源代码 没有提示 由于是网页被黑 使用御剑扫描试试 御剑扫描工具是一款后台安全扫描工具&#xff0c;它能帮你实时监控后台文件的安全性&#xff0c;防御网站风险 2. 扫描后发现shell,php 进入 随便输入一个a进行抓包 bp爆破 得到密码ha…

六个维权相关电话与网站

一、12315互联网平台与微信小程序 全国12315互联网平台&#xff0c;是全国消费者通过电脑、手机APP、微信公共号、微信小程序等多渠道、24小时便捷高效地进行投诉、举报的平台。这一平台由工商总局建设&#xff0c;全国工商和市场监管部门共同使用&#xff0c;解决不良商家问题…

Windows服务器上搭建Windows2003+IIS+ASP.NET+MSSQL网站

一、安装IIS服务 1. 选择“开始”→“所有程序”→“管理工具”→“管理您的服务器”菜单命令&#xff0c;启动“添加或删除你的角色”对话框&#xff0c;单击两次“下一步”按钮&#xff0c;若出现“配置选项”向导页&#xff0c;选择“自定义配置”单选钮&#xff0c;单击“下…

使用webmagic爬取51job网站的招聘信息

最近做了一个爬虫项目&#xff0c;爬取了51job网站的招聘信息。 1.首先编写数据库表&#xff1a; CREATE TABLE job_info ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT ‘主键id’, company_name varchar(100) DEFAULT NULL COMMENT ‘公司名称’, company_addr varchar(…

Bugku,Web:程序员本地网站

让服务器获取请求端的本地 IP 地址&#xff0c;添加 XFF 头部 获取 flag