SpringBoot常用注解总结

目录

  • Spring Boot
    • @Controller和@RequestMapping
    • @RequestMapping标注类
    • @RequestMapping的简写形式
      • 返回HTML
      • 本地资源文件组织
      • 服务器中的静态资源文件
    • @PathVariable
      • 定义URL变量规则
      • 获取URL变量
      • 匹配正则表达式
    • @RequestParam
      • Spring MVC中的Request参数
    • @RequestParam vs @PathVariable
      • 更多用法
    • 总结

Spring Boot

SpringBoot主要包括以下特性:

  1. 直接嵌入Tomcat,Jetty或者Undertow作为Servlet container。从此之后再也不用将应用程序打包成war然后上传到application server里面了。
  2. 提供了starter POM,能够非常方便的进行包管理,很大程度上减少了jar hell或者dependency hell。
  3. 自动进行Spring框架的配置,节省程序员大量的时间和精力,能够让程序员专注在业务逻辑代码的编写上。
  4. 不需要任何第三方系统,Spring
    Boot自带了可以用于生产环境的程序状态信息和健康状态。同时可以让应用程序非常方便的读取外部的配置信息。
  5. 完全不需要任何代码的自动生成。更不需要用xml来进行框架配置。

@Controller和@RequestMapping

@Controller标注的类表示的是一个处理HTTP请求的控制器(即MVC中的C),该类中所有被 @RequestMapping 标注的方法都会用来处理对应URL的请求。

在SpringMVC框架中,使用@RequsetMapping标注可以将URL与处理方法绑定起来,例如:

@RestController
public class HelloworldRestController {
    @RequestMapping("/")
    public String helloworld(){
        return "hello world";
    }
    @RequestMapping("/hello")
    @ResponseBody
    public String hello(){
        return "fpc";
    }
}

HelloworldRestController类被@Controller标注,其中的两个方法都被@RequestMapping标注,当应用程序运行后,在浏览器中访问:localhost:8080,请求会被SpringMVC框架分发到hellworld()方法进行处理。同理输入localhost:8080/hello会交给hello()方法处理。

@ResponseBody标注表示处理函数直接将函数的返回值传到浏览器端显示。

运行结果:

输入localhost:8080:
SpringBoot常用注解总结_第1张图片
输入loalhost:8080/hello:
SpringBoot常用注解总结_第2张图片

@RequestMapping标注类

@RequestMapping标注同样可以加在类上:

@RestController
@RequestMapping("/index")
public class HelloworldRestController {
    @RequestMapping("/")
    public String helloworld(){
        return "hello world";
    }
    @RequestMapping("/hello")
    @ResponseBody
    public String hello(){
        return "fpc";
    }
}

hello()方法绑定的URL路径是/index/hello

运行结果:
如果直接访问:localhost:8080/hello: (原因 url路径需要先匹配 /index)
SpringBoot常用注解总结_第3张图片
如果访问:http://localhost:8080/index/
SpringBoot常用注解总结_第4张图片
如果访问:localhost:8080/index/hello:
SpringBoot常用注解总结_第5张图片

提示: 每一个类都可以包含一个或者多个@RequestMapping标注的方法,通常我们会将业务逻辑相近的URL放在同一个Controller中处理。

@RequestMapping的简写形式

在web应用中常用的HTTP方法有四种:

  • PUT方法用来添加资源
  • GET方法用来获取已有的资源
  • POST方法用来对资源进行状态转换
  • DELETE方法用来删除已有的资源

这四个方法可以对应到CRUD操作(Create,Read,Update和Delete)比如博客的创建操作,按照REST风格设计URL就应该使用PUT方法,读取博客使用GET方法,更新博客使用POST方法,删除博客使用DELETE方法。

每一个Web请求都是属于其中一种,在SpringMVC中如果不特殊指定的话,默认是GET请求。

比如@RequestMapping("/")和@RequestMapping("/hello")和对应的Web请求分别是:
GET /
GET /hello

实际上@RequestMapping("/")是@RequestMapping("/",method = RequestMethod.GET)的简写,即可以通过method属性,设置请求的HTTP方法。

比如PUT /hello请求,对应@RequestMapping("/hello",method = RequestMethod.PUT)

Spring MVC最新的版本中提供了一种更加简洁的配置HTTP方式,增加了四个标注:

  • PutMapping
  • GetMapping
  • PostMapping
  • DeleteMapping

基于新的标注@RequestMapping("/hello",method = RequestMethod.PUT) 可以简写成@PutMapping("/hello"),
@RequestMapping("/hello")和@GetMapping("/hello")等价。

返回HTML

在之前所有的Controller方法中,返回值字符串被直接传送到浏览器端并显示给用户。但是为了能够呈现更加丰富,美观的页面,我们需要将HTML代码返回给浏览器,浏览器在进行页面的渲染显示,一种很直观的方法是在处理请求的方法中,直接返回HTML代码:

@RequestMapping("/blog")
    public String blog(){
        return "Title

This is a blog

This is content of the blog.

"
; }

运行结果:浏览器地址栏输入:localhost:8080/blog:
SpringBoot常用注解总结_第6张图片
显然,这样做的问题在于一个复杂的页面的HTML代码往往也非常复杂,并且内嵌在Java代码中十分不利于维护。

更好的做法是将页面的HTML代码卸载模板文件中,然后读取该文件并返回。Spring天然支持这种非常常见的场景,需要现在pom.xml引入Thymelea依赖:

<dependency>
  <groupId>org.springframework.bootgroupId>
  <artifactId>spring-boot-starter-thymeleafartifactId>
dependency>

将HTML文本保存在:src/main/webapp/pages/blog.html


<html>
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
    <h1>This is titleh1>
    <p>This is Content.p>
body>
html>

Controller中可以去掉@ResponseBody标注(表示不是直接返回字符串,而是返回渲染的HTML模板,并将URL处理函数设置为刚刚保存在pages/文件夹中的文件名(不需要扩展名:))

运行结果并没有出现返回blog.html页面,而是返回了"blog"字符串在浏览器中显示出来:

造成这种现象的原因是:如果类是用@RestController修饰的出现这种情况很正常,如果想要返回页面可以将@RestController改为@Controller

package springboot;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@Controller
//@RequestMapping("/index")
public class HelloworldRestController {
    @RequestMapping("/")
    public String helloworld(){
        return "hello world";
    }
    @RequestMapping("/hello")
    @ResponseBody
    public String hello(){
        return "fpc";
    }
    
    @RequestMapping("/blog")
    public String blog(){
        return "blog";
    }
}

##静态资源处理
在编写HTML代码的过程中,我们会遇到几类外部静态资源:

CSS文件:

"stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"/>
JavaScript文件:<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>

图像:

<img src="http://assets0.tianmaying.com/img/appicon/ios.png"/>

这些外部资源都是通过HTTP协议访问得到–也就是说,当我们用浏览器打开我们编写的HTML页面(无论是通过本地文件直接打开,还是访问SpringBoot服务器),在获取页面内容本身之外,还需要向外部服务器(例如maxcdn.bootstrapcdn.com)发起HTTP请求以获取我们需要的CSS/JavaScript资源。

但是在我们开发过程中,如果某个时刻不能访问Internet,那我们的页面也就无法正确地展现出它应有的样式。另一方面,除了使用第三方库,我们自己还会编写大量的CSS/JavaScript文件,这就要求我们必须有一种很快的方式能够在修改后立马在本地看到结果。

本地资源文件组织

首先我们抛开本地HTTP服务器,简单来看在本地编写一个HTML文件以及使用CSS资源,那么我们可以这样组织项目结构:

├── index.html
├── css
└── style.css
└── js
└── main.js
在index.html文件中你可以这样引用它们:
css/style.css和js/main.js都是使用相对路径描述。

"stylesheet" href="css/style.css"/>

服务器中的静态资源文件

如果需要将index.html放在服务器中呢?index.html位于templates目录下,通过http://localhost:8080/可以访问首页内容,但是CSS和JavaScript外部资源呢?
因为我们的HTTP服务器根本没有处理它们,所以不可能通过类似http://localhost:8089/css/style.css这样的方式来访问他们使得我们的页面正确显示。

默认情况下,SpringBoot会将类路径上的/static/目录的内容Serve起来,意思就是对静态资源的请求,都会返回/static/目录中对应路径的文件内容,于是我们可以这样组织文件目录结构来处理静态资源(以下是src/main/resources 目录结构,这个目录经过编译后被添加到类路径上)
├── static
├── css
└── style.css
└── js
└── main.js
└── templates
└── index.html
这样,当我们经过以上布局,重启应用后,就可以通过访问http://localhost:8089/css/style.css和http://localhost:8089/js/main.js来获取CSS和JavaScript资源了。

在HTML中引入资源
最后我们将静态资源引入到HTML页面中,我们往往需要一种介于相对路径(css/style.css)和绝对路径(http://localhost:8080/css/style.css)之间的资源访问方式–context路径:



这里只是简单的在相对路径URL的最前面加上了/,但是意义和相对路径就完全不同了,此时服务器会将其视为访问当前host中的“绝对路径”,也就是自动在这个路径前面加上协议,主机名,端口(都是当前服务器的相同信息),那么无论我们访问的是当前网站下的任何路径,它都会给出统一的结果,从而正确引用到外部资源。

@PathVariable

在上面的注解中,学习了如何在@Controller中创建@RequestMapping(或者响应的简写)来处理不同的URL请求。但是在Web应用中URL通常不是一成不变的,例如微博两个不同用户的个人主页对应两个不同的URL:http://weibo.com/user1,http://weibo.com/user2。我们不能对于每一个用户都编写一个被@RequestMapping注解的方法来处理其请求,也就是说,对于相同模式的URL(例如不同用户的主页,它们仅仅是URL中的某一部分不同,为他们各自的用户名,我们说它们具有相同的模式)。

定义URL变量规则

可以在@RequestMapping注解中用{}来表明它的变量部分,例如:

@RequestMapping("/users/{username}")

这里{username}就是我们定义的变量规则,username是变量的名字,那么这个URL路由可以匹配下列任意URL并进行处理:

  1. /users/tianmaying
  2. /users/ricky
  3. users/tmy1234

需要注意的是,在默认情况下,变量中不可以包含URL的分隔符/,例如路由不能匹配/users/tianmaying/ricky,即使你认为tianmaying/ricky是一个存在的用户名。

获取URL变量

在路由中定义变量规则后,通常我们需要在处理方法(也就是@RequestMapping注解的方法)中获取这个URL的具体值,并根据这个值(例如用户名)做相应的操作,SpringMVC提供的@PathVariable可以帮助我们:

@RequestMapping("/users/{username}")
    @ResponseBody
    public String userProfile(@PathVariable String username){
//        return String.format("user %s", username);
        return "user" + username; 
    }

在上述例子中,当@Controller处理HTTP请求时,userProfile的参数username会自动设置为URL中对应变量username(同名赋值)的值,例如当HTTP请求为/users/fpc

,URL变量username的值fpc会被赋给函数参数username,函数的返回值自然是userfpc。

在默认的情况下,Spring会对@PathVariable注解的变量进行自动赋值,当然你也可以指定@PathVariable使用哪一个URL中的变量:

@RequestMapping("/users/{username}")
@ResponseBody
public String userProfile(@PathVariable("username") String username){
    return "user" + username; 
}

运行结果:在这里插入图片描述
定义多个URL变量
可以定义URL路由,其中包含多个URL变量:

@RequestMapping("/user/{username}/blog/{blogId}")
@ResponseBody
public String getUerBlog(@PathVariable String username , @PathVariable int blogId) {
        return "user: " + username+"->" + "blog->" + blogId;
}

这种情况下,Spring能够根据名字自动赋值对应的函数参数值,当然也可以在@PathVariable中显示地表明具体的URL变量值。

在默认情况下,@PathVariable注解的参数可以是一些基本的简单类型:int,long,Date,String等,Spring能根据URL变量的具体值以及函数参数的类型来进行转换,例如/user/fpc/blog/1,会将“fpc”的值赋给username,而1赋值给int变量blogId。

运行结果:在这里插入图片描述

匹配正则表达式

很多时候,需要对URL变量进行更加精确的定义,例如-用户名只可能包含小写字母,数字,下划线,我们希望:

/user/fpc是一个合法的URL
/user/#$$$则不是一个合法的URL
除了简单地定义{username}变量,还可以定义正则表达式进行更精确的控制,定义语法是{变量名:正则表达式}[a-zA-Z0-9_]+是一个正则表达式,表示只能包含小写字母,大写字母,数字,下划线。如此设置URL变量规则后,不合法的URL则不会被处理,直接由SpringMVC框架返回404Not Found。

@RequestParam

Request参数
在访问各种各样网站时,经常会发现网站的URL的最后一部分形如:?xxxx=yyyy&zzzz=wwww。这就是HTTP协议中的Request参数,它有什么用呢?先来看一个例子:

  1. 在知乎中搜索web
  2. 浏览器跳转到新页面后,URL变为https://www.zhihu.com/search?type=content&q=web
    这里type=content&q=web就是搜索请求的参数,不同参数之间用&分隔,每个参数形如name=value形式,分别表示参数名字和参数值。在这个例子中,我们输入不同的搜索关键词,在搜索结果页面的URL的q参数是不同的,也就是说,HTTP参数实际上可以认为是一种用户的输入,根据不同的用户输入,服务器经过处理后返回不同的输出(例如搜索spring和搜索java,显示结果是不一样的。)

Spring MVC中的Request参数

在SpringMVC框架中,现在我们已经可以通过定义@RequestMapping来处理URL请求了,和@PathVariable一样,我们也需要再处理URL的函数中获取URL中的参数-也就是?key=value1&key2=value2这样的参数列表。通过注解@RequestParam可以轻松的将URL中的参数绑定到处理函数方法的变量中:

@RequestMapping("/user")
@ResponseBody
public String getUserBlog(@RequestParam("id") int blogId) {
    return "blogId = " + blogId;
}

这样当我们访问/user/?id=123时,Spring MVC帮助我们将Request参数id的值绑定到了处理函数的参数blogId上。这样就能够轻松获取用户输入,并根据它的值进行计算并返回了。

运行结果:

SpringBoot常用注解总结_第7张图片

@RequestParam vs @PathVariable

相信大家可能注意到了,@RequestParam和@PathVariable都能够完成类似的功能——因为本质上,它们都是用户的输入,只不过输入的部分不同,一个在URL路径部分,另一个在参数部分。要访问一篇博客文章,这两种URL设计都是可以的:

  • 通过@PathVariable,例如/blogs/1
  • 通过@RequestParam,例如blogs?blogId=1

那么究竟应该选择哪一种呢?建议:

  1. 当URL指向的是某一具体业务资源(或者资源列表),例如博客,用户时,使用@PathVariable
  2. 当URL需要对资源或者资源列表进行过滤,筛选时,用@RequestParam

例如我们会这样设计URL:

  • /blogs/{blogId}
  • /blogs?state=publish而不是/blogs/state/publish来表示处于发布状态的博客文章

更多用法

一旦我们在方法中定义了@RequestParam变量,如果访问的URL中不带有相应的参数,就会抛出异常——这是显然的,Spring尝试帮我们进行绑定,然而没有成功。但有的时候,参数确实不一定永远都存在,这是我们可以通过定义required属性:

@RequestParam(name="id",required=false)

当然,在参数不存在的情况下,可能希望变量有一个默认值:

@RequestParam(name="id",required=false,defaultValue="0")

总结

@RequestMapping注解中定义URL变量规则
@RequestMapping注解方法中获取URL变量-@PathVariable
@RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
@PathVariable指定URL变量名
定义多个URL变量
用正则表达式精确定义URL变量

参考文献:

  • SpringBoot-@PathVariable
  • SpringBoot-URL路由:@Controller和@RequestMapping
  • SpringBoot-@RequestParam

你可能感兴趣的:(Spring)