base:这个我用来入门SpringBoot的一个小项目,只注重如何把功能做出来并在这个过程练习一下使用SpringBoot
网站具体的功能是:代码分享。分享者将分享的代码和口令填入网站中进行分享,被分享者可以使用口令或是网址进行代码的查看,功能基本和Ubuntu Paste(https://paste.ubuntu.com/)这个网站一致。
使用的技术栈有:SpringBoot、Redis、Mysql
步骤一:搭建SpringBoot项目
此步骤只需按照图片搭建或是自行搭建即可
文件结构大致如下图。创建一个baseController类,测试SpringBoot是否正常工作
@RestController
@RequestMapping("")
public class baseController {
@RequestMapping("hello")
public String hello(){
return "hello";
}
}
步骤二:整合Redis
首先安装一个Redis,并启动服务、测试
接下来进行SpringBoot和Redis的整合
<!-- pom.xml -->
<!--jedis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<!--<artifactId>spring-boot-starter-redis</artifactId>-->
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
在com.hazy.codeshare下新建一个config包,并新建一个RedisConfig类,作为redis的配置类
@Configuration
@PropertySource("classpath:redis.properties")
public class RedisConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout;
@Value("${spring.redis.jedis.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.jedis.pool.max-wait}")
private long maxWaitMillis;
// @Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.block-when-exhausted}")
private boolean blockWhenExhausted;
@Bean
public JedisPool redisPoolFactory() throws Exception{
// log.info("JedisPool注入成功!!");
// log.info("redis地址:" + host + ":" + port);
System.out.println("JedisPool注入成功!!");
System.out.println("redis地址:" + host + ":" + port);
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
// 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
jedisPoolConfig.setBlockWhenExhausted(blockWhenExhausted);
// 是否启用pool的jmx管理功能, 默认true
jedisPoolConfig.setJmxEnabled(true);
JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password);
return jedisPool;
}
}
与此同时,要写一个Redis的配置文件:在resources目录下新建一个redis.properties,写入基本的redis配置
#redis配置开始
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=localhost
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
# spring.redis.password=123456
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=1024
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=10000
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=200
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=10000
#redis配置结束
spring.redis.block-when-exhausted=true
接下来,可以进行一次测试,启动项目,如果控制台出现redis注入成功就说明redis已经注册成为一个Bean(但不意味着已经可以正常使用)
为了后续方便使用,在com.hazy.codeshare新建一个utils包,并新建一个RedisUtil类(为了方便使用,已经把日志去掉改为控制台输出)这里只有最基本的字符串的set、get和exist功能,可以作为参考
package com.hazy.codeshare.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
@Component
public class RedisUtil {
@Autowired
private JedisPool jedisPool;
/**
* 返还到连接池
*
* @param jedisPool
* @param jedis
*/
public static void returnResource(JedisPool jedisPool, Jedis jedis) {
if (jedis != null) {
jedis.close();
}
}
public String set(String key, String value,int indexdb) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.select(indexdb);
return jedis.set(key, value);
} catch (Exception e) {
System.out.println(e.getMessage());
// log.error(e.getMessage());
return "0";
} finally {
returnResource(jedisPool, jedis);
}
}
/**
* <p>
* 通过key获取储存在redis中的value
* </p>
* <p>
* 并释放连接
* </p>
*
* @param key
* @param indexdb 选择redis库 0-15
* @return 成功返回value 失败返回null
*/
public String get(String key,int indexdb) {
Jedis jedis = null;
String value = null;
try {
jedis = jedisPool.getResource();
jedis.select(indexdb);
value = jedis.get(key);
// log.info(value);
} catch (Exception e) {
System.out.println(e.getMessage());
// log.error(e.getMessage());
} finally {
returnResource(jedisPool, jedis);
}
return value;
}
/**
* 通过key判断redis中是否有该key
* 并释放连接
* @param key
* @param indexdb 选择redis库 0-15
* @return 成功返回value 失败返回null
*/
public boolean exists(String key,int indexdb) {
Jedis jedis = null;
boolean exist = false;
try {
jedis = jedisPool.getResource();
jedis.select(indexdb);
exist = jedis.exists(key);
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
returnResource(jedisPool, jedis);
}
return exist;
}
}
步骤三:编写前端界面(建议直接复制使用或是自己根据后续的路由去编写)
在resources的static目录下新建一个index.html(可以直接被映射)代码如下:
其中,bootstrap最好下载一个,但不是必须。jquery是必须的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/bootstrap/css/bootstrap.min.css">
<script type="text/javascript" src="/bootstrap/js/jquery3.5.js"></script>
<script type="text/javascript" src="/bootstrap/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="/css/index.css">
<script type="text/javascript" src="/js/index.js"></script>
</head>
<body>
<div class=".container">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="main-form well">
<div class="form-group">
<label>口令</label>
<input class="form-control" type="text" name="shareKey" id="shareKey"/>
<span id="shareKey-help" class="help-block"></span>
</div>
<div class="form-group">
<label>请输入代码</label>
<textarea class="form-control" rows="20" name="codeContext" id="codeContext"></textarea>
<span id="codeContext-help" class="help-block"></span>
</div>
<div class="form-group">
<input id="submit-btn" class="btn btn-primary" type="button" value="分享/查询"/>
</div>
<div class="form-group">
选择分享时长:<select class="form-control" id="shareDuration">
<option>临时</option>
<option>永久</option>
</select>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
index.js代码如下:
$(function () {
if(window.location.search != "") {
shareKey = window.location.search.substring(1);
$.get({
url:"/code-share/" + shareKey,
success:function (codeContext_return) {
clearMsg();
if(codeContext_return.code == 200) {
$("#shareKey-help").text(codeContext_return.msg);
$("#shareKey").parent("div").addClass("has-success");
$("#shareKey").val(shareKey);
$("#codeContext").val(codeContext_return.body.shareKey);
}
else {
$("#shareKey").parent("div").addClass("has-error");
$("#shareKey-help").text(codeContext_return.msg);
}
}
});
}
function clearMsg() {
$("#shareKey").parent("div").removeClass("has-error has-success");
$("#shareKey-help").empty();
$("#codeContext").parent("div").removeClass("has-error has-success");
$("#codeContext-help").empty();
}
//提交按钮的功能:判断口令是否为空;判断代码是否为空
$("#submit-btn").click(function () {
clearMsg();
var shareKey = $("#shareKey").val();
if(shareKey == "") {
$("#shareKey").parent("div").addClass("has-error");
$("#shareKey").next("span").text("口令不能为空");
}
var codeContext = $("#codeContext").val();
if($("#shareDuration").val() == "临时")
var shareDuration = "temp";
else
var shareDuration = "permanent";
if(codeContext == "") {
$.get({
url:"/code-share/" + shareKey,
success:function (codeContext_return) {
clearMsg();
if(codeContext_return.code == 200) {
$("#shareKey-help").text(codeContext_return.msg);
$("#shareKey").parent("div").addClass("has-success");
$("#codeContext").val(codeContext_return.body.shareKey);
}
else {
$("#shareKey").parent("div").addClass("has-error");
$("#shareKey-help").text(codeContext_return.msg);
}
}
});
}
else {
$.post({
url:"/code-share/" + shareKey,
data:{codeContext:codeContext, shareDuration:shareDuration},
success:function (result) {
if(result.code == 200)
$("#codeContext-help").text("存储完毕!请把口令或者把 " + window.location.host + "/?" + result.body.shareKey + " 复制给您的好友~");
else
$("#shareKey-help").text(result.msg);
}
});
}
});
//ajax检查口令是否存在
$("#shareKey").change(function () {
clearMsg();
if($(this).val() == "") return ;
$.get({
url:'/check-code-exist/' + $("#shareKey").val(),
success:function (result) {
if(result.code == 400) {
$("#shareKey").parent("div").addClass("has-error");
$("#shareKey-help").text(result.msg);
}
else {
$("#shareKey").parent("div").addClass("has-success");
}
}
});
});
});
写完之后可以进行测试是否能正常访问index页面,各种功能是否能正常使用
步骤四:为了返回信息的统一,创建一个返回信息类
在pojo包下新建一个Msg类
package com.hazy.codeshare.pojo;
import java.util.HashMap;
import java.util.Map;
/**
* @version 1.0
* @Author yd
* @Date 2020/11/19 21:10
* @TODO function
*/
public class Msg {
private Msg(){};
private Msg(int code, String msg) {
this.code = code;
this.msg = msg;
}
//信息的代码:200成功 400失败
private int code;
//返回信息的提示
private String msg;
//返回的信息
private Map<String, Object> body = null;
//成功返回代码200
public static Msg success(String msg) {
return new Msg(200, msg);
}
//失败返回代码400
public static Msg fail(String msg) {
return new Msg(400, msg);
}
//可链式添加
public Msg add(String key, Object value) {
if(body == null) {
body = new HashMap<>();
}
body.put(key, value);
return this;
}
//以下是一系列get、set、tostring方法
}
步骤五:整合mybatis
首先把application.properties删掉,换成application.yml,并写入以下配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/codeshare?useUnicode=true&characterEncoding=UTF-8
username: root
password: 换成你的密码
driver-class-name: com.mysql.jdbc.Driver
mybatis:
type-aliases-package: com.hazy.codeshare.dao
configuration:
map-underscore-to-camel-case: true
并引入依赖:
<!-- 整合mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
此时,需要在mysql中新建库、表
与此对应,需要有一个pojo类:CodeShare
package com.hazy.codeshare.pojo;
import java.sql.Date;
public class CodeShare {
private int id;
private String shareKey;
private String filePath;
private String codeContext;
private Date shareTime;
public CodeShare() {
}
public CodeShare(String shareKey, String filePath) {
this.shareKey = shareKey;
this.filePath = filePath;
}
//一系列get、set、tostring方法
}
和操作数据库的mapper:com.hazy.codeshare.dao.CodeMapper
public interface CodeMapper {
public CodeShare selectByShareKey(String shareKey);
public int insert(CodeShare codeShare);
public int deleteByShareKey(String shareKey);
}
在dao包下写一个Mapper.XML 文件,与CodeMapper同名
<?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">
<mapper namespace="com.hazy.codeshare.dao.CodeMapper">
<resultMap id="CodeShareResultMap" type="com.hazy.codeshare.pojo.CodeShare" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="share_key" property="shareKey" jdbcType="VARCHAR" />
<result column="file_path" property="filePath" jdbcType="VARCHAR" />
<result column="share_time" property="shareTime" jdbcType="VARCHAR" />
</resultMap>
<select id="selectByShareKey" resultType="com.hazy.codeshare.pojo.CodeShare" resultMap="CodeShareResultMap">
select `id`, `share_key`, `file_path`, `share_time` from code where share_key = #{shareKey}
</select>
<insert id="insert" parameterType="com.hazy.codeshare.pojo.CodeShare">
insert into code(`share_key`, `file_path`, `share_time`) values(#{shareKey}, #{filePath}, CURDATE())
</insert>
<delete id="deleteByShareKey" >
delete from code where `share_key` = #{shareKey}
</delete>
</mapper>
并且!在你的主运行程序Application上增加一个注解:
@SpringBootApplication
@MapperScan("com.hazy.codeshare.dao")//增加此注解
public class CodeshareApplication {
public static void main(String[] args) {
SpringApplication.run(CodeshareApplication.class, args);
}
}
步骤六:编写controller
package com.hazy.codeshare.controller;
import com.hazy.codeshare.dao.CodeMapper;
import com.hazy.codeshare.pojo.CodeShare;
import com.hazy.codeshare.pojo.Msg;
import com.hazy.codeshare.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.io.*;
@RestController
@RequestMapping("")
public class baseController {
//注入redis工具类
@Autowired
private RedisUtil redisUtil;
//注入mapper
@Autowired
private CodeMapper codeMapper;
//当请求为get时说明是查询请求
@GetMapping("/code-share/{shareKey}")
public Msg getCodeContext(@PathVariable("shareKey") String shareKey){
String codeContext = redisUtil.get(shareKey, 0);
if(codeContext != null)
return Msg.success("查询成功!").add("shareKey", codeContext);
else {
String src = "./file/" + shareKey + ".txt";
File file = new File(src);
if(!file.exists()) return Msg.fail("该口令不存在");
FileReader fileReader;
BufferedReader br = null;
try {
fileReader = new FileReader(file);
br = new BufferedReader(fileReader);
StringBuilder sb = new StringBuilder();
String temp;
while ((temp = br.readLine()) != null) {
// 拼接换行符
sb.append(temp + "\n");
}
String js = sb.toString();
redisUtil.set(shareKey, js, 0);
return Msg.success("查询成功!").add("shareKey", js);
}catch (Exception e) {
System.out.println(e.getMessage());
} finally {
if(br != null)
try {
br.close();
}catch (Exception e) {
System.out.println(e.getMessage());
}
}
return Msg.fail("该口令不存在");
}
}
//当请求为post时说明是上传请求
@PostMapping("/code-share/{shareKey}")
public Msg storeCodeContext(@PathVariable("shareKey") String shareKey, @RequestParam("codeContext") String codeContext, @RequestParam("shareDuration")String shareDuration) {
if("".equals(shareKey))
return Msg.fail("口令为空!");
if("".equals(codeContext))
return Msg.fail("代码为空!");
if(redisUtil.get(shareKey,0) != null)
return Msg.fail("口令已被使用!");
try {
redisUtil.set(shareKey, codeContext, 0);
if("permanent".equals(shareDuration)) {
String filePath = "./file/";
File file = new File(filePath);
if(!file.exists()) {
file.mkdirs();
}
filePath = filePath + shareKey + ".txt";
BufferedWriter bw = new BufferedWriter(new FileWriter(filePath));
bw.write(codeContext);
bw.close();
codeMapper.insert(new CodeShare(shareKey, filePath));
}
} catch (Exception e) {
System.out.println(e.getMessage());
return Msg.fail("代码存入失败!");
}
return Msg.success("保存成功,请分享给您的朋友~").add("shareKey", shareKey);
}
//检查code是否已被占用
@GetMapping("/check-code-exist/{shareKey}")
public Msg checkCodeExist(@PathVariable("shareKey") String shareKey){
if("".equals(shareKey))
return Msg.fail("shareKey为空");
boolean exist = redisUtil.exists(shareKey, 0);
if(exist)
return Msg.fail("shareKey已经存在!").add("shareKey", redisUtil.get(shareKey, 0));
else
return Msg.success("shareKey可以使用!");
}
}
测试!完毕!
看到这里,其实你可以依照这个需求,自己写一个相似的网站。因为本人的水平非常差,只是刚看了点SpringBoot的皮毛,想着练习一下,才给自己想了一个需求。如果对你有帮助,那就再好不过。如果没有帮助,可以试着抛开我的代码自己写一个类似的网站!