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 搭建一个简单的分布式服务,所以 ...
随机推荐
- component & slot
component & slot <template> <div class="myHeaderContainer"> <header cla ...
- redux & dispatch & payload
redux & dispatch & payload react & react-redux & redux-saga // contrast dispatch({ t ...
- CSS Dark Mode
CSS Dark Mode https://kevq.uk/automatic-dark-mode/ https://kevq.uk/how-to-add-css-dark-mode-to-a-web ...
- 炒币亏损一万美金?不如抢SPC空投!
币圈的市场可以用风云变幻来形容,1月9日的时候比特币震荡,其他币种争先上涨,连平时都不涨的币种都拉出了10%-20%的领先涨幅,市场惊呼牛市来了,但喜悦还没有维持一天,1月10日(昨天)市场就走向另一 ...
- 「NGK每日快讯」12.2日NGK公链第29期官方快讯!
- SpringBoot2.1中添加过滤器配置
1:构造一个实现 Filter 接口的过滤器,并在类上添加@component注释: notice1:若不添加,则需在spring中注入该bean,不然会报错. package com.dev.fil ...
- Flannel和Calico网络插件工作流程对比
Flannel和Calico网络插件对比 Calico简介 Calico是一个纯三层的网络插件,calico的bgp模式类似于flannel的host-gw Calico方便集成 OpenStac ...
- Linux graphics stack
2D图形架构 早期Linux图形系统的显示全部依赖X Server,X Client调用Xlib提供的借口向 X Server发送渲染命令,X Server根据 X Client的命令请求向硬件设备绘 ...
- 后端程序员之路 48、memcached
memcached - a distributed memory object caching systemhttp://memcached.org/ Memcached 教程 | 菜鸟教程http: ...
- selenium之元素定位的方法(一)
WebDriver 对象有多种方法用于在页面中寻找元素.他们被分成find_element_*和find_elements_*方法.find_element_*方法返回一个WebElement对象,代 ...