SpringBoot + Vue 开发前后端分离的旅游管理系统(1)

org.junit.vintage

junit-vintage-engine

org.springframework.boot

spring-boot-maven-plugin

配置文件(application.properties)


application.properties:

server.port=8989

spring.application.name=travels

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.datasource.url=jdbc:mysql://localhost:3306/travels?characterEncoding=UTF-8

spring.datasource.username=root

spring.datasource.password=1234

mybatis.mapper-locations=classpath:com/yusael/travels/mapper/*.xml

mybatis.type-aliases-package=com.yusael.travels.entity

logging.level.root=info

logging.level.com.yusael.travels.dao=debug

上传的图片存放的路径

upload.dir=D:/CodePro/IdeaPro/SpringBoot/travels/images

spring.resources.static-locations=file:${upload.dir}

href=“javascript:;” 含义

=========================================================================================

代码中经常遇到这种写法:

<a href=“javascript:;” @click=“deleteProvince(province.id)”>删除省份

其中的 href="javascript:;" 是什么意思呢?

  • javascript: 表示在触发默认动作时,执行一段 JavaScript 代码;

  • javascript:; 表示什么都不执行,这样点击时就没有任何反应,相当于去掉 a 标签的默认行为。

select - option 绑定 Vue 实例

============================================================================================

select 中 通过 v-model 绑定当前的选项,option 中使用 v-for 遍历显示所有选项。

所属省份:

删除时增加确认选项

============================================================================

if (confirm(“确定要删除景点吗?”)) {

// code…

}

在这里插入图片描述

Vue 获取地址栏跳转的参数

=================================================================================

对于这么一个 a 标签,我们要在另一个页面获取这个 url 的参数 id:

修改省份

可以通过 location.href 获取 url 再进行截取:

var id = location.href.substring(location.href.indexOf(“=”) + 1);

前后端分离项目—验证码功能

================================================================================

验证码工具类:

package com.yusael.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;

public class CreateImageCode {

// 图片的宽度。

private int width = 160;

// 图片的高度。

private int height = 40;

// 验证码字符个数

private int codeCount = 4;

// 验证码干扰线数

private int lineCount = 20;

// 验证码

private String code = null;

// 验证码图片Buffer

private 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;

// 图像buffer

buffImg = 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());

}*/

}

后台控制器:需要对生成的验证码图片进行 Base64 编码后传到前端页面,前端再解析展示图片。

@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();

// 验证码存入session

String 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;

}

}

前端页面:

<img :src=“src” id=“img-vcode” @click=“getImage” :key=“key”>

验证码:

前后端分离项目—分页功能

===============================================================================

mysql 的 LIMIT 分页语句:

  • LIMIT n: 取前 n 个数据,相当于 LIMIT 0, n

  • LIMIT 2, 4: 从第 3 行开始检索 4 条数据;


分页查询的SQL语句:参数1是开始查询的数据行,参数2是查询数据条数。

SELECT * FROM t_province

ORDER BY placecounts

LIMIT #{start}, #{rows}

后台业务层代码:

传入的参数是当前所在页数,以及页面显示数量,无法直接应用 MySQL 的 limit 查询子句中,需要转换一下:start = (page - 1) * rows 计算出 limit 字句的第一个参数。

@Override

public List findByPage(Integer page, Integer rows) {

// 传入的是当前页数, 以及页面显示的数量

// 所以要根据这两个参数计算从mysql中查询数据要从第几行开始查几条

int start = (page - 1) * rows; // 计算要查询的数据是从第几条数据开始的

return provinceDAO.findByPage(start, rows);

}

后台控制器代码:

/**

  • 分页查询数据

*/

@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 provinces = provinceService.findByPage(page, rows);

// 查询总数据条数, 用于计算总页数

Integer totals = provinceService.findTotals();

// 计算总页数

// 如果总数据条数可以整除每一页数据个数, 说明结果正好为总页数

// 如果总数据条数无法整除每一页数据个数, 说明总页数需要结果 + 1

Integer totalPage = totals % rows == 0 ? totals / rows : totals / rows + 1;

map.put(“provinces”, provinces);

map.put(“totals”, totals);

map.put(“totalPage”, totalPage);

map.put(“page”, page);

map.forEach((k, v) -> {

System.out.println(k + ": " + v);

});

return map;

}

前端页面:

<a href=“javascript:;” class=“page” v-if=“page > 1” @click=“findAll(page - 1)”><上一页

<a href=“javascript:;” class=“page” v-for=“index in totalPage” @click=“findAll(index)” v-text=“index”>

<a href=“javascript:;” class=“page” v-if=“page < totalPage” @click=“findAll(page + 1)”>下一页>

超链接的写法可以更优化一下:优化后点击当前所在页数无效(不会发送任何请求)。

<a href=“javascript:;” class=“page” v-if=“page > 1” @click=“findAllPage(page - 1)”><上一页

<a href=“javascript:;” class=“page” v-if=“page != index” @click=“findAllPage(index)” v-text=“index”>

<a href=“javascript:;” class=“page” v-if=“page < totalPage” @click=“findAllPage(page + 1)”>下一页>

前后端分离项目—日期数据类型的处理

====================================================================================

前后端数据交互采用的是 Json 的话,只需要在实体类中的属性加一个注解即可:

Docker步步实践

目录文档:

①Docker简介

②基本概念

③安装Docker

④使用镜像:

⑤操作容器:

⑥访问仓库:

⑦数据管理:

⑧使用网络:

⑨高级网络配置:

⑩安全:

⑪底层实现:

⑫其他项目:

= res.data.provinces;

_this.page = res.data.page;

_this.totalPage = res.data.totalPage;

_this.totals = res.data.totals;

});

},

},

created() {

this.findAll();

}

});

前后端分离项目—日期数据类型的处理

====================================================================================

前后端数据交互采用的是 Json 的话,只需要在实体类中的属性加一个注解即可:

Docker步步实践

目录文档:

[外链图片转存中…(img-2vFH9MqQ-1714459007880)]

[外链图片转存中…(img-WtFn5Tka-1714459007881)]

①Docker简介

②基本概念

③安装Docker

[外链图片转存中…(img-NfETczty-1714459007881)]

④使用镜像:

[外链图片转存中…(img-F3ciX0Tk-1714459007881)]

⑤操作容器:

[外链图片转存中…(img-siHmSZFi-1714459007882)]

⑥访问仓库:

[外链图片转存中…(img-8VdYWuH9-1714459007882)]

⑦数据管理:

[外链图片转存中…(img-MbwRgflH-1714459007883)]

⑧使用网络:

[外链图片转存中…(img-DdrqmoyT-1714459007883)]

⑨高级网络配置:

[外链图片转存中…(img-thOl2PvB-1714459007883)]

⑩安全:

[外链图片转存中…(img-jDTHg298-1714459007884)]

⑪底层实现:

[外链图片转存中…(img-DAGe5sHh-1714459007884)]

⑫其他项目:

[外链图片转存中…(img-ZinuCgsU-1714459007884)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 27
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值