zoukankan      html  css  js  c++  java
  • vue+quasar+electron+springboot+mysql撸一个TODO LIST 看板

    先看效果

    写本项目的目的有几点:

    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");
            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());
            }
        }
    

    源码地址

  • 相关阅读:
    poj 1475 Pushing Boxes 推箱子(双bfs)
    poj 1806 Frequent values(RMQ 统计次数) 详细讲解
    poj 2846 Repository
    poj Ping pong LA 4329 (树状数组统计数目)
    POJ 1962-Corporative Network (并查集)
    hdu 2217 Visit
    nyoj304 节能
    与R纠缠的两件事——rownames和子集--转载
    七步精通Python机器学习--转载
    win10专业版激活(亲测可用)
  • 原文地址:https://www.cnblogs.com/maitian2013/p/14636632.html
Copyright © 2011-2022 走看看