错误总结--SpringBoot--1

1.:Required request body is missing 及HttpServletRequestWrapper的使用

SpringBoot的Controller中,由于新添加的Filter中对请求流的处理,导致json解析失败,Required request body is missing的错误。

错误场景

1.新增的filter

package com.nt.demo.config.filters;

import com.nt.demo.config.wrapper.WrapperServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Create by TaoTaoNing
 * 2019/7/3
 **/
@Slf4j
@Order(0)
@WebFilter(urlPatterns = "/*", filterName = "loginFilter")
public class LoginFilter implements Filter {
    private static final String SESSION_TOKEN = "user_name";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info(this.getClass().getSimpleName() + " -- " + "is init ------");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info(servletRequest.getContentType());
        HttpServletResponse servletResponse1 = (HttpServletResponse) servletResponse;
        servletResponse1.setHeader("ningtao", "test_header");

// 从这里开始是导致错误的原因
        BufferedReader br = new BufferedReader(new InputStreamReader(servletResponse1 .getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        // readLine自带flush效果
        while ((line = br.readLine()) != null) {
            System.out.println(line);
            sb.append(line);
        }
        System.out.println(sb.toString());
        filterChain.doFilter(servletResponse1 , servletResponse);
    }

    @Override
    public void destroy() {
        log.info(this.getClass().getSimpleName() + " -- " + "is destroy ------");

    }
}

2.Controller

package com.nt.demo.controller;

import com.nt.demo.entity.UserDTO;
import com.nt.demo.intf.TestService;
import com.nt.demo.pojo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

/**
 * Create by TaoTaoNing
 * 2019/7/4
 **/
@Slf4j
@RestController
@RequestMapping("/core")
public class CoreController {

    @Reference
    private TestService testService;

    @PostMapping("/login")
    public String checkLogin(@RequestBody @Valid UserVO userVO, BindingResult errors){

        log.info(userVO.toString());

        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(userVO,userDTO);
        UserDTO userDTO1 = testService.selectUser(userDTO);
        if (null != userDTO1){
            return "success";
        }
        return "fail";
    }

}

3.运行结果:

{
    "timestamp": "20190724151800",
    "status": 400,
    "error": "Bad Request",
    "message": "Required request body is missing: public java.lang.String com.nt.demo.controller.CoreController.checkLogin(com.nt.demo.pojo.UserVO,org.springframework.validation.BindingResult)",
    "trace": "org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public java.lang.String com.nt.demo.controller.CoreController.checkLogin(com.nt.demo.pojo.UserVO,org.springframework.validation.BindingResult)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:160)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:130)\r\n\tat org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:126)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)\r\n\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)\r\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)\r\n\tat org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:660)\r\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:741)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat com.nt.demo.config.filters.LoginFilter.doFilter(LoginFilter.java:53)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200)\r\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)\r\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)\r\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)\r\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\r\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)\r\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)\r\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)\r\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)\r\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:836)\r\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1747)\r\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\r\n\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)\r\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)\r\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n\tat java.lang.Thread.run(Thread.java:748)\r\n",
    "path": "/demo/core/login"
}

改正

  1. 新增请求包装类
package com.nt.demo.config.wrapper;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;

/**
 * Create by TaoTaoNing
 * 2019/7/24
 * 这个类的作用相当于将请求流中的信息保存起来,后续的对请求流的操作都使用该对象获取流
 * 可以达到类似请求流复制的效果,可以有效避免controller中参数封装之前,请求流中信息就已经被读取出来,
 * 抛出:Required request body is missing  异常
 **/
@Slf4j
public class WrapperServletRequest extends HttpServletRequestWrapper {

    private byte[] buffer;

    public WrapperServletRequest(HttpServletRequest request) {
        super(request);
        try {
            // 读取输入流里面的参数,保存到buff 缓存中
            buffer = IOUtils.toByteArray(request.getInputStream());
        } catch (IOException e) {
            log.error(e.getMessage());
        }
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        return new BufferedServletInputStream(this.buffer);
    }

    class BufferedServletInputStream extends ServletInputStream {

        private ByteArrayInputStream byteArrayInputStream;
        private boolean isFinished = false;

        public BufferedServletInputStream(byte[] buffer) {
            this.byteArrayInputStream = new ByteArrayInputStream(buffer);
        }

        @Override
        public int available() throws IOException {
            return byteArrayInputStream.available();
        }

        @Override
        public int read() {
            int read = byteArrayInputStream.read();
            if (-1 == read) {
                isFinished = true;
            }
            return read;
        }

        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            int read = byteArrayInputStream.read(b, off, len);
            if (-1 == read) {
                isFinished = true;
            }
            return read;
        }

        @Override
        public void setReadListener(ReadListener readListener) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean isReady() {
            return true;
        }

        @Override
        public boolean isFinished() {
            return isFinished;
        }


    }

}

  1. filter修正
package com.nt.demo.config.filters;

import com.nt.demo.config.wrapper.WrapperServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Create by TaoTaoNing
 * 2019/7/3
 **/
@Slf4j
@Order(0)
@WebFilter(urlPatterns = "/*", filterName = "loginFilter")
public class LoginFilter implements Filter {
    private static final String SESSION_TOKEN = "user_name";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info(this.getClass().getSimpleName() + " -- " + "is init ------");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info(servletRequest.getContentType());
        HttpServletResponse servletResponse1 = (HttpServletResponse) servletResponse;
        servletResponse1.setHeader("ningtao", "test_header");
        WrapperServletRequest wrapperServletRequest = null;
        // 关于请求包装流的使用
        if (servletRequest instanceof HttpServletRequest){

            HttpServletRequest servletRequest1 = (HttpServletRequest) servletRequest;
            wrapperServletRequest = new WrapperServletRequest(servletRequest1);

        }

        BufferedReader br = new BufferedReader(new InputStreamReader(wrapperServletRequest.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            System.out.println(line);
            sb.append(line);
        }
        System.out.println(sb.toString());
        filterChain.doFilter(wrapperServletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        log.info(this.getClass().getSimpleName() + " -- " + "is destroy ------");

    }
}

SpringBoot–整合–Mybatis错误:

"org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: \r\n### Error updating database. Cause: java.lang.NullPointerException\r\n### The error may exist in file [G:\code\springboot-dubbo-demo\springboot-dubbo-demo1\springboot-dubbo-provider\target\classes\mapper\EmpMapper.xml]

这个错误困扰我很久,对比了数据库中表字段和基本类字段没有问题,mapper.xml也没有问题,但是一直报这个错误,最后由重新建一个项目运行正常对比出来原因:

使用这个数据源就一直报nullpointexception:
spring.datasource.type=org.apache.ibatis.datasource.pooled.PooledDataSource

切换为另外的数据源:
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
或者阿里的druid(需要引入jar包):
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
之后正常了。。

总结

一开始一直以为是json解析有问题,最后才找到真正错误的原因。关于请求参数的整个解析流程还是不熟悉,需要继续学习:HttpMessageConverter。

关于将mysql 驱动mysql-connector-java.jar由5.xx版本升级到8.xxxx版本的time zone 问题:The server time zone value ’ xxx ’ is unrecognized or represents more than one time zone

法一:

# url加上时区 serverTimezone=GMT (或者UTC)
spring.datasource.url=jdbc:mysql://localhost:3306/nt?serverTimezone=GMT

法二:
连接上mysql,执行命令:

mysql> show variables like '%time_zone';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone |        |
| time_zone        | SYSTEM |
+------------------+--------+
2 rows in set, 3 warnings (0.01 sec)

mysql> set global time_zone='+8:00';

参考链接:csdn-华仔的博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值