原文地址: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. Beta版本敏捷冲刺每日报告——Day1

    1.情况简述 Beta阶段第一次Scrum Meeting 敏捷开发起止时间 2017.11.2 08:00 -- 2017.11.2 21:00 讨论时间地点 2017.11.2晚6:00,软工所实 ...

  2. 关于python中的operator.itemgetter()函数的用法

    1. operator.itemgetter(num)函数 表示对对象的第num维数据进行操作获取. >>>import operator >>>a = [1, 2 ...

  3. Python randrange() 函数

    Python randrange() 函数  Python 数字 描述 randrange() 方法返回指定递增基数集合中的一个随机数,基数缺省值为1. 语法 以下是 randrange() 方法的语 ...

  4. Flask 学习 七 用户认证

    使用werkzeug 实现密码散列 from werkzeug.security import generate_password_hash,check_password_hash class Use ...

  5. hibernate.QueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken

    环境:weblogic10.3.5,hibernate3,GGTS(groovy/grails tools suite):出现这问题是因为该项目是从weblogic8.1.6下移植到weblogic1 ...

  6. 从数据恢复角度解析RAID6结构原理

    [什么是RAID]    RAID的概念描述在互联网上比比皆是,用最简单的原理描述,就是在定义存储方式时允许在一部分数据缺失的情况下不影响全部数据,类似于通讯领域的纠错码.不同的冗余模式形成了不同的R ...

  7. Solr搜索引擎搭建详细过程

    1    什么是solr Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器.Solr可以独立运行在Jetty.Tomcat等这些Servlet容器中 ...

  8. Java面试题合集(二)

    接下来几篇文章准备系统整理一下有关Java的面试题,分为基础篇,javaweb篇,框架篇,数据库篇,多线程篇,并发篇,算法篇等等,陆续更新中.其他方面如前端后端等等的面试题也在整理中,都会有的. 注: ...

  9. JAVA_SE基础——50.接口关系下的多态

    接口关系下的多态和继承关系下的多态 相差无几,应该更简单些~ 多态: 父类的引用类型变量指向了子类的对象或者是接口类型的引用类型变量指向了接口实现类 的对象. 实现关系下的多态: 接口  变量  = ...

  10. AutoCAD中的扩展字典及扩展记录(C#)

    在学习CAD扩展记录的过程中,遇到了一些问题,也积累了一些经验,现在给大家分享一些我的学习心得.在学习扩展字典之前需要读者了解cad的组码,也就是DxfCode.感兴趣的也可以了解一下扩展数据的相关内 ...