背景
创建了一个sprting boot项目反复确认过依赖没有问题,但是始终报404, 解压打包好的jar包文件发现代码已经打包进去了,现象比较奇怪.
各种原因及解决方案
原因一、controller`没有被spring 容器扫描到
-
如果启动失败,一直报错,是有可能 你的启动类直接放在了
src.java.main
下面 ,这是错误的,你需要将您的启动类放在src.java.main.*
以下 例如src.java.main.com.example
下面 -
如果启动成功,但是却访问不了你自己写的controller,报404错误,那么原因就是您写的controller
没有被spring 容器扫描到
-
- spring boot 默认扫描您的类是 在启动类的当前包 和 下级包 。比如: 您的启动类(TestStart.java)在
com.example.test
下(com.example.test.TestStart.java) 那么spring 会扫描com.example.test
和com.example.test.*
如果你的controller(TestController.java)没有放在com.example.test
或者com.example.test.*
下的话,就不会被扫描到,就会发生404错误.
- spring boot 默认扫描您的类是 在启动类的当前包 和 下级包 。比如: 您的启动类(TestStart.java)在
-
- 另外还可通过 配置spring扫描路径来解决问题
在启动类的上面添加@ComponentScan(basePackages = {"com.example.*"})
,这配置的controller
所在的包,重新编译运行后成功调用controller
下的接口
- 另外还可通过 配置spring扫描路径来解决问题
原文参考: spring boot无法启动,或者正常启动之后无法访问报404的解决办法
原因二、 controller中@Controller
注解后面需要添加@ResponseBody
注解
在controller中@Controller
注解后面或者在需要返回数据的方法前面添加@ResponseBody
注解, 另外还可以直接用@RestController
替换这两个注解, @RestController
@RestController
注解相当于@ResponseBody + @Controller
合在一起的作用, 需要注意的是
-
如果只是使用
@RestController
注解Controller,则Controller中的方法无法返回jsp页面,或者html,配置的视图解析器InternalResourceViewResolver
不起作用,返回的内容就是Return
里的内容。 -
如果需要返回到指定页面,则需要用
@Controller
配合视图解析器InternalResourceViewResolver
才行。
如果需要返回JSON,XML或自定义mediaType内容到页面,则需要在对应的方法上加上@ResponseBody
注解。 -
如果需要返回JSON,XML或自定义mediaType内容到页面,则需要在对应的方法上加上
@ResponseBody
注解
原文参考: @Controller和@RestController的区别?
原因三、 需要重写configure
重写configure,可以不用新建类直接在Application里面写
接着是新建一个ServletInitializer 并且集成自SpringBootServletInitializer 示例代码如下:
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
// 不重写打包war部署到tomcat接口会报404
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
特别注意其中的Application要与我们自己建立的Application名称一样。
如果要放在其他tomcat上的话要在pom.xml
需要加入下面的依赖:
<!-- 打war包时加入此项, 告诉spring-boot tomcat相关jar包用外部的,不要打进去 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope><!--由JDK或者容器提供-->
</dependency>
至于为什么要继承重写目前找到的说法如下:(具体还是要自己了解一下SpringBootServletInitializer
)
这里继承SpringBootServletInitializer
并重写其中的configure
方法目的是使用Spring框架的Servlet3.0支持。并且允许我们可以配置项目从serclet容器中启动。
SpringBootServletInitializer
的执行过程,简单来说就是通过SpringApplicationBuilder
构建并封装SpringApplication
对象,并最终调用SpringApplication
的run
方法的过程
原文参考: springboot打包war部署到tomcat接口404