vue+quasar+electron+springboot+mysql撸一个TODO LIST 看板
先看效果
写本项目的目的有几点:
- 学习下vue+electron桌面开发
- 学习下java和spring开发(本人一直使用PHP)
- 一直缺少一款能适合自己的TODO LIST软件,能有桌面端的
可直接打包成dmg、exe 等二进制文件使用。
这是我打包后的效果。
技术栈
- vue
- quasar
- electron
- springboot
- mysql
部分后端知识
自定义注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired {
}
自定义一个loginRequired
注解,标注是否需要登录
然后在拦截器里进行全局检测
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
LoginRequired classRequired = method.getDeclaringClass().getAnnotation(LoginRequired.class);
// 判断接口是否需要登录
LoginRequired methodRequired = method.getAnnotation(LoginRequired.class);
if (classRequired == null && methodRequired == null) {
return true;
}
appService.initSession(); //token 方式验证
if (request.getSession().getAttribute(App.SESSION_USER) != null) {
return true;
}
@RestControllerAdvice
利用@RestControllerAdvice注解进行全局控制器异常拦截
/**
* ConstraintViolationException
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Response handleConstraintViolationException(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getAllErrors().forEach((error) -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});
return new Response(ResponseRet.parametrErrror, "参数错误", errors);
}
/**
* 违反约束异常 字段不为空等
*
* @param ex
* @return
*/
@ExceptionHandler(ConstraintViolationException.class)
public Response handHibernateException(ConstraintViolationException ex) {
return new Response(ResponseRet.dbExecuteFail, ex.getSQLException().toString());
}
@ExceptionHandler(GenericJDBCException.class)
public Response handGenericJDBCException(GenericJDBCException ex) {
return new Response(ResponseRet.dbExecuteFail, ex.getSQLException().toString());
}
你可以全局处理entity定义的参数约束,或其他异常。
p6spy记录sql和耗时
@Override
public void onAfterExecuteQuery(PreparedStatementInformation statementInformation, long timeElapsedNanos, SQLException e) {
App.sqlCount.set(App.sqlCount.get() + 1);
Long duration = timeElapsedNanos / 1000000;
App.sqlDuration.set(App.sqlDuration.get() + duration);
Log.info(String.format("执行sql || %s 耗时 %s ms", statementInformation.getSqlWithValues(), duration));
}
@Override
public void onAfterExecuteUpdate(PreparedStatementInformation statementInformation, long timeElapsedNanos, int rowCount, SQLException e) {
App.sqlCount.set(App.sqlCount.get() + 1);
Log.info(App.sqlCount.get().toString());
Long duration = timeElapsedNanos / 1000000;
App.sqlDuration.set(App.sqlDuration.get() + duration);
String singleLineSql = statementInformation.getSqlWithValues().replaceAll("\n", "\\\\n");
Log.info(String.format("执行sql || %s 耗时 %s ms", singleLineSql, duration));
}
记录带所有参数的sql和执行耗时
继承DispatcherServlet记录请求参数
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
//创建一个 json 对象,用来存放 http 日志信息
ObjectNode rootNode = mapper.createObjectNode();
rootNode.put("uri", requestWrapper.getRequestURI());
rootNode.put("clientIp", requestWrapper.getRemoteAddr());
// rootNode.set("requestHeaders", mapper.valueToTree(getRequestHeaders(requestWrapper)));
String method = requestWrapper.getMethod();
String contentType = requestWrapper.getContentType();
rootNode.put("method", method);
try {
super.doDispatch(requestWrapper, responseWrapper);
} finally {
if (method.equals("GET") || method.equals("DELETE")) {
rootNode.set("request", mapper.valueToTree(requestWrapper.getParameterMap()));
} else if (contentType.equals("application/x-www-form-urlencoded")) {
rootNode.set("request", mapper.valueToTree(requestWrapper.getParameterMap()));
} else {
JsonNode newNode = mapper.readTree(requestWrapper.getContentAsByteArray());
rootNode.set("request", newNode);
}
rootNode.put("status", responseWrapper.getStatus());
JsonNode newNode = mapper.readTree(responseWrapper.getContentAsByteArray());
rootNode.set("response", newNode);
responseWrapper.copyBodyToResponse();
// rootNode.set("responseHeaders", mapper.valueToTree(getResponsetHeaders(responseWrapper)));
Log.info(rootNode.toString());
}
}
源码地址
- 前端 https://github.com/visonforcoding/carambola-todo
- 后端 https://github.com/visonforcoding/carambola-todo-service
vue+quasar+electron+springboot+mysql撸一个TODO LIST 看板的更多相关文章
- vue+nodejs+express+mysql 建立一个在线网盘程序
vue+nodejs+express+mysql 建立一个在线网盘程序 目录 vue+nodejs+express+mysql 建立一个在线网盘程序 第一章 开发环境准备 1.1 开发所用工具简介 1 ...
- Vue.js 入门:从零开始做一个极简 To-Do 应用
Vue.js 入门:从零开始做一个极简 To-Do 应用 写作时间:2019-12-10版本信息:Vue.js 2.6.10官网文档:https://cn.vuejs.org/ 前言 学习 Vue ...
- 纯手工撸一个vue框架
前言 vue create 真的很方便,但是很多人欠缺的是手动撸一遍.有些人离开脚手架都不会开发了. Vue最简单的结构 步骤 搭建最基本的结构 打开空文件夹,通过 npm init 命令生成pack ...
- 看了 Spring 官网脚手架真香,也撸一个 SpringBoot DDD 微服务的脚手架!
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 为什么我们要去造轮子? 造轮子的核心目的,是为了解决通用共性问题的凝练和复用. 虽然 ...
- 用SpringBoot+MySql+JPA实现对数据库的增删改查和分页
使用SpringBoot+Mysql+JPA实现对数据库的增删改查和分页 JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述 ...
- 用初中数学知识撸一个canvas环形进度条
周末好,今天给大家带来一款接地气的环形进度条组件vue-awesome-progress.近日被设计小姐姐要求实现这么一个环形进度条效果,大体由四部分组成,分别是底色圆环,进度弧,环内文字,进度圆点. ...
- 手把手教你用netty撸一个ZkClient
原文地址: https://juejin.im/post/5dd296c0e51d4508182449a6 前言 有这个想法的缘由是前一阵子突发奇想, 想尝试能不能直接利用js连接到zookeeper ...
- 超详细,新手都能看懂 !使用SpringBoot+Dubbo 搭建一个简单的分布式服务
来自:JavaGuide Github 地址:https://github.com/Snailclimb/springboot-integration-examples 目录: 使用 SpringBo ...
- 使用 SpringBoot+Dubbo 搭建一个简单分布式服务
实战之前,先来看几个重要的概念 开始实战之前,我们先来简单的了解一下这样几个概念:Dubbo.RPC.分布式.由于本文的目的是带大家使用SpringBoot+Dubbo 搭建一个简单的分布式服务,所以 ...
随机推荐
- React Hooks & Context API
React Hooks & Context API responsive website https://reactjs.org/docs/hooks-reference.html https ...
- nodejs 查看进程表
psaux tasklist system-tasks const { exec } = require("child_process"); const isWindows = p ...
- node初体验(二)
1.静态资源访问,需要设置路由和响应标头 2.url模块.path模块.querystring模块 Url { protocol: null, slashes: null, auth: null, h ...
- @RestController和@Controller
1.使用@Controller 注解,在对应的方法上,视图解析器可以解析return 的jsp,html页面,并且跳转到相应页面 若返回json等内容到页面,则需要加@ResponseBody注解 2 ...
- 谈一下HashMap的底层原理是什么?
底层原理:Map + 无序 + 键唯一 + 哈希表 (数组+Entry)+ 存取值 1.HashMap是Map接口的实现类.实现HashMap对数据的操作,允许有一个null键,多个null值. Co ...
- eclipse输入时自动提示
当输入一部分代码时,其他的候选代码提示出来,可以提高开发的效率,设置方法如下: 选择Window -> Perferences -> Java -> Editor -> Con ...
- ALGO基础(一)—— 排序
ALGO基础(一)-- 排序 冒选插希快归堆,以下均为从小到大排 1 冒泡排序 描述: 比较相邻的元素.如果第一个比第二个大,就交换它们两个: 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一 ...
- KDE 桌面不显示背景和状态栏
在arch的一次更新后,kde的桌面背景,插件,状态栏变成了一片黑,如下图所示. 解决办法:删除/home/stone/.config/plasma-org.kde.plasma.desktop-ap ...
- 记录PHP post提交表单导入mysql中文乱码的问题
记录记录PHP post提交表单导入mysql中文乱码的问题 关于乱码,这是个糟糕的问题!涉及到很多地方 解决思路:程序所涉及的环境字符集不一致导致 mysql出现乱码一般是mysql数据库内部的字符 ...
- 漏洞复现-ActiveMq任意文件写入漏洞(CVE-2016-3088)
0x00 实验环境 攻击机:Win 10 靶机也可作为攻击机:Ubuntu18 (docker搭建的vulhub靶场) 0x01 影响版本 未禁用PUT.MOVE等高危方法的ActiveM ...