zoukankan      html  css  js  c++  java
  • 记一次SpringBoot 开发中所遇到的坑和解决方法

    记一次SpringBoot 开发中所遇到的坑和解决方法

    mybatis返回Integer为0,自动转型出现空指针异常

    当我们使用Integer去接受数据库中表的数据,如果返回的数据中为0,那么Integer便为null,这时候将Interger自动转型为int,则会出现空指针异常

    这个时候,我们可以在Service层对Integer的数据进行判断,如果为空,就把它赋值为0

    // 在pojo中,如果Integer canJoinNun为null 就把值设置为0
    if (publishMsg.getCanJoinNum() == null) {
       publishMsg.setCanJoinNum(0);
    }

    关于开启druid的监控界面

    maven包的引入:

    <dependency>
       <groupId>org.mybatis.spring.boot</groupId>
       <artifactId>mybatis-spring-boot-starter</artifactId>
       <version>2.0.0</version>
    </dependency>
    <!-- 要引入log4j,不然druid会报错 -->
    <dependency>
       <groupId>log4j</groupId>
       <artifactId>log4j</artifactId>
       <version>1.2.17</version>
    </dependency>

    配置文件:

    spring:
      	datasource:
          url: jdbc:mysql://localhost:3306/test?useAffectedRows=true&allowMultiQueries=true
          username: # 账号
          password: # 密码
          driver-class-name: com.mysql.cj.jdbc.Driver
          platform: mysql
          type: com.alibaba.druid.pool.DruidDataSource
          druid:
             # 下面为连接池的补充设置,应用到上面所有数据源中
             # 初始化大小,最小,最大
             initialSize: 1
             minIdle: 3
             maxActive: 20
             # 配置获取连接等待超时的时间
             maxWait: 60000
             # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
             timeBetweenEvictionRunsMillis: 60000
             # 配置一个连接在池中最小生存的时间,单位是毫秒
             minEvictableIdleTimeMillis: 30000
             validationQuery: select 'x'
             testWhileIdle: true
             testOnBorrow: false
             testOnReturn: false
             # 打开PSCache,并且指定每个连接上PSCache的大小
             #    pool-prepared-statements: true
             #    max-open-prepared-statements: 20
             # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
             filters: stat,wall,log4j
             # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
             connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
             # 配置DruidStatFilter
             web-stat-filter:
             enabled: true
             url-pattern: "/*"
             exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
             # 配置DruidStatViewServlet
             stat-view-servlet:
             enabled: true
             url-pattern: "/druid/*"
             # IP白名单(没有配置或者为空,则允许所有访问)
             #          allow: ****
             # IP黑名单 (存在共同时,deny优先于allow)
             #          deny: ****
             #  禁用HTML页面上的“Reset All”功能
             reset-enable: false
             # 登录名
             login-username: admin
             # 登录密码
             login-password: 123456

    向mysql插入中文字符串,插入成功之后数据显示==?==

    ​ 这个问题有点奇葩,我在本地的manjaro环境中进行开发,插入中文字符串没有问题,但是当我把springboot应用部署到Ubuntu服务器上时,便出现插入中文字符串,最后却显示==?==的情况。

    解决方法:在jdbc的链接后面加上characterEncoding=utf8即可

    jdbc:mysql://localhost:3306/sign_up?useAffectedRows=true&allowMultiQueries=true&characterEncoding=utf8

    ​ 不过,还是不懂为什么在本地不加characterEncoding=utf8也没问题。

    关于跳转的问题

    场景:此时我有一个xxx.com的域名,我用nginx做代理,将xxx.com/project_A/**的请求转到springboot的project_A项目中。这时候我们不可能在每一个路由RequestMapping中,前面都加上一个project_A吧。

    nginx的配置:

    server {
       listen 80;
       server_name xxx.com;
       root /usr/tomcat/webapps;
       charset utf-8;
       location /project_A {
       proxy_pass http://127.0.0.1:8080/project_A;
       proxy_cookie_path /project_A /;
    
       }
    }

    这时候,nginx便会将所有的以==xxx.com/project_A/==转到project_A的项目中。

    那么在前端的thymeleaf中,应该怎么修改呢?

    css引用:使用th:href="@{……}"

    <link rel="stylesheet" th:href="@{/static/css/detail.css}" type="text/css">

    js引用:使用th:src="@{……}"

    <script th:src="@{/static/dist/js/bootstrapValidator.min.js}"></script>

    在ajax请求中,请求路由的写法:

    <script type="text/javascript" th:inline="javascript">
    /*<![CDATA[*/
    $.ajax({
       url: /*[[@{/publish/getContent}]]*/,
       async: false,
       data: form.serialize(),
       complete: function (msg) {
          console.log("完成!");
       },
       success: function (result) {
          console.log(result);	
       }
    })
    /*]]>*/
    </script>

    Tips: js内联代码中需要加入/*<![CDATA[*/……/*]]>*/代码块,thymeleaf才能正确解析一些运算符(<等)和操作符号&/&&等。

    当我们这样使用的时候,他就能够在模板解析的时候自动将project_A,加载在引用的前面。例如:前面的css引用解析的时候就会变成

    <link rel="stylesheet" href="project_A/static/css/detail.css" type="text/css">

    在后端的RequestMapping中,并不需要去修改里面的值,甚至说,return "redirect:/page/index"都不需要去修改。但是,却有一个奇葩,那就是在拦截器中的那个重定向:

    response.sendRedirect("/login/index");

    因为在拦截器中,我们只能够return true或者false,所以我们进行重定向就得使用response.sendRedirect进行重定向,如果我们这样使用,那么它进行重定向就会重定向到xxx.com/login/index去,而不是xxx.com/project_A/login/index

    所以我们不得不更改为response.sendRedirect("/project_A/login/index");

    不过我总感觉应该会有其他方法去解决这个问题,因为这样做的话,一旦更改,就必须得重新改代码或者文件。如果有的话,可以在评论区留言,谢谢。

    数据库的时间问题

    在mybatis中,向数据库插入时间直接使用java.util.Date即可。

    springboot mybatis下划线转驼峰

    本来以为能够自己转的,然后发现自己想多了,╮(╯▽╰)╭

    mybatis:
       #  mapper的位置
       mapper-locations: classpath:mapper/*.xml
       configuration:
          # 开启下划线转驼峰
          map-underscore-to-camel-case: true

    Springboot MySql分页AOP

    场景:有多个网页,但是每个网页的每一页都只显示数据库的10条数据,这个时候我们便需要进行分页。但是如果每次去select数据是,都去写一次分页,这毫无疑问,是一个重复的劳动力。OK,既然OOP是重复的劳动力,那么我们便使用AOP吧。

    maven引入

    <!-- Mybatis分页依赖-->
    <dependency>
       <groupId>com.github.pagehelper</groupId>
       <artifactId>pagehelper-spring-boot-starter</artifactId>
       <version>1.2.10</version>
    </dependency>
    <!--springboot的AOP-->
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

    MyService获得数据里面的数据

       // Mapper
       @Autowired
       private GetMsgMapper getMsgMapper;
    
       @Override
       public Object getJoinMsgsWithPage(Integer page, String id) {
          return getMsgMapper.getJoinMsgs(id);
       }

    切面的写法

    @Component 	// 注入到IOC容器里面
    @Aspect		//是之成为切面类
    public class PageSql {
    
       // 定义每页拿出多少数据
       public static final Integer PAGE_NUM = 10;
       
       // 切入的点 切com.xxx.service.serviceImpl包下所有类中以WithPage结尾的方法
       @Pointcut("execution(public * com.xxx.service.serviceImpl.*.*WithPage(..))")
       public void serviceFindFunction() {
       }
    
       @Around("serviceFindFunction()")
       public Object serviceImplAop(ProceedingJoinPoint point) throws Throwable {
          // 获得切入点的参数
          Object[] args = point.getArgs();
          // 在我的使用中,第一个参数是page,也就是取第几页的数据
          PageHelper.startPage((Integer) args[0], PAGE_NUM);
          // 执行原来的方法得到数据
          Object object = point.proceed(args);
          // 假如拿到的数据是List的这种类型,则就进行分页,否则就直接返回
          if (object instanceof List) {
             List objList = (List) object;
             PageInfo pageInfo = new PageInfo<>(objList);
             return pageInfo;
          }
          return object;
       }
    }
    

    这样,当我们在Controller里面去调用的时候就很爽了

    调用示例:

    PageInfo pageInfo = (PageInfo)MyService.getJoinMsgsWithPage(1, "8888");

    在这里面,返回的pageInfo就是已经经过分页的数据了。

    自己蠢了的地方 404 NOT FOUND

    在将springboot项目部署到服务器上面的时候,刚开始只想试试能不能够部署成功,然后就暂时没有将本地的数据库部署上去。再然后,就陷入了为啥本地能运行而远端不能运行的死循环了。到后面才发现,因为无法链接数据库,project都没有启动。╮(╯▽╰)╭

     

    img
    img
  • 相关阅读:
    H5页面开发的touchmove事件
    css奇技淫巧—border-radius
    css奇技淫巧—box-shadow与outline绘制多重边框效果
    移动前端自适应解决方案和比较
    rem字体在rem盒子里面不一样,或者不同的行解决
    rem 回家测试
    js中函数提升及var变量提示
    盒子模型的百分比是根据什么来的
    $(function(){})返回值$(document)
    开发过程中错误总结
  • 原文地址:https://www.cnblogs.com/xiaohuiduan/p/10743718.html
Copyright © 2011-2022 走看看