先看效果

写本项目的目的有几点:

  1. 学习下vue+electron桌面开发
  2. 学习下java和spring开发(本人一直使用PHP)
  3. 一直缺少一款能适合自己的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());
}
}

源码地址

vue+quasar+electron+springboot+mysql撸一个TODO LIST 看板的更多相关文章

  1. vue+nodejs+express+mysql 建立一个在线网盘程序

    vue+nodejs+express+mysql 建立一个在线网盘程序 目录 vue+nodejs+express+mysql 建立一个在线网盘程序 第一章 开发环境准备 1.1 开发所用工具简介 1 ...

  2. Vue.js 入门:从零开始做一个极简 To-Do 应用

    Vue.js 入门:从零开始做一个极简 To-Do 应用 写作时间:2019-12-10版本信息:Vue.js 2.6.10官网文档:https://cn.vuejs.org/ 前言  学习 Vue ...

  3. 纯手工撸一个vue框架

    前言 vue create 真的很方便,但是很多人欠缺的是手动撸一遍.有些人离开脚手架都不会开发了. Vue最简单的结构 步骤 搭建最基本的结构 打开空文件夹,通过 npm init 命令生成pack ...

  4. 看了 Spring 官网脚手架真香,也撸一个 SpringBoot DDD 微服务的脚手架!

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 为什么我们要去造轮子? 造轮子的核心目的,是为了解决通用共性问题的凝练和复用. 虽然 ...

  5. 用SpringBoot+MySql+JPA实现对数据库的增删改查和分页

    使用SpringBoot+Mysql+JPA实现对数据库的增删改查和分页      JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述 ...

  6. 用初中数学知识撸一个canvas环形进度条

    周末好,今天给大家带来一款接地气的环形进度条组件vue-awesome-progress.近日被设计小姐姐要求实现这么一个环形进度条效果,大体由四部分组成,分别是底色圆环,进度弧,环内文字,进度圆点. ...

  7. 手把手教你用netty撸一个ZkClient

    原文地址: https://juejin.im/post/5dd296c0e51d4508182449a6 前言 有这个想法的缘由是前一阵子突发奇想, 想尝试能不能直接利用js连接到zookeeper ...

  8. 超详细,新手都能看懂 !使用SpringBoot+Dubbo 搭建一个简单的分布式服务

    来自:JavaGuide Github 地址:https://github.com/Snailclimb/springboot-integration-examples 目录: 使用 SpringBo ...

  9. 使用 SpringBoot+Dubbo 搭建一个简单分布式服务

    实战之前,先来看几个重要的概念 开始实战之前,我们先来简单的了解一下这样几个概念:Dubbo.RPC.分布式.由于本文的目的是带大家使用SpringBoot+Dubbo 搭建一个简单的分布式服务,所以 ...

随机推荐

  1. WEB 面向开发者的结构化数据

    通常用于google搜索 See also: video 探索搜索库

  2. ffmpeg concat设置绝对路径

    https://superuser.com/questions/718027/ffmpeg-concat-doesnt-work-with-absolute-path/1551017#1551017 ...

  3. 开源OA办公系统的“应用市场”,能够为协同办公开拓什么样的“前路”?

    在我们的日常生活中,应用市场这个词,总是与智能手机划上等号,不管使用的是iPhone还是安卓,总会接触到手机上的APP应用市场,我们可以在应用市场中,选择自己所需要的APP应用软件,下载使用后,可以让 ...

  4. DCL之单例模式

    所谓的DCL 就是 Double Check Lock,即双重锁定检查,在了解DCL在单例模式中如何应用之前,我们先了解一下单例模式.单例模式通常分为"饿汉"和"懒汉&q ...

  5. 手把手教你手写一个最简单的 Spring Boot Starter

    欢迎关注微信公众号:「Java之言」技术文章持续更新,请持续关注...... 第一时间学习最新技术文章 领取最新技术学习资料视频 最新互联网资讯和面试经验 何为 Starter ? 想必大家都使用过 ...

  6. 一次Ubuntu16.04 虚拟机挂起,ping不到网络引发的思考

    虚拟机挂起 无网络 情况复现 can@ubuntu:~$ ping www.baidu.com ping: unknown host www.baidu.com 挂起重开虚拟机,遇到无网络状态: 首先 ...

  7. 图文详解:阿里宠儿【小兔】RabbitMQ的养成攻略

  8. E: Some index files failed to download. They have been**

    转: E: Some index files failed to download. They have been** 问题描述: 当使用Dockerfile从包含cuda的镜像建立新的image的时 ...

  9. [MIT 18.06 线性代数]Intordution to Vectors向量初体验

    目录 1.1. Vectors and Linear Combinations向量和线性组合 REVIEW OF THE KEY IDEAS 1.2 Lengths and Dot Products向 ...

  10. Git使用的常用场景

    场景一 小张作为一个开发人员,刚进团队,发现团队是使用git进行代码管理的,现在需要去初始化团队的代码仓库以及新增提交自己修改的一部分代码 1.克隆远程仓库 git clone <ssh> ...