前后端分离,前端使用Vue,后端使用SpringBoot,适合作为前后端联调的新手项目。
个人代码地址:https://github.com/coder-zrl/vueblog/
收获
不足
依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-freemarkerartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.2.0version>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-generatorartifactId>
<version>3.2.0version>
dependency>
启动类
package com.example;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
// 演示例子,执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
public class CodeGenerator {
/**
*
* 读取控制台内容
*
*/
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("请输入" + tip + ":");
System.out.println(help.toString());
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotEmpty(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");
// gc.setOutputDir("D:\\test");
gc.setAuthor("coder-zrl");
gc.setOpen(false);
// gc.setSwagger2(true); 实体属性 Swagger2 注解
gc.setServiceName("%sService");
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/vueblog?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("422518");
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName(null);
pc.setParent("com.example");
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
// 如果模板引擎是 freemarker
String templatePath = "/templates/mapper.xml.ftl";
// 如果模板引擎是 velocity
// String templatePath = "/templates/mapper.xml.vm";
// 自定义输出配置
List<FileOutConfig> focList = new ArrayList<>();
// 自定义配置会被优先输出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
return projectPath + "/src/main/resources/mapper/"
+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
// 配置自定义输出模板
//指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
// templateConfig.setEntity("templates/entity2.java");
// templateConfig.setService();
// templateConfig.setController();
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setSuperEntityClass("com.example.entity.BaseEntity");
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);
strategy.setSuperControllerClass("com.example.controller.BaseController");
strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
strategy.setSuperEntityColumns("id", "created", "modified", "status");
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}
在对应包下写上BaseEntity、BaseController这两个类
BaseEntity:
@Data
public class BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private Date created;
private Date modified;
}
BaseController:
public class BaseController {
@Autowired
HttpServletRequest req;
}
复制代码
原来返回一种数据类型到前端,只要这个类继承了Serializable他的数据就会自动拆解为json
可以返回Object类型到前端
一种意识:方法重载时方法之间要学会调用,将数据多层封装
public static Result fail(String msg) {
return fail(400,msg,null);
}
public static Result fail(String msg,Object data) {
return fail(400,msg,data);
}
public static Result fail(int code,String msg,Object data) {
Result r = new Result();
r.setCode(code);
r.setMsg(msg);
r.setData(data);
return r;
}
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET","HEAD","POST","PUT")
.allowCredentials(true)
.allowedHeaders("*");
}
}
对实体类的对应字段添加@JsonFormat(pattern=“yyyy-MM-dd”)注解
例如时间2021-01-10T07:21:45.000+00:00
变成了2021-01-10
下载node.js
进入官网https://nodejs.org/zh-cn/下载长期支持版并安装
设置淘宝源
换源之后安装速度会很快,命令行键入
npm install -g cnpm --registry=https://registry.npm.taobao.org
安装vue
命令行键入
cnpm install vue
启动vue ui并创建vue
命令行输入vue ui
如果没反应就是版本太低,输入这行代码cnpm i -g @vue/cli
如果显示vue无法加载文件就管理员身份运行PowerShell,输入set-ExecutionPolicy RemoteSigned
在输入A
Ider安装vue.js插件,电脑下载element-ui和axios
cnpm install element-ui -S
cnpm install axios -S # 与ajax类似,但是基于xxx
引入模块
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import axios from 'axios'
全局使用
Vue.app文件中输入
Vue.use(Element)
Vue.prototype.$axios = axios
启动
npm run serve # 也可以自己给idea配置npm,然后点击右上角的播放即可
进入router文件夹下的index.js
引入写好的vue界面
编写路由配置
import Login from '../views/Login.vue'
import Blogs from '../views/Blogs.vue'
import BlogDetail from '../views/BlogDetail.vue'
import BlogEdit from '../views/BlogEdit.vue'
const routes = [
{
path: '/',//主页面
name: 'Index',
redirect: {name: "Blogs"}//页面重定向到Blogs
},
{
path: '/blogs',
name: 'Blogs',
component: Blogs
},
{
path: '/blog/add',//这个一定要放在下面这个路由之前,因为否则会把add作为参数传到下面去
name: 'BlogEdit',
component: BlogEdit
},
{
path: '/blog/:blogId',
name: 'BlogDetail',
component: BlogDetail
},
{
path: '/blog/:blogId/edit',//此时blogId就会作为一个参数,页面可以获取
name: 'BlogEdit',
component: BlogEdit
},
]
vue文件下的template只能有一个标签,最好是div标签,多个是不可以的
App.vue文件的内容是全局设置的,包括布局
提交表单数据
vue的数据是双向数据绑定的,ruleForm中包含两个表单字段(用name区分)
ruleForm: {
username: '',
password: ''
}
then是的得到结果后怎么办
this.$axios.post('http://localhost:8080/login',this.ruleForm()).then(res => {
console.log(res)
})
store文件夹下的index.js中state的参数是全局可以使用的,牵一发而动全身
_this.$store.commit(“SET_USERINFO”,userInfo)//调用方法
console.log(_this.$store.getters.GET_USERINFO)
_this.route.push(’/blogs’)//跳转
通常情况下,通用的页面事放在components文件夹下的,此时在需要的文件下的scrip代码中import,然后再在default中注册components,然后就能使用Header标签作为这个页面的一部分了
<script>
//导入头部
import Herder from "@/components/Herder";
export default {
name: "Blogs.vue",
components:{Herder},
}
</script>
安装编辑器
cnpm i mavon-editor -S
main.js进行全局注册
// 全局注册
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
// use
Vue.use(mavonEditor)
页面解析md为html
# 用于解析md文档
cnpm i markdown-it -S
# md样式
cnpm i github-markdown-css -S
渲染内容为html格式
var MarkdownIt = require('markdown-it')
var md = new MarkdownIt()
var result = md.render(blog.content)
_this.blog.content = result
script中引入markdown渲染css格式
import 'github-markdown-css'
内容添加标签