Spring Boot开发时遇到的一系列问题及解决办法总结

转载:  https://blog.yoodb.com/yoodb/article/detail/1476

原文如下:

问题一

Spring Boot扫描包提示找不到mapper的问题,异常信息内容:

Consider defining a bean of type in your configuration

分析原因:Spring Boot项目的Bean装配默认规则是根据Application类所在的包位置从上往下扫描,“Application类”是指Spring Boot项目入口类。如果Application类所在的包为:com.yoodb.blog,则只会扫描com.yoodb.blog包及其所有子包,如果service或dao所在包不在com.yoodb.blog及其子包下,则不会被扫描。

解决方法:

方式一:使用注解@ComponentScan(value=”com.yoodb.blog”),其中,com.yoodb.blog为包路径。

方式二:将启动类Application放在上一级包中,注意的是Application启动类必须要保证在包的根目录下。

 

问题二

启动Spring Boot时,,抛出异常信息如下:

Your ApplicationContext is unlikely to start due to a @ComponentScan of the default package

 

application.Java类文件内容如下:

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.boot.SpringApplication;
@Controller
@SpringBootApplication
@Configuration
public class HelloApplication {
    @RequestMapping("hello")
    @ResponseBody
    public String hello() {
        return "hello world!";
    }
    public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class, args);
    }
}

分析原因:Spring Boot启动时,抛出“** WARNING ** : Your ApplicationContext is unlikely to start due to a @ComponentScan of the default package.”警告信息,这是由于application.Java文件不能直接放在main/java文件夹下,必须要建一个包把它放进去。

解决办法:Spring Boot在写启动类的时候如果不使用@ComponentScan指明对象扫描范围,默认指扫描当前启动类所在的包里的对象,如果当前启动类没有包,则在启动时会抛出上述警告信息,导致项目出错。  

 

问题三

Spring Boot连接数据库时,抛出异常信息如下:

caused by: java.lang.NoClassDefFoundError: javassist/bytecode/ClassFile

分析原因:这是由于缺少javassist.jar包导致启动失败

解决办法:通过Eclipse执行Maven命令重构项目:Maven-Update Project,等待下载jar包即可,若还是失败请手动添加javassist.jar包的pom.xml配置信息。

 

Spring Boot使用spring-data-jpa插件,抛出异常信息如下:

caused by: java.lang.illegalargumentexception: Not a managed type: class entity.User

分析原因:这是由于Spring Boot未找到实体对象指定的类名,缺少jpa entity配置路径

解决办法:在Repository配置类前面添加注解@EntityScan('entity对应的包路径')

 

问题四

Spring Boot返回json字符串,增加APPLICATION_JSON参数代码如下:

mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON))

在添加APPLICATION_JSON参数后,抛出“APPLICATION_JSON cannot be resolved or is not a field”异常信息。

分析原因: Bean实体中存在getXsetX方法,但是没有这个x属性,将导致json转换失败,抛出“APPLICATION_JSON cannot be resolved or is not a field”异常信息。

解决办法:去掉不存在属性的getXsetX方法或者增加上改属性即可。

 

2、转载:https://www.2cto.com/kf/201601/487876.html

原文如下:spring巧用继承解决bean的id相同的问题

先感叹一下:最近的项目真的很奇葩!!!

需求是这样的:我们的项目中引用了两个jar包,这两个jar包是其他项目组提供的,不能修改!

奇葩的是:这两个jar中都需要引用方提供一个相同id的bean,而bean的定义却是不同的,也就是虽然id相同,但他们对应的却是两个不同的java类,导致出现的问题是:该id对应的java类满足了第一个jar包的要求,则不能满足第二个jar包的要求,满足了第二个jar包的要求,则不能满足第一个jar包的要求,导致spring容器在启动时就报错。

那么,该怎么解决该问题呢?如何做才能符合两个jar包的需求呢?经过仔细思考:发现通过java类的继承可以巧妙的实现该需求,现示例如下:

spring主配置文件:

applicationContext.xml

?

1

2

3

4

5

6

7

<!--{cke_protected}{C}%3C!%2D%2D%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%2D%2D%3E-->

<beans xmlns="https://www.springframework.org/schema/beans" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:p="https://www.springframework.org/schema/p" xsi:schemalocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

    <import resource="classpath*:app1.xml">

    <import resource="classpath*:app2.xml">

    <import resource="classpath:appContext1.xml">

<!--{cke_protected}{C}%3C!%2D%2D%20%09%3Cimport%20resource%3D%22classpath%3AappContext2.xml%22%2F%3E%20%20%2D%2D%3E-->

</import></import></import></beans>


其中:app1.xml和app2.xml是两个jar包app1.jar和app2.jar中对应的spring配置文件

app1.jar和app2.jar中主要就有一个java编译好后的class文件和一个配置文件:

其中app1.jar中的java文件和配置文件分别为:

Test1.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

package mypackage;

 

 

public class Test1 {

     

    private Object obj;

     

     

 

    public Object getObj() {

        return obj;

    }

 

 

 

    public void setObj(Object obj) {

        this.obj = obj;

    }

 

 

 

    @Override

    public String toString() {

        if(!this.getObj().getClass().getName().equals("mypackage.Obj1")){

            try {

                throw new Exception();

            } catch (Exception e) {

                System.err.println("test1--->mypackage.Test1依赖的obj类型错误,注入的不是mypacke.Obj1");

            }

        }

        System.out.println("package.Test1");

        return "package.Test1";

    }

 

 

}

app1.xml

?

1

2

3

4

5

6

7

8

9

10

<!--{cke_protected}{C}%3C!%2D%2D%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%2D%2D%3E-->

<beans xmlns="https://www.springframework.org/schema/beans" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:p="https://www.springframework.org/schema/p" xsi:schemalocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

     

    <bean id="test1" class="mypackage.Test1">

        <property name="obj">

            <ref bean="mybean">

        </ref></property>

    </bean>

     

</beans>

app2.jar中的java类和配置文件分别为:

Test2.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

package mypackage;

 

public class Test2 {

     

    private Object obj;

     

 

    public Object getObj() {

        return obj;

    }

 

 

    public void setObj(Object obj) {

        this.obj = obj;

    }

 

 

    @Override

    public String toString() {

        if(!this.getObj().getClass().getName().equals("mypackage.Obj2")){

            try {

                throw new Exception();

            } catch (Exception e) {

                System.err.println("test2--->mypackage.Test2依赖的obj类型错误,注入的不是mypacke.Obj2");

            }

        }

        System.out.println("package.Test2");

        return "package.Test2";

    }

 

 

}

app2.xml:

 

?

1

2

3

4

5

6

7

8

9

10

<!--{cke_protected}{C}%3C!%2D%2D%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%2D%2D%3E-->

<beans xmlns="https://www.springframework.org/schema/beans" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:p="https://www.springframework.org/schema/p" xsi:schemalocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

     

    <bean id="test2" class="mypackage.Test2">

        <property name="obj">

            <ref bean="mybean">

        </ref></property>

    </bean>

     

</beans>


其中:mybean是需要引用方提供的,这两个jar中需要引用方提供的bean的id都是一样的,这就导致了文章开始所提到的的问题。

测试程序:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

package mypackage;

 

 

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

 

public class Test {

     

 

 

    public static void main(String[] args) {

 

        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

     

    /*  System.out.println(((Test1)context.getBean("child1")).getObj().getClass().getName());

        System.out.println(((Test1)context.getBean("child2")).getObj().getClass().getName());*/

         

         

        System.out.println(((Test1)context.getBean("test1")).getObj().getClass().getName());

        System.out.println(((Test2)context.getBean("test2")).getObj().getClass().getName());

         

 

    }

 

}

运行得到的两个bean是相同的bean,不符合要求!!

解决方案:

引进两个子类Child1和Child2,分别继承jar包需要的Test1和Test2

Child1.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

package mypackage;

 

public class Child1 extends Test1 {

 

    private Object obj;

     

 

    public Object getObj() {

        return obj;

    }

 

    public void setObj(Object obj) {

        this.obj = obj;

    }

 

    @Override

    public String toString() {

        if(!this.getObj().getClass().getName().equals("mypackage.Hello")){

            try {

                throw new Exception();

            } catch (Exception e) {

                System.err.println("child1--->mypackage.Test依赖的obj注入的类型错误,注入的不是mypacke.Hello");

            }

        }

        return "package.Test1";

    }

 

}

Child2.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

package mypackage;

 

 

public class Child2 extends Test2 {

     

     

    private Object obj;

     

     

 

    public Object getObj() {

        return obj;

    }

 

 

 

    public void setObj(Object obj) {

        this.obj = obj;

    }

 

 

 

    @Override

    public String toString() {

        if(!this.getObj().getClass().getName().equals("mypackage.World")){

            try {

                throw new Exception();

            } catch (Exception e) {

                System.err.println("child2--->mypackage.Test2依赖的obj注入的类型错误,注入的不是mypacke.World");

            }

        }

        return "package.Test2";

    }

 

     

 

 

}

添加一个新的spring辅助配置文件:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

<!--{cke_protected}{C}%3C!%2D%2D%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%2D%2D%3E-->

<beans xmlns="https://www.springframework.org/schema/beans" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:p="https://www.springframework.org/schema/p" xsi:schemalocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

     

    <bean id="obj1" class="mypackage.Obj1"></bean>

    <bean id="obj2" class="mypackage.Obj2"></bean>

    <bean id="mybean1" class="mypackage.Obj2"></bean>

    <bean id="mybean2" class="mypackage.Obj2"></bean>

    <bean id="child1" class="mypackage.Child1">

        <property name="obj">

            <ref bean="mybean1">

        </ref></property>

    </bean>

     

    <bean id="child2" class="mypackage.Child2">

        <property name="obj">

            <ref bean="mybean2">

        </ref></property>

    </bean>

     

</beans>

在spring主配置文件做修改如下:

?

1

2

3

4

5

6

<!--{cke_protected}{C}%3C!%2D%2D%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%2D%2D%3E-->

<beans xmlns="https://www.springframework.org/schema/beans" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:p="https://www.springframework.org/schema/p" xsi:schemalocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

    <!--{cke_protected}{C}%3C!%2D%2D%20%3Cimport%20resource%3D%22classpath*%3Aapp1.xml%22%2F%3E%0A%09%3Cimport%20resource%3D%22classpath*%3Aapp2.xml%22%2F%3E%20%2D%2D%3E-->

    <import resource="classpath:appContext1.xml">

    <import resource="classpath:appContext2.xml">

</import></import></beans>

测试程序:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

package mypackage;

 

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

 

public class Test {

     

 

    public static void main(String[] args) {

 

        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        //System.out.println(context);

        /*System.out.println(((Test2)(context.getBean("test2"))).getObj().getClass().getName());

        System.out.println(((Test)(context.getBean("test"))).getObj().getClass().getName());*/

        //System.out.println(context.getBean("mybean").getClass().getName());

         

        System.out.println(context.getBean("child1"));

        System.out.println(context.getBean("child2"));

         

/*      System.out.println(context.getBean("mypackage.Hello"));

        System.out.println(context.getBean("mypackage.Hello#1"));*/

    }

 

}

运行得到:获取的是不同的bean,也就是间接实现了两个jar包中需要提供同名id的bean,但bean对应的java类是不同的java类的需求!

总结:实际上就是面向对象的lisp原则,就是里氏替换原则,具体点就是凡是父类出现的地方,都可以用子类来代替!

例子很简单,但是能说明问题。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值