zoukankan      html  css  js  c++  java
  • Spring Boot学习随记

    由于早年在管理领域耕耘了一段时间,完美错过了Spring的活跃期,

    多少对这个经典的技术带有一种遗憾的心态在里面的,

    从下面的我的生涯手绘图中大概可以看出来我的经历。

    最近由于新介入到了工业数字化领域,工作也专注于业务应用,

    不怎么搞平台了,平台更多的是采取与友商战略合作的方式,

    也有机会重新认识并学习一下这个被完美错过的经典技术。

    以下是本次的随记。

    一、本次的代码地址

    https://github.com/quchunhui/demo-macket/tree/master/springboot

    二、一个简单的需求场景

    1)  从云平台按照一定频率拉取数据(每次间隔5秒)。

    2)  将待获取的数据保存至本地数据库(MySQL)。

    3)提供可视化web页面供查看流转数据状态。

    4)  由DView工业软件从数据库中拉取数据(每次间隔5秒)。

    5)  按照一定数量间隔向PLC下发加工数据(每次5个)。

    其中,红色字体部分,为本次随记的范围。

    三、学习书籍

    我本在在正式开始学习及开发之前,通过书籍和付费视频对Spring boot进行了简单扫盲

    学习的书籍为:《Spring 5企业级开发实战》

    学习的收费视频为:极客时间《Spring全家桶》

    书籍可以采用快速阅读的方式进行框架性学习

    视频可以采用2倍速,按照需要先挑选部分模块学习

    四、学习笔记

    ===初始化工程===

    https://start.spring.io/

    可以通过这个地址初始化工程

    也可以通过IDEA的Spring initializr来进行初始设计。

    可以选择一下组件:

    Developer Tools

    →Lombok

    →Spring Configuration Processor

    Web

    →Spring Web

    SQL

    →Spring Boot JPA

    →MySQL Driver

    Ops

    →Spring Boot Actuator

    ===spring boot actuator===

    用于健康检查的模块,可以考虑引入进来。

    ===lombok===

    Lombok想要解决了的是在我们实体Bean中大量的Getter/Setter方法,以及toString,hashCode等可能不会用到,

    在使用Lombok之后,将由其来自动帮你实现代码生成,注意,其是 在运行过程中,帮你自动生成的 。就是说,将极大减少你的代码总量。

    ===JDBC与JPA区别===

    1.定义

    JDBC提供一种接口,它是由各种数据库厂商提供类和接口组成的数据库驱动,为多种数据库提供统一访问。我们使用数据库时只需要调用JDBC接口就行了。

    JDBC的用途:与数据库建立连接、发送操作数据库的语句并处理结果。

    JPA是Java持久层API。它是对java应用程序访问ORM(对象关系映射)框架的规范。为了我们能用相同的方法使用各种ORM框架。

    JPA用途:简化现有Java EE和Java SE应用开发工作;整合ORM技术。

    2.不同点:

    1)使用的sql语言不同:
    JDBC使用的是基于关系型数据库的标准SQL语言
    JPA通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
    2)操作的对象不同:
    JDBC操作的是数据,将数据通过SQL语句直接传送到数据库中执行:
    JPA操作的是持久化对象,由底层持久化对象的数据更新到数据库中。
    3)数据状态不同:
    JDBC操作的数据是“瞬时”的,变量的值无法与数据库中的值保持一致;
    JPA操作的数据时可持久的,即持久化对象的数据属性的值是可以跟数据库中的值保持一致的。

    ===mvn package报错===

    错误日志

    Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
    

    问题原因:

    Mybatis没有找到合适的加载类,其实是大部分spring - datasource - url没有加载成功,

    解决办法:
    在application.propertier中增加如下代码之后,编译通过。

    spring.datasource.url=jdbc:mysql://localhost:3306/read_data?useUnicode=true&characterEncoding=UTF-8&useSSL=false
    spring.datasource.username: root
    spring.datasource.password: 123456
    spring.datasource.driver-class-name: com.mysql.jdbc.Driver
    

      

    参考博客:

    https://www.cnblogs.com/wuxiang12580/archive/2019/01/25/10319914.html

    ===运行报错===

    错误日志

    com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
    

      

    问题原因:

    数据库连接相关的配置不正确,连接不上数据库

    解决办法:

    application.propertier中的数据库连接信息修改为正确的即可。修改后如下:

    spring.datasource.url=jdbc:mysql://localhost:3306/visual?useUnicode=true&characterEncoding=UTF-8&useSSL=false
    spring.datasource.username: root
    spring.datasource.password: 123456
    spring.datasource.driver-class-name: com.mysql.jdbc.Driver
    

      

    ===@Builder注解===

    在出现lombok之后,对象的创建工作更提供Builder方法,

    它提供在设计数据实体时,对外保持private setter,而对属性的赋值采用Builder的方式,

    这种方式最优雅,也更符合封装的原则,不对外公开属性的写操作!

    @Builder声明实体,表示可以进行Builder方式初始化,

    @Value注解,表示只公开getter,对所有属性的setter都封闭,即private修饰,所以它不能和@Builder一起使用

    参考博客:

    https://www.cnblogs.com/lori/p/9024933.html

    ===Builder注解没有builder方法===

    解决办法:

    在IDEA中下载lombok插件解决。vscode一样。

    参考博客:

    https://blog.csdn.net/Butterfly_resting/article/details/101377756

    ===Lombok中的@Data注解===

    @Data:该注解相当于同时加上以下注解@Setter @Getter,@ToString,@EqualsAndHashCode

    @Getter:生成getter方法

    @Setter:生成setter方法

    @AllArgsConstructor:全参构造

    @NoArgsContructor:无参构造

    ===JdbcTemplate与NamedParameterJdbcTemplate===

    SimpleJdbcTemplate加入了Java5的特性支持,例如可变参数、自动拆包封包、泛型等支持。

    JdbcTemplate,已经基本能看到相对于JDBC比较强大的能力,

    但是它有一个问题很不方便,就是使用参数的占位符时,必须得按照顺序来写参数,如果顺序不对,则操作失败,

    NamedParameterJdbcTemplate可以用来解决这个问题,它提供了一个方式,可以通过参数名来映射参数而不是传统的"?"

    可以使用SqlParameterSourceUtils.createBatch()方法,将list里的东西变成一个batch的值

    List<Foo> list = new ArrayList<>();
    list.add(Foo.builder().id(100L).bar("b-100").build());
    list.add(Foo.builder().id(101L).bar("b-101").build());
    namedParameterJdbcTemplate.batchUpdate("INSERT INTO FOO (ID, BAR) VALUES (:id, :bar)",
    SqlParameterSourceUtils.createBatch(list));
    

      

    ===spring boot的定时任务(Scheduled)===

    @Scheduled中的参数说明

    @Scheduled(fixedRate=2000):上一次开始执行时间点后2秒再次执行;

    Scheduled(fixedDelay=2000):上一次执行完毕时间点后2秒再次执行;

    @Scheduled(initialDelay=1000, fixedDelay=2000):第一次延迟1秒执行,然后在上一次执行完毕时间点后2秒再次执行;

    @Scheduled(cron="* * * * * ?"):按cron规则执行。

    参考博客:

    https://www.cnblogs.com/mmzs/p/10161936.html

    ===Spring boot Scheduled没有被定时执行===

    解决办法:

    @ComponentScan(basePackages = {"com.xxx"})

    这是spring扫描路径,Test 是否在 com.xxx 包下面

    @ComponentScan做的事情就是告诉Spring从哪里找到bean

    @Component 和 @ComponentScan的使用目的不一样

    @Component注解,表明当需要创建类时,这个被注解的类是一个候选类。就像是举手

    @ComponentScan 用于扫描指定包下的类。就像看都有哪些举手

    参考博客:

    https://blog.csdn.net/Lamb_IT/article/details/80918704

    ===JPA的一些注解===

    主体

    @Entity

    @MappedSuperclass 

    @Table(name)

    主键

    @Id

    @GeneratedValue(strategy, generator)

    @SuquenceGenerator(name, sequenceName)

    @GeneratedValue注解的strategy属性提供四种值:

    -AUTO主键由程序控制, 是默认选项 ,不设置就是这个

    -IDENTITY 主键由数据库生成, 采用数据库自增长, Oracle不支持这种方式

    -SEQUENCE 通过数据库的序列产生主键, MYSQL  不支持

    -Table 提供特定的数据库产生主键, 该方式更有利于数据库的移植

    映射

    @Column(name, nullable, length, insertable, updatable)

    @JoinTable(name)

    @JoinColumn(name)

    关系

    @OneToOne

    @OneToMany

    @ManyToOne

    @ManyToMany

    @OrderBy

    ===几种注解的关系===

    @Repository、@Service、@Controller 和 @Component 将类标识为Bean

    @Repository注解便属于最先引入的一批,它用于将数据访问层 (DAO 层 ) 的类标识为 Spring Bean

    @Component 是一个泛化的概念,仅仅表示一个组件 (Bean) ,可以作用在任何层次。

    @Service 通常作用在业务层,但是目前该功能与 @Component 相同。

    @Constroller 通常作用在控制层,但是目前该功能与 @Component 相同。

    通过在类上使用 @Repository、@Component、@Service 和 @Constroller 注解,

    Spring会自动创建相应的 BeanDefinition 对象,并注册到 ApplicationContext 中。

    这些类就成了Spring受管组件。

    这三个注解除了作用于不同软件层次的类,其使用方式与 @Repository 是完全相同的

    ===@GeneratedValue===

    在JPA中

    @GeneratedValue注解存在的意义主要就是为一个实体生成一个唯一标识的主键(JPA要求每一个实体Entity,必须有且只有一个主键)

    @GeneratedValue提供了主键的生成策略。

    @GeneratedValue注解有两个属性,分别是strategy和generator

    generator属性的值是一个字符串,默认为"",其声明了主键生成器的名称(对应于同名的主键生成器@SequenceGenerator和@TableGenerator)

    PA为开发人员提供了四种主键生成策略,其被定义在枚举类GenerationType中,包括

    GenerationType.TABLE:

    GenerationType.SEQUENCE:

    GenerationType.IDENTITY:

    GenerationType.AUTO:

    参考博客:

    https://blog.csdn.net/u012493207/article/details/50846616

    ===@Id 和 @GeneratedValue 注解===

    @Id 标注用于声明一个实体类的属性映射为数据库的主键列。

    该属性通常置于属性声明语句之前,可与声明语句同行,也可写在单独行上。

    参考博客:

    https://blog.csdn.net/Jae_Wang/article/details/80533137

    ===@Query===

    @Query(value=" 这里就是查询语句")

    @Query支持hql和原生sql两种方式,默认是hql,hql就是语句中用的是实体名字和实体属性,原生sql用的表名字和表字段, 

    hql方式不支持select * 要想查询全部字段可以用select 实体名 这里省略了value,参数使用了占位置符 ?1代表第一个参数?2代表第二个

    @Param 代替参数占位符,hql或者sql里就用:firstname替换方法里的参数顺序可以打乱

    如果是更新或者删除操作,方法上面要加@Modifying默认开启的事务只是可读的,更新操作加入@Modifying就会关闭可读

    原生sql方式 不能和Pageable pageable 同时使用,要用自己的limit实现分页,原生的方式就和sql语法完全一样,使用的表名字,表字段

    @Data 属于lombok注解,与jpa无关,自动生成getter/setter/equals/hashcode/tostring等方法

    @Entity, @Table jpa注解,表示这个类与db的表关联,具体匹配的是表 money

    @Id @GeneratedValue 作用与自增主键

    @Column表明这个属性与表中的某列对应

    @CreateDate根据当前时间来生成默认的时间戳

    参考博客:

    https://blog.csdn.net/qq_27886997/article/details/82982936

    ===启动报错===

    Field processedDataDao in rexel.controller.RexelMiddlewareController required a bean of type 'rexel.dao.ProcessedDataDao' that could not be found.
    
    The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)
    

      

    问题原因:

    包扫描路径不正确

    @ComponentScan("rexel")

    ===启动报错===

    Composite-id class must implement Serializable: rexel.entity.DViewVarNameDic
    

    如果该实体类对应的表只有一个主键,即图中的id,把linkName上面的@Id注解删除即可,重新启动就不会报错了。

    如果该实体类对应的表确实使用的两个字段(联合主键),则要求该实体类必须可序列化,该类要实现 Serializable 接口,并添加如下代码:

    private static final long serialVersionUID = 1L;
    public class DViewVarNameDic implements Serializable {
    

     

    参考博客:

    http://www.mamicode.com/info-detail-2681892.html

    ===启动报错===

    Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: This class [class rexel.entity.DViewVarNameDicEntity] does not define an IdClass
    

    解决办法:

    在Entity类前面加上@IdClass()

    ===@Configuration和@Bean===

    @Configuration底层是含有@Component ,所以@Configuration 具有和 @Component 的作用。

    @Configuration可理解为用spring的时候xml里面的<beans>标签。

    @Configuration注解可以达到在Spring中使用xml配置文件的作用。

    @Configuration标注在类上,相当于把该类作为spring的xml配置文件中的<beans>,作用为:配置spring容器(应用上下文)

    参考博客:

    https://blog.csdn.net/qq_36472252/article/details/86623630

    ===RestRemplate样例程序运行报错===

    Caused by: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class rexel.webservice.bean.ProcessedDataBean] and content type [text/html;charset=utf-8]
    

     

    按照这个网址可以解决
    https://www.jianshu.com/p/95bf08696cd7

    然后再次运行,又会提示其他错误

    Caused by: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized token 'H24': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'H24': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
    at [Source: (PushbackInputStream); line: 6, column: 20]
    

    检查之后,发现是我在postman里定义的json格式不正确引起的。

    Shit,多少有些2B了,暂时放过自己一次。

    ===增加了事务注解,但是无法回滚===

    我这里发生的原因是用@Transactional(rollbackFor = Exception.class)标注的方法没有是public

    参考博客:

    https://blog.csdn.net/zdyueguanyun/article/details/80236401

    ===读取application.properties文件的几种方法===

    第一种方式:使用@ConfigurationProperties(prefix = "com.zyd")注解在class头

    第二种方式:使用@Value("${propertyName}")注解在变量上

    第三种方式:使用Environment evn; env.getProperty("com.zyd.type2")

    第四种方式:使用Properties properties = PropertiesLoaderUtils.loadAllProperties(propertyFileName);

    参考博客:

    https://www.cnblogs.com/FraserYu/p/11261916.html

    ===Http报头Accept与Content-Type的区别===

    Http报头分为通用报头,请求报头,响应报头和实体报头。

    1.Accept属于请求头, Content-Type属于实体头。 

    Http报头分为通用报头,请求报头,响应报头和实体报头。 

    请求方的http报头结构:通用报头|请求报头|实体报头 

    响应方的http报头结构:通用报头|响应报头|实体报头

    2.Accept代表发送端(客户端)希望接受的数据类型。 

    比如:Accept:text/xml; 

    代表客户端希望接受的数据类型是xml类型

    3.Content-Type代表发送端(客户端|服务器)发送的实体数据的数据类型。 

    比如:Content-Type:text/html; 

    代表发送端发送的数据格式是html。

    二者合起来, 

    Accept:text/xml; 

    Content-Type:text/html 

    即代表希望接受的数据类型是xml格式,本次请求发送的数据的数据格式是html。

    ===运行报错===

    Caused by: org.hibernate.AnnotationException: No identifier specified for entity: rexel.entity.AccessTokenEntity
    at org.hibernate.cfg.InheritanceState.determineDefaultAccessType(InheritanceState.java:266) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
    at org.hibernate.cfg.InheritanceState.getElementsToProcess(InheritanceState.java:211) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
    at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:781) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
    at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:254) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:230) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:273) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1214) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1245) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
    

    问题原因:  

    当使用idclass时,实体中须有和idclass类中属性个数的主键,并且一致

    参考博客:

    https://blog.csdn.net/Mosqiote/article/details/89227931

    ===Springboot的entity,dao,controller,service层级理解===

    1.Dao层:持久层,主要与数据库交互

    DAO层首先会创建Dao接口,接着就可以在配置文件中定义该接口的实现类;

    接着就可以在模块中调用Dao的接口进行数据业务的处理,而不用关注此接口的具体实现类是哪一个类,

    Dao层的数据源和数据库连接的参数都是在配置文件中进行配置的。

    2.Entity层:实体层,数据库在项目中的类

    主要用于定义与数据库对象应的属性,提供get/set方法,tostring方法,有参无参构造函数。

    3.Service层:业务层 控制业务

    业务模块的逻辑应用设计,和DAO层一样都是先设计接口,再创建要实现的类,然后在配置文件中进行配置其实现的关联。

    接下来就可以在service层调用接口进行业务逻辑应用的处理。

    好处:封装Service层的业务逻辑有利于业务逻辑的独立性和重复利用性。

    4.Controller层:控制层 控制业务逻辑

    具体的业务模块流程的控制,controller层主要调用Service层里面的接口控制具体的业务流程,控制的配置也要在配置文件中进行。

    Controller和Service的区别是:Controller负责具体的业务模块流程的控制;Service层负责业务模块的逻辑应用设计

    5、View层

    此层与控制层结合比较紧密,需要二者结合起来协同工发。View层主要负责前台jsp页面的表示

    总结:

    Controller层调用了Service层的方法,Service层调用Dao层的方法,其中调用的参数是使用Entity层进行传递的。

    参考博客:

    https://www.cnblogs.com/almm/p/10802419.html

    ===请求报错===

    Invalid character found in method name. HTTP method names must be tokens
    

    解决办法:

    请求由https修改为http之后解决。

    ===后端如何将数据返回给前端?===

    @RequestBody:

    用于读取Http请求的body部分数据——就是我们的请求数据。比如json或者xml。然后把数据绑定到 controller中方法的参数上

    @ReponseBody:

    放在controller层的方法上,将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。

    使用时机: 当我们想让页面知道我们返回的数据不是按照html标签的页面来解析,而是其他某种格式的数据解析时(如json、xml等)使用。

    ===运行报错===

    javax.persistence.TransactionRequiredException: Executing an update/delete query
    	at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:409) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
    	at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1601) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
    

     

    问题原因

    在@Query注解中编写JPQL语句, 但必须使用@Modifying进行修饰。以通知SpringData,这是一个UPDATE或DELETE操作 

    其中,nativeQuery = true 就代表使用原始 sql

    修改之后代码如下:

    @Modifying
    @Query(nativeQuery = true, value = "insert into COLLECT_SWITCH(collect) values (:#{#entity.collect})")
    public void insert(@Param("entity") CollectSwitchEntity entity);
    

    ===运行错误===

    org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://3dd39ca6-40bd-41ae-a045-ff80d0e6aca8.mock.pstmn.io/openapi/ipm/wait/process/query": Read timed out; nested exception is java.net.SocketTimeoutException: Read timed out
    

     

    解决办法:

    增加对RestRemplate连接时间的配置。

    解决后代码

    @Configuration
    public class RestTemplateConfig {
        @Bean
        public RestTemplate restTemplate(ClientHttpRequestFactory factory){
            return new RestTemplate(factory);
        }
    
        @Bean
        public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
            SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
            factory.setConnectTimeout(15000);
            factory.setReadTimeout(15000);
            return factory;
        }
    }
    

      

    ===mysql传入时间正确,但是插入到数据库时间错误,相差几个小时===

    解决办法:

    直接在数据库连接地址后面添加引号内的内容“&serverTimezone=GMT%2B8”

    spring.datasource.url=jdbc:mysql://192.168.29.100:3306/rexel_hzzg?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
    

    ===saveAll为啥每次都要查询数据?===

    原因请参考博客:

    https://www.cnblogs.com/blog5277/p/10661096.html

    解决办法:

    自己写插入的语句,不适用JPA自带的saveAll方法。

    ====运行错误===

    错误日志:

    2019-11-22 16:20:13.862 ERROR 98860 --- [   scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task
    
    org.springframework.web.client.HttpClientErrorException$NotFound: 404 Not Found
    	at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:85) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    	at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:123) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    	at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:102) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    

      

    原因:
    已经发布的系统,其中有一个quartz的定时器运行了一段时间后突然挂掉了。

    并报错:Unexpected error occurred in scheduled task.

    调查发现因为:定时器的动作是调用一个同步线程,而某一次该线程运行时间过长即锁未释放,而第二次定时器动作又并发执行了,所以就导致了冲突。

    解决办法:

    1、增加config配置
    2、----------------------------不要使用https请求。。。。。。。。。。。。。

    补充:

    在博文最开始共享的代码中,我已经删除了ScheduleConfig的配置,代码中已经找不到这个配置了。

    ===mysql在台式机上安装报错(Windows10操作系统)===

    mysql启动服务报错

    Found option without preceding group in config file
    

      

    问题原因:

    mysql里面的配置文件my.ini文件格式是utf-8。

    只要把my.ini文件格式改为ANSI就可以了。

    ===程序运行了一段时间之后,报错===

    Hibernate: select collectswi0_.collect as collect1_1_ from COLLECT_SWITCH collectswi0_
    Hibernate: select accesstoke0_.token as token1_0_, accesstoke0_.insertTime as insertTi2_0_ from ACCESS_TOKEN accesstoke0_ order by accesstoke0_.insertTime desc
    2019-11-25 08:20:49.772 ERROR 15728 --- [pool-1-thread-2] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task
    
    org.springframework.web.client.HttpClientErrorException$TooManyRequests: 429 Too Many Requests
            at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:97) ~[spring-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:123) ~[spring-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:102) ~[spring-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63) ~[spring-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:785) ~[spring-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:743) ~[spring-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:717) ~[spring-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:605) ~[spring-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at rexel.schedule.MiddleWareSchedule.exchange(MiddleWareSchedule.java:318) ~[classes!/:0.0.1]
            at rexel.schedule.MiddleWareSchedule.getProcessData(MiddleWareSchedule.java:218) ~[classes!/:0.0.1]
            at rexel.schedule.MiddleWareSchedule.scheduleProcess(MiddleWareSchedule.java:111) ~[classes!/:0.0.1]
            at rexel.schedule.MiddleWareSchedule$$FastClassBySpringCGLIB$$3847585e.invoke(<generated>) ~[classes!/:0.0.1]
            at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769) ~[spring-aop-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747) ~[spring-aop-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366) ~[spring-tx-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99) ~[spring-tx-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747) ~[spring-aop-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689) ~[spring-aop-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at rexel.schedule.MiddleWareSchedule$$EnhancerBySpringCGLIB$$3bdb64f9.scheduleProcess(<generated>) ~[classes!/:0.0.1]
            at sun.reflect.GeneratedMethodAccessor96.invoke(Unknown Source) ~[na:na]
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_77]
            at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_77]
            at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) ~[spring-context-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
            at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [na:1.8.0_77]
            at java.util.concurrent.FutureTask.runAndReset(Unknown Source) [na:1.8.0_77]
            at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source) [na:1.8.0_77]
            at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) [na:1.8.0_77]
            at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.8.0_77]
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.8.0_77]
            at java.lang.Thread.run(Unknown Source) [na:1.8.0_77]
    

      

    原因是potstman已经达到了模拟请求的极限,需要升级到专业版

    You’ve reached your limit for mock requests. Upgrade to Pro for more.

    ===cron表达式===

    cron一共有7位,但是最后一位是年,可以留空,所以我们一般可以只写6位:

    第一位,表示秒,取值0-59

    第二位,表示分,取值0-59

    第三位,表示小时,取值0-23

    第四位,日期天/日,取值1-31

    第五位,日期月份,取值1-12

    第六位,星期,取值1-7,星期一,星期二…注意:1表示星期天,2表示星期一。

    第7为,年份,可以留空,取值1970-2099

    样例:

    每隔5秒执行一次:*/5 * * * * ? 
    每隔1分钟执行一次:0 */1 * * * ?
    每天凌晨1点执行一次:0 0 1 * * ?
    每天23点执行一次:0 0 23 * * ?
    每月最后一天23点执行一次:0 0 23 L * ?
    每月1号凌晨1点执行一次:0 0 1 1 * ?
    每天3点5分执行:0 5 3 * * ?
    每天3点5分执行,与上面作用相同:0 5 3 ? * *
    每天3点的 5分,15分,25分,35分,45分,55分这几个时间点执行:0 5/10 3 * * ?
    每周星期天,3点10分 执行,注:1表示星期天:0 10 3 ? * 1
    每个月的第三个星期,星期天 执行,注:#号只能出现在星期的位置:0 10 3 ? * 1#3
    在26分、29分、33分执行一次:0 26,29,33 * * * ?
    每天的0点、13点、18点、21点都执行一次:0 0 0,13,18,21 * * ?

    ===@Scope("prototype")===

    spring中bean的scope属性,有如下5种类型:

    1)singleton 表示在spring容器中的单例,通过spring容器获得该bean时总是返回唯一的实例

    2)prototype表示每次获得bean都会生成一个新的对象

    3)request表示在一次http请求内有效(只适用于web应用)

    4)session表示在一个用户会话内有效(只适用于web应用)

    5)globalSession表示在全局会话内有效(只适用于web应用)

    在多数情况,我们只会使用singleton和prototype两种scope,如果在spring配置文件内未指定scope属性,默认为singleton。

    ===接口Service有多个实现类===

    //接口.java
    public interface DeService {
    }
    
    //接口实现类1.java
    @Service("ud")
    public class DeServiceImplUD implements DeService{
    }
    
    //接口实现类2.java
    @Service("ug")
    public class DeServiceImplUG implements DeService{
    }
    
    //调用类.java
    @Autowired
    @Qualifier("ug")
    private DeService ds;

    ===all elements are null===

    使用spring jpa查询书库的时候,数据库中明明有数据,查询出来的结果却显示all elements are null。

    可以看出,实际上List中有38条数据,只不过都没能正确转换为Entity。

    后来调查原因是因为我用的PostgreSQL中数据有的字段为null,所以没能转换成功。

  • 相关阅读:
    谷歌浏览器本地调试时调用服务跨域
    SVN提交时忽略不必提交的文件夹和文件,如node_modules
    热点链接实现不规则菜单
    easyui分页控件的应用
    Filter过滤器的应用
    SVG绘图学习总结
    VS2010无法调试页面问题
    java学习
    webservice配置
    jQuery
  • 原文地址:https://www.cnblogs.com/quchunhui/p/11934249.html
Copyright © 2011-2022 走看看