SpringMVC 教程 - Controller
原文地址:https://www.codemore.top/cates/Backend/post/2018-04-10/spring-mvc-controller
声明Controller
Controller也是一个标准的Spring bean,可以在Servlet的WebApplicationContext中定义。也可以使用@Controller注解,Spring会扫描注解自动注册为Spring的bean。 开启自动注册@Controller注解的bean可以使用如下Java Config的配置:
@Configuration
@ComponentScan("org.example.web")
public class WebConfig {
// ...
}
如果使用xml配置,如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="org.example.web"/>
<!-- ... -->
</beans>
请求映射
@RequestMapping可以将请求映射到具体的Controller方法上。通过找到匹配的url,http 方法,请求参数,header,媒体类型来映射请求。这个注解既可以用在类级别,也可以用在方法级别上。 为了方便@RequestMapping根据HTTP方法不同提供了如下快捷注解:
- @GetMapping
- @PostMapping
- @DeleteMapping
- @PutMapping
- @PatchMapping
示例如下所示:
@RestController
@RequestMapping("/persons")
class PersonController {
@GetMapping("/{id}")
public Person getPerson(@PathVariable Long id) {
// ...
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public void add(@RequestBody Person person) {
// ...
}
}
URI 模式
请求映射支持glob模式和通配符
?匹配一个字符*匹配0个或多个字符**匹配0个或多个路径 可以通过@PathVariable访问在URI中定义的变量:
@GetMapping("/owners/{ownerId}/pets/{petId}")
public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
// ...
}
URI的变量可以在类和方法中定义:
@Controller
@RequestMapping("/owners/{ownerId}")
public class OwnerController {
@GetMapping("/pets/{petId}")
public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
// ...
}
}
URI变量会自动类型转换,如果失败会抛出TypeMismatchException的异常。默认支持int,long,Date等类型,也可以通过DataBinder和 Type Conversion来注册其他需要支持的类型。 URI变量名也可以明确的支持,例如@PathVariable("customId"),不过如果在编译的时候带着调试信息,或者对于Java8 使用-parameters 编译,则可以不需要明确的命名。 语法{varName:regex}表示变量根据正则表达是来匹配,例如"/spring-web-3.0.5 .jar"可以使用以下表达式匹配
@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
public void handle(@PathVariable String version, @PathVariable String ext) {
// ...
}
URI同样可以有内嵌的${}的占位符,在应用启动的时候由PropertyPlaceHolderConfigurer从本地,系统,环境变量或者其他配置中解析。 Spring MVC使用的是Spring core 中的AntPathMatcher来匹配路径。
模式对比
当有很多模式匹配URI的时候,必须通过对比来找到最合适的匹配。这个是通过AntPathMatcher.getPatternComparator(String path)来实现。 可以根据URI中的变量个数,通配符个数来给URL打分,如果一个URI的变量少,通配符多,那么他得到的分数就会低。当匹配的模式分数相同是,选择匹配模式长的那个,如果分数和长度都相同,选择变量比通配符少的那个。 /**是不参与评分的,而且总会是最后一个选择。同样/plublic/**也是当匹配不到其他没有两个通配符的模式的时候才会被选择。 了解更加详细的信息可以查看AntPathMatcher中的AntPatternComparator。同时也可个继承PathMatcher来定制URI匹配。
后缀匹配
Spring MVC 默认启动.*后缀匹配模式,这样映射到/person的controller 同样可以映射到/person.*。扩展名可以用来代替header中的Accept表示请求返回的类型。例如person.pdf,person.xml等。 因为过去浏览器的Accept头很难解析,所以这么是有意要的,但是现在浏览器的Accept更加清晰明确了,所以更好的选择是用Accept。而且过去一段时间内,使用后缀名匹配的时候会有各种各样的问题,当使用URI变量,路径参数,URI编码时后缀模式会导致歧义。 可以使用以下方法关闭后缀模式:
PathMatchConfigurer的useSuffixPatternMatching(false)ContentNeogiationConfigurer的favorPathExtension(false)
后缀匹配和RFD
反射型文件下载(RFD)攻击和XSS攻击很相似。XSS依赖于请求的输入,例如查询参数,URI变量等,而RFD是用户点击URL浏览器会下载恶意文件,用户点击后会攻击主机。 由于Spring MVC的 @ResponseBody和ResponseEntity会根据URI后缀来渲染不同类型的响应内容,所以可能受到RFD攻击。关闭后缀匹配可以降低攻击的风险,但是不能完全防止RFD攻击。 为了防止RFD攻击,可以在渲染响应内容的时候添加Content-Disposition:inline;filename=f.txt确保一个安全的下载文件。 默认情况下大多数扩展名都有白名单,可以通过继承HttpMessageConverter对内容协商注册扩展,可以避免在响应中添加Content-Disposition。
可消费媒体类型
通过请求的Content-Type可以缩小请求的匹配范围,例如:
@PostMapping(path = "/pets", consumes = "application/json")
public void addPet(@RequestBody Pet pet) {
// ...
}
consumes也支持表达式求反操作,例如!text/plain指的就除了text/plain都可以。 可以定义一个类级别的consumes,其方法共享这个consumes,和其他的@ReqeustMapping的属性不同,方法的consumes会覆盖类的定义。
可产生的媒体类型
可以通过Accept头来缩小请求的匹配范围,例如:
@GetMapping(path = "/pets/{petId}", produces = "application/json;charset=UTF-8")
@ResponseBody
public Pet getPet(@PathVariable String petId) {
// ...
}
媒体类型可以指定一个字符集。对表达式取反也是支持的,例如:!text/plain指的就是除了text/plain都可以。 和consumes一样,也可以指定一个类级别的produces,其方法属性也会覆盖类的属性。
参数和HTTP header
可以通过参数来缩小请求匹配的范围。可以设置是否有参数("myParam"),反过来是否没有("!myParam")或者指定一个值("myParam=myValue")。
@GetMapping(path = "/pets/{petId}", params = "myParam=myValue")
public void findPet(@PathVariable String petId) {
// ...
}
同样的情况也适合HTTP header
@GetMapping(path = "/pets", headers = "myHeader=myValue")
public void findPet(@PathVariable String petId) {
// ...
}
SpringMVC 教程 - Controller的更多相关文章
- springMVC中controller的几种返回类型
==网文1,还不错,感觉比较老旧springMVC中controller的几种返回类型 - CSDN博客http://blog.csdn.net/qq_16071145/article/details ...
- SpringMVC教程3
SpringMVC教程2 一.文件上传 1.引入相关jar包 maven坐标 <!-- fileUpload 解析上传的文件用到的jar --> <dependency> &l ...
- SpringMVC教程4
SpringMVC教程3 一.数据回写 数据回写:在做数据更新的时候服务端查询的数据自动填充到表单中. 1.1默认方式 通过前面讲解的 Map Mode ModelMap绑定数据 @RequestMa ...
- SpringMVC教程1
一.SpringMVC介绍 1.MVC介绍 ==模型-视图-控制器(MVC== 是一个众所周知的以设计界面应用程序为基础的设计模式.它主要通过分离模型.视图及控制器在应用程序中的角色将业务逻辑从界面中 ...
- SpringMVC教程2
接上篇文章-SpringMVC教程1 五.基本操作 1.响应请求的方式 1.1ModeAndView /** * 查询方法 * @return */ @RequestMapping("/qu ...
- Java系列教程-SpringMVC教程
SpringMVC教程 1.SpringMVC概述 1.回顾MVC 1.什么是MVC MVC是模型(Model).视图(View).控制器(Controller)的简写,是一种软件设计规范. 是将业务 ...
- springMVC基础controller类
此文章是基于 搭建SpringMVC+Spring+Hibernate平台 功能:设置请求.响应对象:session.cookie操作:ajax访问返回json数据: 创建springMVC基础con ...
- springmvc 中controller与jsp传值
参考:springmvc 中controller与jsp传值 springMVC:将controller中数据传递到jsp页面 jsp中,死活拿不到controller中的变量. 花了半天,网上列出各 ...
- SpringMVC的Controller中使用线程安全的初始化
因为SpringMVC的Controller默认是单例, 在这种情况下, Controller中使用的私有变量必须也是单例, 例如各种service, 否则会有多线程访问数据互相修改的问题. 对于需要 ...
随机推荐
- Linux下进程间通信--消息队列
消息队列的定义遍地都是,不想移驾,请看下文: 一.定义: 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法. 每个数据块都被认 为是有一个类型,接收者进程接收的数据块可以有不同的类型值.我 ...
- iOS开发UIKit框架-可视化编程-XIB
1. Interface Builder 可视化编程 1> 概述 GUI : 图形用户界面(Graphical User Interface, 简称GUI, 又称图形化界面) 是指采用图形方式显 ...
- Linux系统安装gcc/g++详细过程
下载: http://ftp.gnu.org/gnu/gcc/gcc-4.5.1/gcc-4.5.1.tar.bz2 浏览: http://ftp.gnu.org/gnu/gcc/gcc-4.5.1/ ...
- scrapy crawl 源码修改 爬虫多开
import os from scrapy.commands import ScrapyCommand from scrapy.utils.conf import arglist_to_dict fr ...
- 【iOS】swift 排序Sort函数用法(包含NSDictionary排序)
用了几分钟做的简单翻译 一个例子 直接贴代码,不过多解释 //这是我们的model class imageFile { var fileName = String() var fileID = Int ...
- Python习题(第一课)
想了想其他的太简单了,还是不放了,剩三题吧. 一.完美立方 编写一个程序,对任给的正整数N (N≤100),寻找所有的四元组(a, b, c, d),使得a^3= b^3 + c^3 + d^3,其中 ...
- php的数组的函数
1.可以将一个二位数组转化成两个一维数组,没有指定键就是默认的索引 注意二位数组有几种类型,其中最常见的一种是外层循环是一个索引数组,然后内层是一个关联数组.这种通过便利第一层,然后第二层指定关联词就 ...
- 用nodejs 开发的智能提示
用nodejs 开发的智能提示 时间:2014-07-01 03:50:18 类别:搜索引擎 访问: 2576 次 感谢:http://lutaf.com/223.htm 智能提示对于搜索非常重要,相 ...
- LeetCode & Q1-Two Sum-Easy
Array Hash Table Question Given an array of integers, return indices of the two numbers such that th ...
- AWS的开发工具包和设备SDK开发工具包
一.开发工具包 二.设备sdk开发工具包