原文地址: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编码时后缀模式会导致歧义。 可以使用以下方法关闭后缀模式:

  • PathMatchConfigureruseSuffixPatternMatching(false)
  • ContentNeogiationConfigurer 的favorPathExtension(false)
后缀匹配和RFD

反射型文件下载(RFD)攻击和XSS攻击很相似。XSS依赖于请求的输入,例如查询参数,URI变量等,而RFD是用户点击URL浏览器会下载恶意文件,用户点击后会攻击主机。 由于Spring MVC的 @ResponseBodyResponseEntity会根据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的更多相关文章

  1. springMVC中controller的几种返回类型

    ==网文1,还不错,感觉比较老旧springMVC中controller的几种返回类型 - CSDN博客http://blog.csdn.net/qq_16071145/article/details ...

  2. SpringMVC教程3

    SpringMVC教程2 一.文件上传 1.引入相关jar包 maven坐标 <!-- fileUpload 解析上传的文件用到的jar --> <dependency> &l ...

  3. SpringMVC教程4

    SpringMVC教程3 一.数据回写 数据回写:在做数据更新的时候服务端查询的数据自动填充到表单中. 1.1默认方式 通过前面讲解的 Map Mode ModelMap绑定数据 @RequestMa ...

  4. SpringMVC教程1

    一.SpringMVC介绍 1.MVC介绍 ==模型-视图-控制器(MVC== 是一个众所周知的以设计界面应用程序为基础的设计模式.它主要通过分离模型.视图及控制器在应用程序中的角色将业务逻辑从界面中 ...

  5. SpringMVC教程2

    接上篇文章-SpringMVC教程1 五.基本操作 1.响应请求的方式 1.1ModeAndView /** * 查询方法 * @return */ @RequestMapping("/qu ...

  6. Java系列教程-SpringMVC教程

    SpringMVC教程 1.SpringMVC概述 1.回顾MVC 1.什么是MVC MVC是模型(Model).视图(View).控制器(Controller)的简写,是一种软件设计规范. 是将业务 ...

  7. springMVC基础controller类

    此文章是基于 搭建SpringMVC+Spring+Hibernate平台 功能:设置请求.响应对象:session.cookie操作:ajax访问返回json数据: 创建springMVC基础con ...

  8. springmvc 中controller与jsp传值

    参考:springmvc 中controller与jsp传值 springMVC:将controller中数据传递到jsp页面 jsp中,死活拿不到controller中的变量. 花了半天,网上列出各 ...

  9. SpringMVC的Controller中使用线程安全的初始化

    因为SpringMVC的Controller默认是单例, 在这种情况下, Controller中使用的私有变量必须也是单例, 例如各种service, 否则会有多线程访问数据互相修改的问题. 对于需要 ...

随机推荐

  1. Git 建立仓库及常用命令速查表

    Git新建仓库两种模式: 一.项目在本地时,本地初始化仓库并提交至Coding.Net 新建一个空白目录并进入,执行如下流程 1.git init2.项目代码复制到当前目录3.git add *4.g ...

  2. Welcome to StackEdit!

    Welcome to StackEdit! Hey!our first Markdown document in StackEdit1. Don't delete me, I'm very helpf ...

  3. Alpha第二天

    Alpha第二天 听说 031502543 周龙荣(队长) 031502615 李家鹏 031502632 伍晨薇 031502637 张柽 031502639 郑秦 1.前言 任务分配是VV.ZQ. ...

  4. idea 导eclipse项目

    https://www.cnblogs.com/xiaoBlog2016/archive/2017/05/08/6825014.html

  5. 22.C++- 继承与组合,protected访问级别

    在C++里,通过继承和组合实现了代码复用,使得开发效率提高,并且能够通过代码看到事物的关系 组合比继承简单,所以在写代码时先考虑能否组合,再来考虑继承. 组合的特点 将其它类的对象作为当前类的成员使用 ...

  6. java 1.7新特性

    try( ... ){ ... } catch(xxx e){ ... } java1.7特性,叫做try-with-resource,实现了AutoCloseable接口的实例可以放在try(... ...

  7. 国内maven仓库地址 || 某个pom或者jar找不到的解决方法

    解决方法 建议在maven仓库中新建settings.xml,然后把如下内容粘贴进去即可.也可以找到maven的安装目录中的conf/settings.xml,把如下的mirrors节复制到对应部分. ...

  8. python random 模块的用法

    Python中的random模块用于生成随机数.下面介绍一下random模块中最常用的几个函数. random.random random.random()用于生成一个0到1的随机符点数: 0 < ...

  9. Spring Security 入门(3-11)Spring Security 的使用-自定义登录验证和回调地址

    配置文件 security-ns.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmln ...

  10. ssh整合之六管理我们的配置文件

    1.我们的ssh搭建已经搭建好了,之前是纯xml方式,而且我们的配置文件,是一个框架一个配置文件.这样的话,配置文件中的内容就会很多,这样以后修改起来也会很麻烦,因        此,我们尝试着把这些 ...