2.3 Controller层
Spring Boot把后台分成三层:Controller(控制器)负责响应http请求;Service(服务层),负责业务处理;Repository(仓库)负责直接和数据对接。
在上一节,http的响应方法都写在了DemoApplication.java这个文件里面了,如图所示:

实际上,响应方法通常并不写在这里,因为随着http请求增多,函数会越来越多,此文件就会越来越长,不利于维护。另外,这个文件是Spring Boot的启动文件,直接以应用的方式执行此文件,就相当于启动项目,所以此文件应当保持只有一个main函数,其他的响应方法要移走。
为了保持项目的可维护性,我们不会在DemoApplication类中直接添加请求处理方法。取而代之,我们会在com.example.restservice包下创建一个名为GreetingController的新类,并用@RestController注解来标注它。
首先,新建一个包com.example.restservice,专门用来放置http响应方法。
最后在新建的包里创建新的java文件GreetingController.java,这个类只需要加上标签@RestController,类里面就可以写http响应方法了。完成后如代码所示:
package com.example.restservice;import org.springframework.web.bind.annotation.RestController;@RestController public class GreetingController{}
把上一节的root函数移植到这里,注意一定是移植不能复制(复制会造成两个相同模式的响应入口),移植后如代码7-6所示:
package com.example.restservice;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.bind.annotation.CrossOrigin;import org.springframework.web.bind.annotation.GetMapping; @RestController public class GreetingController{ @CrossOrigin @GetMapping("/") public String root(){ return "{\"info\":\"Good\"}"; }}
GreetingController.java需要两个标签,一个是@RestController,表示这个类里面的http响应方法会被识别到;一个是@CrossOrigin,解决跨域问题(前端发起的HTTP请求不在它所处的服务器内)。
把所有包含响应http请求函数的类组织到同一个包里面,就形成了controller层。这个层被SpringBoot识别为响应函数,需要两个条件:1.函数带@RestController标签,2.所处的类,要么和启动类(DemoApplicaion.java)同一个包,或者在它的子包里。
于是还有一个修改,那就是DemoApplication.java的位置。这个文件之前是在包com.example.demo里面,现在需要移动到包com。因为Spring Boot规定,不在DemoApplication的响应方法,必须在DemoApplication所在包的子包里,也就是说为了Spring Boot扫描到com.example.restservice.GreetingController,并找到响应方法root,DemoApplication.java就必须在com包或者com.example包,或者和controller同一个包。
如果DemoApplication.java还在com.example.demo包,而controller在另一个包com.example.restservice,那么com.example.restservice.GreetingController里面的响应方法就无法生效。
修改后的位置如图7-12所示:

移植完后,重新启动Spring Boot,刷新一下网页验证看是否正常。
提示
带有RestController标签的类的内可以写http响应方法,Sprigboot会自动扫描所有带有RestController标签的类,相当于把这些类内部所有的响应方法都集中到一起,所以不能出现有相同URL模式的响应方法,即使它们在不同的类里面。
默认情况下,Spring Boot只会扫描主启动类所在包,或者它的子包(主启动类就是启动Spring Boot的那个类,包含标签Spring BootApplication)。例如主启动类在com这个包里面,那么com内部的类以及com的所有子包的类都会被扫描到;如果主启动类在com.xx这个包里面,那么com.yy的类就不会被扫描到,只能扫描com.xx所有子包的类,如com.xx.a。
类似这样的自动识别的扫描还有数据库表的实体类,数据库操作类等等。
提示
和前端不同,后台修改代码后,需要重启才能生效。通常前后端一起开发的时候,两个服务一起启动,并且打开浏览器,修改了部分代码后,就要测试一下是否生效,有没有影响正常功能的运行。