技术标签: spring boot 第一个小项目实战 java
学习了Java两个月后,自己开始跟着老师做了一个小项目,我想记录一下自己第一次做项目的过程,以及自己遇到的一些难题。
老师已经把整个项目给我们讲解完了,但是你懂的,不经过自己的实际操作,你是很难从项目中学到东西的。于是我开始从前端页面开始写,按照自己的理解和参照老师的代码,我成功把注册和登录页面写出来了(哈哈,我的基础的的确很差),而且实现了第一个难题的突破,也就是验证码这个部分,如下图:
(先忽略我这个后端仔写的页面~~~)
看,这个验证码还不错吧,只要点击它,就可以实时刷新啦。因为前端用的是Vue.js、ElementUI、还有Axios写的,所以把验证码传到页面还算简单,真正的难点是画验证码的部分。你没听错,这个验证码是画出来的,代码真的很神奇。我把验证码的实现封装在了一个工具类中,话不多说,直接上代码:
话不多说,直接上代码,
/**
* 验证码工具类
*/
public final class VerifyCodeUtil {
/*定义图片的width*/
private static int WIDTH = 80;
/*定义图片的height*/
private static int HEIGHT = 30;
/*定义图片上显示的验证码个数*/
private static int CODECOUNT = 4;
/*字符间隔*/
private static final int CHARACETRSPACING = 8;
/*字体大小*/
private static final int FONTHEIGHT = 24;
/*干扰线*/
private static final int LINENUMBER = 25;
/*字符垂直位置*/
private static final int VERTICALPOSITION = 24;
private static final char[] CODESEQUENCE = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
'P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n',
'o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0'};
/*无参构造器*/
private VerifyCodeUtil(){}
/**
* 生成验证码字符串
* @param count 验证码字符个数
* @return 返回验证码字符串
*/
public static String generateVerifyCode(int count){
//产生随机数
Random random = new Random();
//生成验证码
StringBuilder randomCode = new StringBuilder();/*StringBuilder可变字符串序列*/
for (int i = 0; i < count; i++) {
//获取一位验证码
String code = String.valueOf(CODESEQUENCE[random.nextInt(CODESEQUENCE.length)]);
randomCode.append(code);/*字符串拼接*/
}
return randomCode.toString();
}
/**
* 生成验证码字符串
* @return 返回验证码字符串
*/
public static String generateVerifyCode(){//方法的重载
return generateVerifyCode(CODECOUNT);//静态方法中只能调用静态方法
}
/**
* 生成验证码图片
* @param width 验证码图片的宽度,默认95
* @param height 验证码图片的高度,默认30
* @param code 验证码字符串
* @return 返回创建好的画布对象
*/
public static BufferedImage outputImage(Integer width, Integer height, String code){
if(!ObjectUtil.isEmpty(width)){//Spring工具包中的方法
WIDTH = width;//为图片设置宽度
}
if(!ObjectUtil.isEmpty(height)){
HEIGHT = height;//为图片设置高度
}
if(ObjectUtil.isEmpty(code)){
return null;//做这些判断都是为了防止出现空指针异常
}
//创建画布对象(不带透明色)
BufferedImage buffImg = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
//创建画笔对象
Graphics gd = buffImg.getGraphics();
//创建生成随机数对象
Random random = new Random();
//设置画布背景色(白色)
gd.setColor(Color.WHITE);
//根据设置的背景色填充画布
gd.fillRect(0, 0, WIDTH, HEIGHT);
//创建字体对象
Font font = new Font("Arial", Font.BOLD, FONTHEIGHT);
//给画笔对象设置字体
gd.setFont(font);
//给画笔对象设置颜色
gd.setColor(Color.BLACK);
//给画布绘制边框
gd.drawRect(0, 0, WIDTH - 1, HEIGHT - 1);
//生成验证码
char[] codes = code.toCharArray();
for (int i = 0; i < codes.length; i++) {
//设置颜色
gd.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
//绘制验证码
gd.drawString(String.valueOf(codes[i]), CHARACETRSPACING + i * 2 * CHARACETRSPACING, VERTICALPOSITION);
}
//设置干扰线颜色(深灰色)
gd.setColor(Color.DARK_GRAY);
//干扰线
for (int i = 0; i < LINENUMBER; i++) {
//线的起始X坐标
int startX = random.nextInt(WIDTH);
//线的起始Y坐标
int startY = random.nextInt(HEIGHT);
//线的结束X坐标
int endX = random.nextInt(VERTICALPOSITION);
//线的结束Y坐标
int endY = random.nextInt(VERTICALPOSITION);
//绘制直线
gd.drawLine(startX, startY, startX + endX, startY + endY);
}
return buffImg;
}
/**
* 输出验证码图片流
* @param w 宽度
* @param h 高度
* @param code 验证码字符串
* @param os 输出流
*/
public static void outputImage(Integer w, Integer h, String code, OutputStream os) throws IOException {
if(ObjectUtil.isEmpty(code)){
return;
}
// 创建画布对象
BufferedImage bi = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
// 创建画笔对象
Graphics gd = bi.getGraphics();
// 创建生成随机数对象
Random random = new Random();
// 设置画布背景色
gd.setColor(Color.DARK_GRAY);
// 根据设置的背景色填充画布
gd.fillRect(0, 0, WIDTH, HEIGHT);
// 创建字体对象
Font font = new Font("Arial", Font.BOLD, FONTHEIGHT);
// 给画笔对象设置字体
gd.setFont(font);
// 给画笔设置颜色
gd.setColor(Color.BLACK);
// 给画布绘制边框
//gd.drawRect(0, 0, WIDTH - 1, HEIGHT - 1);
// 设置干扰线颜色
gd.setColor(Color.BLACK);
// 干扰线
for (int i = 0; i < LINENUMBER; i++) {
// 线的起始X坐标
int startX = random.nextInt(WIDTH);
// 线的起始Y坐标
int startY = random.nextInt(HEIGHT);
// 线的结束X坐标
int endX = random.nextInt(VERTICALPOSITION);
// 线的结束Y坐标
int endY = random.nextInt(VERTICALPOSITION);
// 绘制直线
gd.drawLine(startX, startY, startX + endX, startY + endY);
}
// 生成验证码
char[] codes = code.toCharArray();
for (int i = 0; i < codes.length; i++) {
// 设置颜色
gd.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
// 绘制验证码
gd.drawString(String.valueOf(codes[i]), CHARACETRSPACING + i * 2 * CHARACETRSPACING, VERTICALPOSITION);
}
gd.dispose();
ImageIO.write(bi, "png", os);
}
/**
* 输出验证码图片流
* @param code 验证码
* @param os 创建的输出流
*/
public static void outputImage(String code, OutputStream os) throws IOException {
outputImage(WIDTH, HEIGHT, code, os);
}
}
这就是实现验证码的整个过程啦。我们做的是一个简单的客户管理系统,后续还会继续更新嗷~
文章浏览阅读2.4k次。一、准备工作1.注册账号注册一个Docker Hub账号,管理自己的镜像(共享镜像)https://hub.docker.com2.新建一个仓库Docker hub上面创建仓库,仓库用于存放镜像,就像我们在Github Create Create Repository比如:仓库名称叫navigation-server,所以路径就是liyinchi/navigation-server了。注意:仓库名称只能小写3.查看容器IDdocker ps上传到Doc._本地docker镜像上传dockhub
文章浏览阅读1.5k次,点赞2次,收藏8次。**this.$refs.transformerForm.clearValidate(['transformerLVSRateCapacity'])**清除切换校验时上一次校验留下的警告文字,<el-form :model="transfomerInfo" :rules="rules" ref="transformerForm" label-width="170px"> <el-form-item label="低压侧容量(MVA):" prop="transformer..._ele 切换后清除校验
文章浏览阅读2k次。0x01、S2-001远程代码执行漏洞原理该漏洞因为用户提交表单数据并且验证失败时,后端会将用户之前提交的参数值使用 OGNL 表达式 %{value} 进行解析,然后重新填充到对应的表单数据中。例如注册或登录页面,提交失败后端一般会默认返回之前提交的数据,由于后端使用 %{value} 对提交的数据执行了一次 OGNL 表达式解析,所以可以直接构造 Payload 进行命令执行影响版本Struts 2.0.0 - Struts 2.0.8poc执行任意命令%{#a=(new java.lan_vulhub靶场有哪些漏洞
文章浏览阅读1.7w次,点赞5次,收藏33次。1 问题找出2个文件里面重复的数据(这个问题是csdn排名第一的大神stpeace的专栏在微信里面和我的交流,我当时一脸懵逼)文件a.txt文件内容如下cat a.txt123123234345456文件b.txt文件内容如下cat b.txt234345456789789两个文件重复的数据如下234345456..._limux中a-b相同内容
文章浏览阅读545次。说明:在调用applyhatch前,按照自己的需要对Matlab自动绘制的图片编辑。function applyhatch(h,patterns,colorlist)%APPLYHATCH Apply hatched patterns to a figure% APPLYHATCH(H,PATTERNS) creates a new figure from the figure Hby% repl..._matlab不等间隔直方图
文章浏览阅读373次。本人使用的版本是navicat_for_mysql_10.0.11_cn_linux,使用官网上下的11版本的无法打开注意解压目录不要放在中文目录下,会出现各种问题,本人就出现打开之后添加列名添加不上。(1).先安装wine环境yum install wine如果yum源中没有,可以使用下面这个源wgethttp://download.fedoraproject.org/pub/epel/6/i..._centos7安装navicate for mysql
文章浏览阅读234次。列表的开始和结束要加上中括号 采用逗号将列表的项与项分开 使用“=”号操作符将整个列表赋予一个变量列表中可以放置任意的数据类型,如果是字符串,需要打上引号2.列表索引:从0开始;可以倒着来数,最后一个的序号是-1。取列表中的值:print aList[1]、print aList[-2]、print aList[-1][0]片段切片:[a:b],表示从a开始(包括a)到b之..._python列表类型怎么写
文章浏览阅读2.2k次。在oracle的存储过程中,不能直接使用DDL语句,比如create、alter、drop、truncate等。那如果我们想在存储过程中建立一张临时表就只能使用动态sql语句了:create or replace procedure pro asstr_sql varchar2(100);begin-- 创建临时表str_sql := 'create global temporary table ..._oracle 存储过程 临时表
文章浏览阅读476次。特别注意:本人很懒就搞了些懒人办法1.建立个文本。shell.sh,复制下面代码保存。打开终端(建议直接root用戶运行)。2.sudo chmod +x sheell.sh3.sudo ./shell.sh 文件名.avi (扩展名可以任意) 使用方法4.这段代码 支持H264 h265 支持60针视频5.shell.sh 文件要和视频文件同一目录6.转换完的文件被保存在finish文件夹中#!/bin/bash##i-合并视频##-change(转换)##i用法i(_kvmts
文章浏览阅读4.2k次。SpringBoot整合Redis与Cache实现分页缓存_分页缓存
文章浏览阅读192次。一、tomcat7.exe与startup.bat的区别:1、这两个都可以启动tomcat,但tomcat7.exe必须安装了服务才能启动,而startup.bat不需要2、另外一个区别是它们启动所使用的JAVA环境配置是分开的tomcat7.exe启动所使用JAVA配置与服务启动所使用的JAVA配置一样,都是通过tomcat7w.exe的JAVA面板配置(可以在创建服务前修..._龙蜥操作系统tomcat启动的java和java版本不一样
文章浏览阅读1.2k次。下面的伪元素都与元素相对于HTML文档和它内部的HTML元素的位置有关。:first-letter允许你选定元素的第一个字母。下面是一个例子:p:first-letter {font-size:30pt;display:block;float:left;margin:05px5px0;}:first-line伪元素让你可以选择HTML元素包含文本的首行。下面一个例子为文本的第一行加粗,并让它的字母..._css第几个判断