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. 虚拟机和Docker的异同

    [摘要]各种虚拟机技术开启了云计算时代:而Docker,作为下一代虚拟化技术,正在改变我们开发.测试.部署应用的方式.那虚拟机与Docker究竟有何不同呢? 首先,大家需要明确一点,Docker容器不 ...

  2. Apache ab使用POST参数进行压力测试 (服务端为Django)

    2016年07月07日 15:04:51 常城 阅读数:13774更多 个人分类: PythonLinux架构   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.cs ...

  3. EasyUI 异步Tree

    用etmvc framework返回json数据.创建HTML标记 <ul id="tt"></ul> 创建jQuery代码我们使用url属性来指向远程数据 ...

  4. linux -- ubuntuserver 安装图形界面

    安装Gnome桌面 1.安装全部桌面环境,其实Ubuntu系列桌面实际上有几种桌面应用程序,包括Ubuntu-desktop.Kubunut-desktop和Xubuntu- desktop. 我们就 ...

  5. 数据驱动ddt+excel数据读取

    我们可以将测试数据用excel存储,再用ddt去传入,不过我们需要安装对应的库,因为python是无法操作excel的 1.安装第三方库xlrd 2.创建一个excel表格,将需要测试的数据保存 3. ...

  6. string类(四、字符串比较相关)

    string类比较相关: 1. string.Compare [static] 1/ string.Compare(string A, string B); 比较两个string,返回整数表示二者在排 ...

  7. 在VS中调试javascript脚本

    https://blog.csdn.net/u010228798/article/details/78207375

  8. vue2.0中子组件通过v-modal改变父组件中的值

    父组件代码: <template lang="pug"> div p this is father child(v-model="data") &l ...

  9. 通过AnimationSet 同步或一部播放多个动画 Android 属性动画(Property Animation) 完全解析 (下)

    AnimationSet提供了一个把多个动画组合成一个组合的机制,并可设置组中动画的时序关系,如同时播放,顺序播放等. 以下例子同时应用5个动画: 播放anim1: 同时播放anim2,anim3,a ...

  10. <span>和<div>标签的隐藏和显示切换

    <div class="axb"> <span id="tipStep1" class="fl" >第一步显示< ...