Spring Boot2 Web开发(一)

  • 时间:2018-10-27 23:23 作者:程序员那点事儿 来源:程序员那点事儿 阅读:590
  • 扫一扫,手机访问
摘要:关注一下,更多精彩等着你“最美好的生活方式,不是睡到自然醒,也不是可以随便购物无所事事,而是和一群志同道合的人,一起奔跑在理想的路上,回头有一路的故事,低头有坚定的脚步,抬头有清晰的远方。”Web开发的核心内容主要包括内嵌Servlet容器和Spring MVC。Spring Boot提供了spri
Spring Boot2 Web开发(一)

关注一下,更多精彩等着你

“最美好的生活方式,不是睡到自然醒,也不是可以随便购物无所事事,而是和一群志同道合的人,一起奔跑在理想的路上,回头有一路的故事,低头有坚定的脚步,抬头有清晰的远方。”


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 Boot2 Web开发(一)

图1

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的路径,支持URL模版、正则表达式。

属性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();
}
  • method,HTTP请求方法,有GET、POST、PUT等。

method属性映射对应HTTP的请求方法,通常HTTP请求方法有如下内容:

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,允许的媒体类型(Media Types),如consumes=“application/json”,对应于请求的HTTP的Content-Type。

属性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,响应的媒体类型,如produces=“application/json”,对应于HTTP的Accept字段。

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格式。

  • params,请求的参数,如params=“action=update”。
  • headers,请求的HTTP头的值,如headers=“myHeader=myValue”

方法参数

Spring的Controller方法可以接受多种类型的参数,比方我们看到的path变量,还有MVC的Model。除此之外,方法还能接受一下参数:

Spring Boot2 Web开发(一)

图2

@PathVariable

注解@PathVariable用于从请求URL中获取参数并映射到方法参数中,如下代码:

@Controller
@RequestMapping("/user/{id}")
public class HelloworldController {
@Autowired
UserService userService;

@GetMapping(path="/{type}/get.json")
public @ResponseBody User getUser(@PathVariable Long id,@PathVariable Integer type){
return userService.getUserById(id);
}
}

符号{}中的变量名与方法中的参数名逐个对应,假如不想对应,如Path中的名字是id,方法签名是userId,则可以使用@PathVariable(“id”) Long userId 来对应。

通常情况下,Java编译代码的时候,会将参数名称也编译到class字节码里,因而Spring会根据名字匹配自动映射。假如上述例子中出现如下错误:

There was an unexpected error (type = Internal Server Error, status = 500 ).

Name for argument type [java.lang.Long] not available, and parameter name information not found in class file either.

则表明你的编译环境未将调试信息加入class中,建议将编译器改成默认设置。以Eclipse为例,选择工程,右键选择属性,找到Java Compiler,在Classfile Generation 选项中勾选除Inline finally Blocks外的所有选项,如图所示:

Spring Boot2 Web开发(一)

图3

Spring也支持URL中的矩阵变量,所谓矩阵变量,就是出现在URL片段中,通过“;”分割的多个变量,比方/user/id=123;status=1/update.json。

JavaBean接受HTTP参数

HTTP提交的参数可以映射到方法参数上,按照名称来映射,比方一个请求/javaBean/update.json?name=abc&id=1,将会映射到如下方法:

@GetMapping(path="/update.json")
public @ResponseBody User getUser(Integer id,String type){
return userService.getUserById(id);
}

可以通过@RequestParam来进一步限定HTTP参数到Controller方法的映射关系,RequestParam支持如下属性:

value:指明HTTP参数的名称。

required:boolean类型,公告此参数能否必需有,假如HTTP参数里没有,则会抛出400错误。

defaultValue:字符类型,假如HTTP参数没有提供,可以指定一个默认字符串,Spring类型转换为目标类型,如上一个例子,我们可以提供默认参数:

@GetMapping(path="/update.json")
public @ResponseBody User getUser(@RequestParam(value = "id", required = true, defaultValue = "12") Integer id,String type) {
return userService.getUserById(id);
}

可以将HTTP参数转为JavaBean对象,HTTP参数的名字对应到POJO的属性名。通常,HTTP提交了多个参数,Spring支持按照前缀自动映射到不同的对象上。简单来说,Spring有如下表所示的HTTP参数到JavaBean的映射规则:

Spring Boot2 Web开发(一)

图4

@RequestBody接受JSON

Controller方法带有@RequestBody注解的参数,意味着请求的HTTP消息体的内容是一个JSON,需要转化为注解指定的参数类型。Spring Boot默认使用Jackson来解决反序列化工作。

MultipartFile

通过MultipartFile来解决文件上传,MultipartFile提供了以下方法来获取上传的文件信息:

getOriginalFilename:获取上传的文件名字。

getBytes:获取上传文件内容,转为字节数组。

getInputStream:获取一个InputStream。

isEmpty:文件上传为空,或者者就没有文件上传。

getSize:文件上传的大小。

transferTo(File dest):保存上传文件到目标文件系统。

假如同时上传多个文件,则使用MultipartFile数组类来接受多个文件上传。

Spring Boot中可以通过配置文件application.properties对上传文件进行限定,默认为如下配置:

spring.servlet.multipart.enabled=true
spring.servlet.multipart.file-size-threshold=0
spring.servlet.multipart.location=
spring.servlet.multipart.max-file-size=1MB
spring.servlet.multipart.max-request-size=10MB
spring.servlet.multipart.resolve-lazily=false

参数enabled默认为true,即允许上传,file-size-threshold 限定了当上传的文件超过肯定长度时,就写到临时文件里。者有助于上传文件不占用过多的内存,单位时MB或者者KB,默认是0,即不限定阀值。location指的是临时文件的存放目录,假如不设定,则Web服务器提供一个临时目录。max-file-size 属性指定了单个文件的最大长度,默认是1MB,max-request-size 属性说明单次HTTP请求上传的最大长度,默认是10MB。resolve-lazily 表示当文件和参数被访问的时候再解析成文件。

假如上传大文件失败,则需要检查是不是由于Spring Boot 对文件的限定过小造成的。另一方面,有些Spring Boot应用设置了代理商服务器,比方设置了Apache,也需要检查代理商服务器能否支持大文件上传,能否对超时做了设定。

@ModelAttribute

注解ModelAttribute通常作用做Controller的某个方法上,此方法会首先被调用,并将方法结果作为Model的属性,而后再调用对应的Controller解决方法。

@ModelAttribute
public void findUserById(@PathVariable Long id,Model model){
model.addAttribute("user", userService.getUserById(id));
}

@GetMapping(path="/{id}/get.json")
public @ResponseBody String getUser(Model model) {
System.out.println(model.containsAttribute("user"));
return "success";
}

对于HTTP请求,modelattribute/1/get.json,会先调用findUserById方法获得user,并增加到模型里。使用ModelAttribute通常可以用来向一个Controller中需要的公共模型增加数据。

假如findUserById仅仅增加一个对象到Model中,则可以改写成如下形式:

@ModelAttribute
public void findUserById(@PathVariable Long id){
userService.getUserById(id);
}

这样,返回到对象自动增加到Model中,相当于调用model.addAttribute(user)。

@InitBinder

将HTTP参数绑定到JavaBean对象中,其实Spring框架是通过WebDataBinder类实现这种绑定到,所以,可以在Controller中用注解@InitBinder公告一个方法,来自己扩展绑定到特性,比方:

@InitBinder
public void findUserById(WebDataBinder binder){
binder.addCustomFormatter(new DateFormatter("yyyy-mm-dd"));
}

@RequestMapping(path="/date")
public @ResponseBody void printDate(Date d) {
System.out.println(d);
return;
}

当需要绑定到一个Date类型的时候,如上述代码所示,则采用“yyyy-MM-dd”格式,比方客户访问databind/date?d=2001-1-1。

历史文章推荐:

Spring Boot2 热部署

Comparator接口的使用

  • 全部评论(0)
最新发布的资讯信息
【系统环境|windows】字节跳动前台面试题解析:盛最多水的容器(2021-03-20 21:27)
【系统环境|windows】DevOps敏捷60问,肯定有你想理解的问题(2021-03-20 21:27)
【系统环境|windows】字节跳动最爱考的前台面试题:JavaScript 基础(2021-03-20 21:27)
【系统环境|windows】JavaScript 的 switch 条件语句(2021-03-20 21:27)
【系统环境|windows】解决 XML 数据应用实践(2021-03-20 21:26)
【系统环境|windows】20个编写现代CSS代码的建议(2021-03-20 21:26)
【系统环境|windows】《vue 3.0探险记》- 运行报错:Error:To install them, you can run: npm install --save core-js/modules/es.arra...(2021-03-20 21:24)
【系统环境|windows】浅谈前台可视化编辑器的实现(2021-03-20 21:24)
【系统环境|windows】产品经理入门迁移学习指南(2021-03-20 21:23)
【系统环境|windows】初识webRTC(2021-03-20 21:23)
血鸟云
手机二维码手机访问领取大礼包
返回顶部