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, 否则会有多线程访问数据互相修改的问题. 对于需要 ...
随机推荐
- New UWP Community Toolkit - RadialProgressBar
概述 UWP Community Toolkit 中有一个圆形的进度条控件 - RadialProgressBar,本篇我们结合代码详细讲解 RadialProgressBar 的实现. Radi ...
- linux分析、诊断及调优必备的“杀器”之二
先说明下,之所以同类内容分成多篇文章,不是为了凑篇数,而是为了便于自己和大家阅读,下面继续: 7.sar The sar command is used to collect, report, and ...
- 20162308 实验二《Java面向对象程序设计》实验报告
20162308 实验二<Java面向对象程序设计>实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 ...
- 数据结构——线性表——队列(queue)
队列也是一种特殊的线性表,它的特点是先入先出(FIFO,即first in first out).它的意思也很直观,想象一下排队买票,先排的人先买(插队是不对的,所以别去想).它也是很常用的数据结构, ...
- 团队作业5-测试与发布(AIpha版本)
对于已完成的项目我们进行了诸多测试,找到了少许bug,对着这些bug我们在改进的基础上提出了新的目标. 1,测试环境:个人笔记本.个人台式机.环境windows7.网络校园网加移动vpn,浏览器360 ...
- Linux下Apache服务的查看和启动
cd到/etc/rc.d/init.d/目录,并列出该目录下的所有文件,看看是否有httpd 使用httpd -v查看已经安装的httpd的版本 使用rpm -qa | grep http ...
- 【iOS】swift 排序Sort函数用法(包含NSDictionary排序)
用了几分钟做的简单翻译 一个例子 直接贴代码,不过多解释 //这是我们的model class imageFile { var fileName = String() var fileID = Int ...
- Angular.js 1++快速上手
AngularJS诞生于2009年,由Misko Hevery 等人创建,后为Goole所收购.是一款优秀的前端JS框架.AngularJS有着诸多特性,最为核心的是:MVC,撗块化,自动化双向数据绑 ...
- jquery基础总结 -- 转载
jquery的each里面return的使用 在使用jquery的each方法时, return false相当于break,是跳出each循环,return true相当于continue,是继续循 ...
- zookeeper 入门系列-理论基础 – zab 协议
上一章讨论了paxos算法,把paxos推到一个很高的位置.但是,paxos有没有什么问题呢?实际上,paxos还是有其自身的缺点的: 1. 活锁问题.在base-paxos算法中,不存在leader ...