终于,咱们的教程来到了SpringBoot核心功能的介绍。对于本章,各位读者至少具有如下的知识:前端
对于一个简单的maven结构的项目来讲,如下结构:java
${basedir} |-- pom.xml |-- src |-- main |-- java || com.xxx.xxx 项目源码 |-- resources || 项目配置文件 .xml等 |-- test |-- java |-- resources
在咱们前面的教程中,咱们都是在编写着代码,从未关注过maven的pom.xml到底是如何配置的,由于项目脚手架已经配置完成了,也许有细心的同窗已经看过了pom.xml文件的内容了:git
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- ... 省略了当前项目自己信息的配置,若有须要,请读者查看源码 --> <!-- 当前pom的父级 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.3</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <!-- springboot框架web功能starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- springboot框架的测试依赖starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <!-- 构建流程使用SpringBoot的maven插件 --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
对于一个普通的maven项目,其实核心的就是dependencies节点-dependency节点
了。经过dependency
节点,咱们能够GAV坐标(Group-Artifact-Version)引入不一样的库jar包,便于咱们的项目使用这些库。github
那么为何在上面的pom出现了一个parent节点呢?实际上,pom容许所谓的继承:咱们能够把一堆的pom依赖和配置,放到一个公共的pom里面,而后各个项目经过parent节点去引用这个公共的pom文件。因为SpringBoot并非一个单一的jar包构成的框架,它的内部其实依赖了下面的核心库:web
spring-core spring-beans spring-context ...还有不少
若是手动一项又一项编写dependency来使用Spring框架,不只仅容易遗漏,并且十分不方便进行这些依赖库的版本管理。基于此,SpringBoot官方提供了父级pom:spring
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.3</version> <!-- 2021/08/09最新 --> <relativePath/> <!-- lookup parent from repository --> </parent>
那么再看咱们的pom文件中,还依赖了spring-boot-starter-web
,这又是什么呢?难道有一个jar包叫作spring-boot-starter-web
吗?其实否则。咱们上面提到了parent POM,可是Spring框架下的依赖包特别多,而且有些包是核心的包,有些包则是在某些功能须要的状况下才依赖的包。若是一股脑的所有经过parent引入会让你的项目依赖十分臃肿,因此Spring官方再次按照包的功能进行了必定的组合,造成了所谓的starter,若是你只是想作web API的服务开发,用spring-boot-starter-web
就能够了,要是须要使用AOP(面向切面编程,做切面开发),加上spring-boot-starter-aop
依赖便可。apache
// 使用注解 @RestController,代表当前类是一个基于REST 规范的HTTP API Controller @RestController // @RequestMapping 注解放在Controller上,用于标记 HTTP url的路径入口, // 例如 http://localhost:8080/hello/xxx 才会进入当前Controller @RequestMapping("hello") public class HelloController { // @RequestMapping 注解放在Controller的里面的方法上, // 将会与Controller上的RequestMapping组合成:"/hello/say" // method用于指示经过何种HTTP方法访问 // 在程序启动后,咱们可使用GET方法访问:http://localhost:8080/hello/say @RequestMapping(value = "say", method = RequestMethod.GET) public String say() { return "hello, world"; } }
编写启动类,启动咱们的SpringBoot程序:编程
@SpringBootApplication public class Chapter03App { public static void main(String[] args) { SpringApplication.run(Chapter03App.class, args); } }
启动成功后,经过HTTP访问:浏览器
http://localhost:8080/hello/say # 输出:hello, world
上面的例子中,咱们使用注解@RestController
来标记了咱们的Controller类,会有初学者使用@Controller
来标记Controller,让咱们改为它试试:
@Controller // 改为使用 @Controller注解,其余不变,再次访问,看看有什么问题 @RequestMapping("hello") public class HelloController { // ... }
重启启动应用后再次访问对应地址。若是是在浏览器中,你会看到:
Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. Mon Aug 09 10:16:59 CST 2021 There was an unexpected error (type=Not Found, status=404).
type=Not Found, status=404
,404!为何会这样呢?
@Controller
标记,那么将使用SpringMVC架构(自行了解),若是对应的方法返回的是字符串,则这个字符串代表须要查找对应的视图(View)名称,并将对应的视图经过视图解析器(InternalResourceViewResolver)解析修改成前端web页面。@RestController
注解Controller,则Controller中的方法没法返回jsp页面,或者html,配置的视图解析器不起做用,返回的内容就是return里的内容。针对状况1,解决方法就是在方法的返回上加上注解:@ResponseBody
:
@ResponseBody // 若是当前Controller被@Controller注解,又想返回字符串或其余原始数据 @RequestMapping(value = "say", method = RequestMethod.GET) public String say() { return "hello, world"; }
在以前的文章,咱们已经介绍了SpringBoot是如何初始化Bean而且将其放在IOC容器的。咱们提到了三种方式:一、@Component
;二、Java配置类;三、XML配置。对于第二、3点,好像目前咱们的样例中并无作手动配置的事情。那么是否是咱们的Controller已经被@Component
标记了呢?
查看@RestController的定义:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Controller // 原来你RestController也是一个Controller注解啊! @ResponseBody // 而且,已经添加了@ResponseBody public @interface RestController { @AliasFor( annotation = Controller.class ) String value() default ""; }
@RestController
其实组合了@Controller
和@ResponseBody
两个注解了。咱们再看看@Controller
的定义:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component // 原来你Controller注解也组合了Component注解 public @interface Controller { @AliasFor( annotation = Component.class ) String value() default ""; }
原来@Controller
也已经组合了@Component
注解啊,难怪咱们的定义的Controller能被加载。
要回答这个问题,须要你有必定的关于Java Tomcat Web容器的知识。本系列主要是对SpringBoot的快速入门,不便于讲的过细。简单一点就是: