美文网首页JavaJava学习之路Java 杂谈
一次小意外引发的对@RestController的思考

一次小意外引发的对@RestController的思考

作者: 椰子奶糖 | 来源:发表于2019-08-14 11:14 被阅读86次

    这个小错误是这样的:在连接数据库的时候发现了500错误

    错误页面

    这只是一个小的查询操作,却报了这么多错误日志,这玩意我是没有看出什么所以然来的(大段英文看不懂综合征患者),于是返回去看控制台的错误日志:
    控制台打了那老些日志,还不停地在打....

    2019-08-14 10:30:25.441 ERROR 24380 --- [reate-455005050] com.alibaba.druid.pool.DruidDataSource   : create connection SQLException, url: jdbc:mysql:///testcc, errorCode 0, state 01S00
    
    java.sql.SQLException: The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:73) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:76) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:827) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:447) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:237) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:199) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.alibaba.druid.filter.FilterChainImpl.connection_connect(FilterChainImpl.java:149) ~[druid-1.1.8.jar:1.1.8]
        at com.alibaba.druid.filter.FilterAdapter.connection_connect(FilterAdapter.java:786) ~[druid-1.1.8.jar:1.1.8]
        at com.alibaba.druid.filter.FilterEventAdapter.connection_connect(FilterEventAdapter.java:38) ~[druid-1.1.8.jar:1.1.8]
        at com.alibaba.druid.filter.FilterChainImpl.connection_connect(FilterChainImpl.java:143) ~[druid-1.1.8.jar:1.1.8]
        at com.alibaba.druid.filter.FilterAdapter.connection_connect(FilterAdapter.java:786) ~[druid-1.1.8.jar:1.1.8]
        at com.alibaba.druid.filter.FilterChainImpl.connection_connect(FilterChainImpl.java:143) ~[druid-1.1.8.jar:1.1.8]
        at com.alibaba.druid.filter.stat.StatFilter.connection_connect(StatFilter.java:218) ~[druid-1.1.8.jar:1.1.8]
        at com.alibaba.druid.filter.FilterChainImpl.connection_connect(FilterChainImpl.java:143) ~[druid-1.1.8.jar:1.1.8]
        at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1515) ~[druid-1.1.8.jar:1.1.8]
        at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1578) ~[druid-1.1.8.jar:1.1.8]
        at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2451) ~[druid-1.1.8.jar:1.1.8]
    Caused by: com.mysql.cj.exceptions.InvalidConnectionAttributeException: The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
        at sun.reflect.GeneratedConstructorAccessor35.newInstance(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_201]
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_201]
        at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:85) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.mysql.cj.util.TimeUtil.getCanonicalTimezone(TimeUtil.java:132) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.mysql.cj.protocol.a.NativeProtocol.configureTimezone(NativeProtocol.java:2139) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.mysql.cj.protocol.a.NativeProtocol.initServerSession(NativeProtocol.java:2163) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.mysql.cj.jdbc.ConnectionImpl.initializePropsFromServer(ConnectionImpl.java:1301) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:958) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:817) ~[mysql-connector-java-8.0.17.jar:8.0.17]
        ... 14 common frames omitted
    

    秉着大段文字不看的原则,直接找Caused by这一行,说:时区无法识别什么的,要求配置数据库服务器或者jdbc驱动程序
    懂了,时区不对呗,于是在application.yml中的url改成:

    url: jdbc:mysql:///testcc?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
    

    不但加了时区设置,我还加编码,多查询看你怎么报错

    接下来。。

    可怕的404出现了

    好在这回没有大段大段的日志(庆幸)

    aaaaaaaaaaaaaaa
    id=1
    Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
    log4j:WARN No appenders could be found for logger (druid.sql.Connection).
    log4j:WARN Please initialize the log4j system properly.
    log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    

    前两行是我为了验证有没有进入controller这个方法打印的测试,事实证明,数据是传到了服务器的,是查询数据库出了幺蛾子。
    Loading class com.mysql.jdbc.Driver'. This is deprecated. The new driver class iscom.mysql.cj.jdbc.Driver'. 这行说com.mysql.jdbc.Driver这个驱动已经呗抛弃了,要改成com.mysql.cj.jdbc.Driver驱动WHAT?用了一万年的jdbc驱动竟然也改了,好吧改就改吧

    改完重启,错误页面没变依旧是404

    看日志,刚刚的驱动日志倒是没了剩下的是:

    aaaaaaaaaaaaaaa
    id=1
    log4j:WARN No appenders could be found for logger (druid.sql.Connection).
    log4j:WARN Please initialize the log4j system properly.
    log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    

    官方是这么解释的:

     Why do I see a warning about "No appenders found for logger" and "Please configure log4j properly"?
        This occurs when the default configuration files log4j.properties and log4j.xml can not be found and the application performs no explicit configuration. log4j uses Thread.getContextClassLoader().getResource() to locate the default configuration files and does not directly check the file system. Knowing the appropriate location to place log4j.properties or log4j.xml requires understanding the search strategy of the class loader in use. log4j does not provide a default configuration since output to the console or to the file system may be prohibited in some environments. Also see FAQ: Why can't log4j find my properties in a J2EE or WAR application?.
    

    太长懒得看,而且一般官方写得比较笼统没啥用,这一段日志是warn,是关于druid的,这就标识其实这还不算是大问题,那么为什么我没有查到数据呢?

    • 首先我把sql扔到mysql客户端里面,成功查询,证明sql是对的,那是对象没封装上?
    • 于是我决定换个返回值(原来是返回User整个类,后来返回一个username字符串)


      又是一个错误
    • 好吧连字符串都没有封装上去,证明查询时没问题的,username的值qqq的确时查出来了,应当是数据封装出了毛病,封装应该在。。。。controller这里
    package com.ch.home.controller;
    
    import com.ch.home.bean.User;
    import com.ch.home.mapper.UserMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * Created by CHEN on 2019/8/14.
     */
    //@RestController=@Controller+@ResponseBody
    //@RestController
    @Controller
    public class UserController {
        @Autowired
        UserMapper userMapper;
    
    
        @GetMapping("/user/{id}")
        public String getUserInfo(@PathVariable("id") Integer id){
    
            System.out.println("aaaaaaaaaaaaaaa");
            System.out.println("id="+id );
    //        return userMapper.selectById(id);
            return userMapper.selectNameById(id);
        }
    
    }
    
    • 此处就是解决方法了,找了一圈之后才发现,这边少了个@ResponseBody,没办法将数据转化成正确的格式,加上一切正常~~~
    • 也能封装对象
      image.png
      后来发现加@RestController也好使(事实上一般加的就是这个),那么这俩之间有啥区别呢

    @Controller和@RestController的区别

    事实上@RestController注解相当于@ResponseBody + @Controller合在一起的作用。

    • 使用@Controller 注解,在对应的方法上,视图解析器可以解析return 的jsp,html页面,并且跳转到相应页面
    • 若返回json等内容到页面,则需要加@ResponseBody注解
      1. 如果只是使用@RestController注解Controller,则Controller中的方法无法返回jsp页面,或者html,配置的视图解析器 InternalResourceViewResolver不起作用,返回的内容就是Return 里的内容。
      1. 如果需要返回到指定页面,则需要用 @Controller配合视图解析器InternalResourceViewResolver才行。
        如果需要返回JSON,XML或自定义mediaType内容到页面,则需要在对应的方法上加上@ResponseBody注解。
    • 大概就是这样,要返回Json数据加RestController比较好使,返回页面加Controller比较好使。

    相关文章

      网友评论

        本文标题:一次小意外引发的对@RestController的思考

        本文链接:https://www.haomeiwen.com/subject/ykgwjctx.html