SpringBoot定义URL处理方法:@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:8089,请求会被SpringMVC框架分发到hellworld()方法进行处理。同理输入localhost:8089/hello会交给hello()方法处理。

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

运行结果:

输入localhost:8089:

输入loalhost:8089/hello:

@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:8089/hello:

如果访问:localhost:8089/index/hello:

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

@RequestMapping的简写形式

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

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

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

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

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

  1. GET /
  2. GET /hello

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

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

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

  1. PutMapping
  2. GetMapping
  3. PostMapping
  4. DeleteMapping

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

返回HTML

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

@RequestMapping("/blog")
public String blog(){
return "<html><head><title>Title</title></head><body><h2>This is a blog</h2><p>This is content of the blog.</p></body></html>";
}

运行结果:浏览器地址栏输入:localhost:8089/blog:

显然,这样做的问题在于一个复杂的页面的HTML代码往往也非常复杂,并且内嵌在Java代码中十分不利于维护。

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

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

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

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>This is title</h1>
<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";
}
}

继续运行项目:又出现问题了,报错信息为:

org.xml.sax.SAXParseException: 元素类型 "meta" 必须由匹配的结束标记 "</meta>" 终止。

报错的原因是blog.html代码中,meta元素没有封闭:

你可以直接封闭meta元素:

<meta charset="UTF-8"/>

也可修改SpringBoot的配置文件application.properties:

spring.thymeleaf.mode=LEGACYHTML5

SpringBoot的配置文件通常在/resource根目录下,以application.properties命名,没有这个文件则创建一个。

另外为了保证Thymeleaf能够正确识别HTML5,还需要添加Maven依赖到pom.xml:

<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<version>1.9.22</version>
</dependency>

再次运行程序:

注意:在编写HTML代码时,请务必保证每一个标签都是闭合的,容易忽略的标签包括<meta/>,<link/>,<br/><hr/>,<img/>,<input/>等等

但是在HTML5中,有些标签并不要求闭合,Thymeleaf遇到这样的HTML文件会报错。为了支持HTML5,你可以在SpringBoot配置文件中增加一行配置:如上面的过程。

静态资源处理

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

  • CSS文件:<link rel="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文件中你可以这样引用它们:

<link rel="stylesheet" href="css/style.css"/>
<script src="js/main.js"></script>

css/style.css和js/main.js都是使用相对路径描述。

服务器中的静态资源文件

如果需要将index.html放在服务器中呢?index.html位于templates目录下,通过http://localhost:8089/可以访问首页内容,但是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:8089/css/style.css)之间的资源访问方式--context路径:

<link rel="stylesheet" href="/css/style.css"/>
<script src="/js/main.js"></script>

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

SpringBoot-URL路由:@Controller和@RequestMapping的更多相关文章

  1. Java开发学习心得(二):Mybatis和Url路由

    目录 Java开发学习心得(二):Mybatis和Url路由 1.3 Mybatis 2 URL路由 2.1 @RequestMapping 2.2 @PathVariable 2.3 不同的请求类型 ...

  2. SpringBoot 中常用注解@Controller/@RestController/@RequestMapping的区别

    SpringBoot中常用注解@Controller/@RestController/@RequestMapping的区别 @Controller 处理http请求 @Controller //@Re ...

  3. SpringBoot 中常用注解@Controller/@RestController/@RequestMapping介绍

    原文 SpringBoot 中常用注解 @Controller/@RestController/@RequestMapping介绍 @Controller 处理http请求 @Controller / ...

  4. Netty URL路由方案探讨

    最近在用Netty做开发,需要提供一个http web server,供调用方调用.采用Netty本身提供的HttpServerCodec handler进行Http协议的解析,但是需要自己提供路由. ...

  5. 《Entity Framework 6 Recipes》中文翻译系列 (21) -----第四章 ASP.NET MVC中使用实体框架之在页面中创建查询和使用ASP.NET URL路由过虑

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 4.2. 构建一个搜索查询 搜索数据是几乎所有应用的一个基本功能.它一般是动态的,因 ...

  6. ASP.NET MVC 多语言实现——URL路由

    考虑实现一个完整的基于asp.net mvc的多语言解决方案,从路由到model再到view最后到数据库设计(先挖好坑,后面看能填多少). 我所见过的多语言做得最好的网站莫过于微软的msdn了,就先从 ...

  7. 004_URL 路由 - URL 路由

    在Web Form 情况下,每一个 ASPX页面既是一个文件,又是一个队请求自包含的响应.而在 MVC 情况下,请求是由控制器类中的动作方法处理的,而且与硬盘上的文件没有一对一的相互关系. ASP.N ...

  8. MVC的URL路由规则

    MVC的URL路由规则 Routing的作用:它首先是获取到View传过来的请求,并解析Url请求中Controller和Action以及数据,其次他将识别出来的数据传递给Controller的Act ...

  9. ASP.NET MVC 的URL路由介绍

    在这个教程中,向你介绍每个ASP.NET MVC一个重要的特点叫做URL路由.URL路由模块是负责映射从浏览器请求到特定的控制器动作. 在教程的第一部分,你将学习标准路由表如何映射到控制器的动作.在教 ...

随机推荐

  1. 《剑指offer》解题笔记

    <剑指offer>解题笔记 <剑指offer>共50题,这两周使用C++花时间做了一遍,谨在此把一些非常巧妙的方法.写代码遇到的难点.易犯错的细节等做一个简单的标注,但不会太过 ...

  2. hdu6125 Free from square 分组背包+状态压缩

    /** 题目:hdu6125 Free from square 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6125 题意: 从不大于n的所有正整数中选出 ...

  3. mysql 存储过程调用

    CALL  存储过程名('参数值1',‘参数值2',’参数值3')

  4. spring boot的@RequestParam和@RequestBody的区别

    一.问题描述 由于项目是前后端分离,因此后台使用的是spring boot,做成微服务,只暴露接口.接口设计风格为restful的风格,在get请求下,后台接收参数的注解为RequestBody时会报 ...

  5. 深入理解Mybatis中sqlSessionFactory机制原理

    对于任何框架而言,在使用前都要进行一系列的初始化,MyBatis也不例外.本章将通过以下几点详细介绍MyBatis的初始化过程. 1.MyBatis的初始化做了什么 2. MyBatis基于XML配置 ...

  6. UDP也需要现有Server端,然后再有Client端

    UDP编程: DatagramSocket(邮递员):对应数据报的Socket概念,不需要创建两个socket,不可使用输入输出流. DatagramPacket(信件):数据包,是UDP下进行传输数 ...

  7. yii2.0操作数据库

    首先不得不说yii2.0面向对象的比较彻底,建议没学过或者没学好面向对象的同学再看看面向对象. 其次切入正题. 先创建数据库,这步自己写. DROP TABLE IF EXISTS `country` ...

  8. adb server is out of date.killing的解决办法

    当把手机连接到电脑端口运行adb程序调试时,出现了下面这样的情况: 分析:出错的原因是adb的端口被其他程序的进程占领了,所以要做的就是找到并kill该进程.     工具/原料   cmd.exe. ...

  9. Unknown SSL protocol error in connection to xxx:443

    使用git从远程下载时,出现Unknown SSL protocol error in connection to xxx:443 错误. 很有可能是被墙在了外面,这里针对墙在外面的情况. 设置代理服 ...

  10. php如何互换一个数组的首尾元素 中间不变 首尾互换

    群里有人提出一个问题 如何互换一个数组的首尾元素 中间不变 首尾互换 代码如下: <?php $array=array(1,2,3,4,5,6,7,8,9,10); $first=array_s ...