Web开发的核心内容主要包括内嵌Servlet容器和Spring MVC。
Spring Boot提供了spring-boot-starter-web为Web开发予以支持,spring-boot-starter-web为我们提供了嵌入的Tomcat以及Spring MVC的依赖。而Web相关的自动配置存储在spring-boot-autoconfigure.jar的org.springframework.boot.autoconfigure.web下,如下图所示:
Spring Boot集成Spring MVC框架并实现自动配置,只需要在pom中添加以下以来即可,不需要其他任何 配置:
org.springframework.boot
spring-boot-starter-web
本文中的例子使用了thymeleaf作为模版技术,因此需要添加以下依赖:
org.springframework.boot
spring-boot-starter-thymeleaf
Web的模版文件位于resources/templates目录下,模版文件使用的静态资源文件,如JS、CSS、图片,存放在resources/static目录下。在MVC中,视图名自动在templates目录下找到对应的模版名称,模版中使用的静态资源将在static目录下查找。
Spring MVC框架不像传统的MVC框架那样必须继承某个基础类才能处理用户的HTTP请求,Spring MVC只需要在类上声明@Controller,标注这是一个Controller即可。对于用户请求,使用@RequestMapping映射HTTP 请求到特定的方法处理类。@RequestMapping既可以作用在方法上,也可以作用在类上。例如:
@Controller
@RequestMapping("/test")
public class HelloworldController {
@RequestMapping("index.html")
public String say(){
return "index.html";
}
}
用户访问/test/index.html,则会交给HelloworldController.say方法来处理。say方法返回的类型是字符串,默认是视图名出。Spring Boot的视图默认保存在resources/templates目录下,因此,渲染的视图是resources/templates/index.html模版文件。
MVC框架有时候返回的是JSON字符串,如果想直接返回内容而不是视图名,则需要在方法上使用@ResponseBody:
@RequestMapping("index.json")
public @ResponseBody String say(){
return "hello,world";
}
@ResponseBody注解直接将返回的对象输出到客户端,如果是字符串,则直接返回;如果不是,则默认使用Jackson序列化城JSON字符串后输出。
如果你期望返回JSON,使用了注解@ResponseBody,但你的请求URL以html结尾,这会导致Spring Boot认为请求的是HTML类型的资源,而返回类型是JSON类型资源,与期望类型不一致而报出如下错误:
There was an unexpected error (type=Not Acceptable, status=406). Could not find acceptable representation
建议在Spring Boot应用中,如果期望返回JSON,URL请求资源后缀是json;如果期望返回视图,URL请求资源后缀是html。
@RequestMapping
可以使用@RequestMapping来映射URL,比如/test到某个Controller类,或者是某个具体的方法。通常类上的注解@RequestMapping用来标注请求的路径,方法上的@RequestMapping注解进一步映射特定的URL到某个具体的处理方法。
@RequestMapping有多个属性来进一步匹配HTTP请求到Controller方法,分别是:
属性value用于匹配一个URL映射,value支持简单的表达式来匹配:
@RequestMapping(value="/get/{id}.json")
public @ResponseBody User getById(@PathVariable("id") Long id){
return userService.getUserById(id);
}
如上面的例子所示,访问路径是/get/1.json,将调用getById方法,且参数id的值是1。注解@PathVariable作用在方法参数上,用来表示参数的值来自于URL路径。
如果你的IDE环境启用了debug模式(通常IDE或者Maven都会启用),则在编译Java代码称为字节码的时候,方法的参数保留了原来的参数名字。Java8如果使用了parameters编译选项,也会保留参数名字。Spring可以在这种情况下识别URL中存在的表达式与方法参数的对应关系,从而自动赋值,因此上述代码通常可以简化成:
@RequestMapping(path="/get/{id}.json",method = RequestMethod.GET)
public @ResponseBody User getById(@PathVariable Long id){
return userService.getUserById(id);
}
URL映射也可以使用${}来获得系统的配置或者环境变量,通常用于Controller路径是通过配置文件设定的情况。
@RequestMapping("/${query.all}.json")
public @ResponseBody List getById(){
return userService.allUser();
}
GET,用来获取URL对应的内容。
POST,用来向服务器提交信息。
HEAD,同GET,但不返回消息体,通常用于返回URL对应的元信息,如过期时间等。
PUT,同POST,用来向服务器提交信息,但语义上更像一个更新操作。同一个数据,多次 PUT操作,也不会导致数据发生改变。而POST在语义上更类似新增操作。
DELETE,删除对应的资源信息。
PATCH,类似PUT方法,表示信息的局部更新。
通常对于Web应用,GET和POST是经常使用的选项,对于REST接口,则会使用PUT、DELETE等用来从语义上进一步区分操作。
Spring提供来简化后的@RequestMapping,提供了新的注解来表示HTTP方法:
@GetMapping;
@PostMapping;
@PutMapping;
@DeleteMapping;
@PatchMapping;
属性consumes意味着请求的HTTP头的Content-Type媒体类型语consumes的值匹配,才能调用次方法。
@GetMapping(value="/consumes/test.json",consumes="application/json")
public @ResponseBody User getById(){
return userService.getUserById(1);
}
这里映射指定请求的媒体类型上application/json,因此,次方法接受一个AJAX请求。如果通过浏览器直接访问,则会看到Spring Boot报出如下错误,以为通过浏览器访问,通常并没有设置Content-Type,所以说null不支持。
produces属性对应于HTTP请求的Accept字段,只有匹配得上的方法才能被调用。
@GetMapping(path="/user/{userId}",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public @ResponseBody User getUser(@PathVariable Long userId){
return userService.getUserById(userId);
}
通常浏览器都会将Accept设置为*.*,因此通过浏览器直接访问/user/1,浏览器总是返回id为1的用户信息,并转换成JSON格式。
方法参数
Spring的Controller方法可以接受多种类型的参数,比如我们看到的path变量,还有MVC的Model。除此之外,方法还能接受一下参数:
@PathVariable |
可以将URL中的值映射到方法参数中。 |
Model |
Spring中通用的MVC模型,也可以使用Map和ModelMap作为渲染视图的模型。 |
ModelAndView |
包含了模型和视图路径的对象。 |
JavaBean |
将HTTP参数映射到JavaBean对象。 |
MultipartFile |
用于处理文件上传。 |
@ModelAttribute |
使用该注解的变量将作为Model的一个属性。 |
WebRequest或者NativeWebRequest |
类似Servlet Request,但做了一定封装。 |
java.io.InputStream和java.io.Reader |
用来获取Servlet API中的InputStream/Reader。 |
java.io.OutputStream/java.io.Writer |
用来获取Servlet API中的OutputStream/Writer。 |
HttpMethod |
枚举类型,对应于HTTP Method,如POST、GET。 |
@MatrixVariable |
矩阵变量。 |
@RequestParam |
对应于HTTP请求的参数,自动转化为参数对应的类型。 |
@RequestHeader |
对应于HTTP请求头参数,自动转化为对应的类型。 |
@RequestBody |
自动将请求内容转为指定的对象,默认使用HttpMessageConverters来转换。 |
@RequestPart |
用于文件上传,对应于HTTP请求的multipart/form-data。 |
@SessionAttribute |
该方法标注的变量来自于Session的属性。 |
@RequestAttribute |
该标注的变量来自于request的属性。 |
@InitBinder |
用在方法上,说明这个方法会注册多个转化器,用来个性化地将HTTP请求参数转化成对应的Java对象,如转化为日期类型、浮点类型、JavaBean等,当然,也可以实现WebBindingInitializer接口来用于Spring Boot应用所需要的dataBinder。 |
BindingResult和Errors |
用来处理绑定过程中的错误。 |