添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

问题总结(1-34) 备注:很多摘抄于博客

目录:

  1. url重写

2. Logger logger = LoggerFactory.getLogger()为什么会出异常?

3. 在继承于HTTPServlet的类中使用Logger logger = LoggerFactory.getLogger()为什么会出异常?

4. log4j在多线程环境下第一次打印一次,第二次重复打印两次…,问题

5. 更改SpringBoot内置tomcat容器默认端口

6. SpringBoot报 Whitelabel Error Page错误

7. SpringBoot无法通过autowired注解注入repository对象

8. log4j:ERROR Could not find value for key log4j.appender.debug错误

9. SpringBoot事务注解@Transactional 事物回滚、手动回滚事物

10. 什么是“容器编排”

11. SpringBoot怎么从配置文件中读取相应属性值

12. Springboot采用从配置文件中读取mapping路径时,若MockMvc的单元测试采用的是独立测试环境,则单元测试代码会出错

13. Springboot的注解@Controller和@RestController有什么区别

14. Sprng注解@ReuqestMapping详解

15. Springboot的定时任务@Scheduled 三个参数fixedRate,fixedDelay,cron的不同

16. 什么是Restful

17. lombok使用

18. 怎么在Intellij中查看某接口的实现类的源码

19. Intellij怎么改项目名称

20. 将log4j.properties的路径写为相对路径

21. mysql中更新时间和创建时间的自动更新

22. mysql删除表中数据

23. mysql修改表结构

24. mysql的timestamp类型的一些注意点

25. springboot返回json格式数据

26. SpringBoot controller类方法接收@Requestbody形式参数,并用postman测试

27. Springboot CrudRepository和JpaRepository的区别

28. Jpa自定义查询报错(Failed to convert from type [java.lang.Object[]] to type)

29. 在使用 Spring Data JPA 时遇到报错:No converter found capable of converting from type [java.lang.Integer] to type [com.wchat.bean.Group]

30. JPA 的Encountered a duplicated sql alias [id] during auto-discovery of a native-sq异常。

31. MySql 为表中已有字段设置默认值

32. Spring 进入Controller前参数校验

33. @ControllerAdvice注解的三种使用场景

34. SpringBoot 使用props类和@ConfigurationProperties注解和@PropertySource注解来读取配置文件的内容


1. url重写

把JSESSIONID从客户端传到服务器端有两种方式:

①JESESSIONID保存在cookie文件中,浏览器发送请求的时候把这个cookie文件中的数据带给服务器(cookie)。

②通过传参的方式,把JSESSIONID的值通过要访问的URL传给服务器.(URL重写)。

2. Logger logger = LoggerFactory.getLogger()为什么会出异常?

没有加载到配置文件,见4点。

3.在继承于HTTPServlet的类中使用Logger logger = LoggerFactory.getLogger()为什么会出异常?

maven添加了相关jar包的依赖,并且已经下载了相关的jar包,在Itellij的External Libraries中也可以找到相关jar包,但启动tomcat容器后,还是显示找不到相关的jar包。

原因:是因为maven管理的jar包没有添加到相应容器中。

解决:以Intellij为例,将maven管理的jar包添加到相应容器中。

①右键项目,点击Open Module Settings

②选择左侧的Artifacts,如图,所有操作更改记得点击Apply

4. log4j在多线程环境下第一次打印一次,第二次重复打印两次…,问题

log4j,slf4j 在运用了BasicConfigurator.configure()后,在多线程环境中,第一次输出1次重复语句,第二次输出2次重复语句,第三次输出3次重复语句,…,的问题。

原因:当遇到如下报错时,

log4j:WARN No appenders could be found for logger (Ch06.Array).

log4j:WARN Please initialize the log4j system properly.

log4j:WARN See logging.apache.org/log4 for more info.

说明log4j.properties配置文件没有被读取,此时如果使用BasicConfigurator.configure()设置缺醒环境,虽然可以使用log4j

但它会给根记录器增加一个ConsoleAppender,默认级别为LEVEL.DEBUG

,因此就出现了上述问题。

应该使用PropertyConfigurator.configure("D:\\project\\src\\log4j.properties");

configure()中传log4j.properties的绝对路径,比如此处的"D:\\project\\src\\log4j.properties"。

5. 更改SpringBoot内置tomcat容器默认端口

在应用的application.properties或者yml配置文件中,添加配置项。

如:

6. SpringBoot报 Whitelabel Error Page错误

cnblogs.com/williamjie/

是因为controller.java文件放的位置不对,程序只加载Application.java所在包及其子包下的内容。

解决方法一:将包目录改成正确的

解决方法二:

在Application类中加上@ComponentScan(basePackages = {"com.demo.controller"}) 多个之间用","分隔。其中,com.demo.controller是你的controller所在的包。如下图:

7. SpringBoot无法通过autowired注解注入repository对象

这其实也是启动类application.java的文件位置的问题,与问题6的原因一样。但是这儿通过问题6中的方法二的@ComponentScan注解无法解决,正确的方法是应该让文件目录正确。检查repository对象注解失败的步骤如下:

①SpringBoot的启动类application一定要放在所有注入包的上面,最好是所有java包都是启动类所在包的子包,springboot启动扫描默认扫描启动类所在包和子包,如果将启动类放置在了底包,那么将扫描不到有些包,造成注入失败。

正确的目录结构如下:

②确保注解已经加上,control层加@RestController或@Controller注解,service层加@Service注解,dao层加上@Repository注解,实体类加上@Entity和@Table注解(如果类名和表名一致可以省略),在id上加@Id注解,并指明id的增长策略,变量加上@Colum注解(如果字段和变量一致可以省略)。

③确保pom文件依赖引入的正确性。我的就是此问题,一不小心引入了Spring-JPA 的依赖,应该引入springboot-starter的JPA依赖。

8. log4j:ERROR Could not find value for key log4j.appender.debug错误

这个问题在用PropertyConfigurator.configure初始化配置文件后仍然无法解决的情况下,引起此错误的原因可能是配置文件log4j.properties写的不对。比如我的配置文件如下所示:

log4j.rootLogger=stdout

# 输出到控制台

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.target=System.out

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %p [%t] %C.%M(%L) | %m%n

这个配置文件可以运行,因为蓝色部分完全对应起来。也就是说,在log4j.rootLogger中定义了什么级别(比如此处的stdout),在下面 log4j.appender.xxx 的配置中就要有该级别的appender的配置。

如果用下面这样的log4j.properties:

log4j.rootLogger=stdout,INFO

# 输出到控制台

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.target=System.out

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %p [%t] %C.%M(%L) | %m%n

就会报错:

log4j:ERROR Could not find value for key log4j.appender.INFO

log4j:ERROR Could not instantiate appender named "INFO".

log4j:ERROR Could not find value for key log4j.appender.INFO

log4j:ERROR Could not instantiate appender named "INFO".

因为log4j.rootLogger中的INFO在log4j.appender中找不到相对应的。

9. SpringBoot事务注解@Transactional 事物回滚、手动回滚事物

spring声明式事务管理默认对非检查型异常和运行时异常进行事务回滚,而对检查型异常则不进行回滚操作(对非检查型类异常可以不用捕获,而检查型异常则必须用try语句块进行处理或者把异常交给上级方法处理)。

在spring的事务管理环境下,使用unchecked exception可以极大地简化异常的处理,只需要在事务层声明可能抛出的异常(这里的异常可以是自定义的unchecked exception体系),在所有的中间层都只是需要简单throws即可,不需要捕捉和处理,直接到最高层,比如UI层再进行异常的捕捉和处理。

默认规则:

让checked异常回滚: @Transactional(rollbackFor=Exception.class),一般只需添加这个即可

让unchecked异常不回滚: @Transactional(notRollbackFor=RunTimeException.class)

不需要事务管理的(只查询的)方法: @Transactional(propagation=Propagation.NOT_SUPPORTED),或者不添加

10. 什么是“容器编排”

应用一般由单独容器化的组件(通常称为微服务)组成,且必须按顺序在网络级别进行组织,以使其能够按照计划运行。以这种方法对多个容器进行组织的流程即称为容器编排。所有的容器编排引擎均可让用户控制容器启动和停止的时间、将其分组合到群集中,以及协调应用组合的流程。容器编排工具允许用户指导容器部署与自动更新、运行状况监控以及故障转移等步骤。

11. SpringBoot怎么从配置文件中读取相应属性值

背景是:在SpringBoot开发中,以前自己写mapping的路径时总是直接写在里面,如下图所示:

但是实际项目开发中,mapping的路径要从properties配置文件中读取

①在application.properties配置文件中,定义属性值。在controller中读取。

application.properties文件中的内容如下:

controller如下:

这种方法可以很好解决背景中的问题,但是要注意的是如果采用从配置文件中读取路径的方式,而单元测试又采用的是MocMvc的独立测试环境来测试的话,单元测试程序会出错,这一点在下面叙述。

②在application.properties中有:

读取时,如下:

定义一个类的属性, 通过@Value(“${properties.path}”)来读取,其中properties.path是properties 自定义属性值的属性名。

③采用自定义配置文件的方式

a. 添加pom依赖

<!-- springboot configuration依赖 -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId> spring-boot-configuration-processor</artifactId>

<optional> true </optional>

</dependency>

b. 在resources下建一个config的directionary(名字人去), 在config里建一个remote.properties(properties文件的文件名任取)。

c. 在配置文件中写入测试内容

d. 写一个实体类,属性与配置文件对应

不适用lombok插件的话,要自己手动写get、set方法和构造函数等。

e. 读取

但是要注意的是如果在@RequestMapping(remoteProperties.getTestname()) 的方式来代替@Request Mapping(”testProperties”),程序会报错,原因还不明白,觉得可能是remoteProperties.getTestname()可能得到空值,所以这种写法被spring禁止。

12. Springboot采用从配置文件中读取mapping路径时,若MockMvc的单元测试采用的是独立测试环境,则单元测试代码会出错

采用MockMvc的独立测试环境进行springboot接口的单元测试的代码如下:

controller的代码如下:

单元测试代码如下:

其中在setup()方法中的 mockMvc = MockMvcBuilders.standaloneSetup(peopleController).build() 就是采用独立测试环境进行单元测试。

当采用从配置文件中读取mapping路径的方式时,

controller的代码如下:

若还是采用上述独立测试环境进行测试的话,会出错,出错的原因在于,虽然peopleController正常注入了不为null,但是通过MockMvcBuilders.standaloneSetup(peopleController).build()得到的MockMvc对象为null。

自己觉得原因是采用独立测试环境进行单元测试时,程序没有从properties配置文件中读取相应值。

解决方法如下:

核心点在于:改变MockMvc对象的生成方式。在单元测试类上加上@AutoConfigureMockMvc注解,然后通过

注解生成MockMvc对象。

13. Springboot的注解@Controller和@RestController有什么区别

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

①使用@Controller 注解,在对应的方法上,视图解析器可以解析return 的jsp,html页面,并且跳转到相应页面,若返回json等内容到页面,则需要加@ResponseBody注解。

②@RestController注解,相当于@Controller+@ResponseBody两个注解的结合,返回json数据不需要在方法前面加@ResponseBody注解了,但使用@RestController这个注解,就不能返回jsp,html页面,视图解析器无法解析jsp,html页面。

14. Sprng注解@ReuqestMapping详解

(1) @RequestMapping的value属性和path属性

这两个属性作用相同,可以互换,如果仅有这一个属性,则可以省略,下面两个例子均采用省略的方式。

①将@RequestMapping注解在login方法上,而UserController上不添加 @RequestMapping 注解,这时的请求 URL 是相对于 Web 根目录。

@Controller
public class UserController {
@RequestMapping("/login")
public String login() {
return "success";
}
}

此时接口地址应该为: localhost/SpringMVC/log

②将 @RequestMapping 注解在 UserController 类上,这时类的注解是相对于 Web 根目录,而方法上的是相对于类上的路径。

@Controller

@RequestMapping("/user")

public class UserController {

@RequestMapping("/login")

public String login() {

return "success";

}

}

此时请求路径为: localhost/SpringMVC/use

(2) @RequestMapping 的 method 属性

①RequestMapping的method属性指定Get请求方式

@RequestMapping(path = "/login", method=RequestMethod.GET)

②RequestMapping的method属性指定Post请求方式

@RequestMapping(path = "/login", method=RequestMethod.POST)

③RequestMapping的method属性指定多种类型的请求方式

@RequestMapping(path = "/login", method={RequestMethod.POST,RequestMethod.GET})

(3) @RequestMapping 的 params 属性

该属性表示请求参数,也就是追加在URL上的键值对,多个请求参数以&隔开。

@RequestMapping(path = "/login", params={"username=kolbe","password=123456"})

该方法将接收 /user/login 发来的请求,且请求参数必须为username=kolbe&password=123456。

(4) @RequestMapping 的 headers 属性

该属性表示请求头

@RequestMapping(path = "/login", headers="Host=localhost:8080")

表示只接收本机发来的请求

15. Springboot的定时任务@Scheduled 三个参数fixedRate,fixedDelay,cron的不同

fixedRate: 每隔多少秒执行一次任务

fixedDelay:前一个任务结束多少秒后开始执行任务

cron:当时间达到设置的时间会触发事件,比如@Scheduled(cron="0/5 * * * *?"),5秒执行一次

import java.text.DateFormat;  
import java.text.SimpleDateFormat;  
import java.util.Date;  
import org.springframework.scheduling.annotation.Scheduled;  
import org.springframework.stereotype.Component;  
@Component  
public class MyProcessor{  
    DateFormat sdf = new SimpleDateFormat("HH:mm:ss");  
    int[] delays = new int[]{8,3,6,2,2};  
    int index = 0;  
    @Scheduled(cron = "0/5 * * * * ?}")  
    public void process() {  
        try {  
            if(index > delays.length - 1){  
                if(index == delays.length){  
                    System.out.println("---------- test end at " + sdf.format(new Date()) + " ---------");  
                index ++;  
                return;  
            }else{  
                System.out.println(index + ":start run at" + sdf.format(new Date()));  
            Thread.sleep(delays[index] * 1000);  
            System.out.println(index + ":end run at " + sdf.format(new Date()));  
            index ++;   
        } catch (InterruptedException e) {  
            e.printStackTrace();  
简要说明上述代码含义:
上述代码假定Scheduled的任务序列如下:
任务编号 耗时(单位:秒)
0 8
1 3
2 6
3 2
4 2
分别使用下述三种参数:
@Scheduled(cron = "0/5 * * * * ?}") :5秒执行一次
@Scheduled(fixedDelay = 3000) :上次任务结束3秒后开始执行
@Scheduled(fixedRate = 5000) :每隔5秒开始执行
@Scheduled(cron = "0/5 * * * * ?}")的执行结果如下图:
从结果可以看出,使用了cron参数的时间轮转片总为5秒,第一个任务需要8秒执行完,
第一个5秒后发现任务仍然在执行,在第二个5秒中的第三秒,任务结束,此时还需等待2秒,等第二个5秒执行完,再开始新的任务。后续类似。比如任务2耗时6秒,待第一个5秒过后,第二个5秒中运行了1秒任务结束,此时需将第二个5秒的时间流转片运行完,故还要等待4秒,再开启新任务(任务3)