@Controller和@RequestMapping注解

在前面写一个控制器需要继承Controller并重写方法,而且还要到配置文件中注册这个控制器,是比较麻烦的,而我们可以使用@Controller和@RequestMapping注解来代替这种操作,首先我们需要写编写springmvc-servlet.xml配置文件:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:mvc="http://www.springframework.org/schema/mvc"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
  8. <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
  9. <context:component-scan base-package="com.wjh.controller"/>
  10. <!-- 让Spring MVC不处理静态资源 -->
  11. <mvc:default-servlet-handler/>
  12. <!--支持mvc注解驱动在spring中一般采用@RequestMapping注解来完成映射关系要想使
  13. @RequestMapping注解生效必须向上下文中注册DefaultAnnotationHandlerMapping
  14. 和一个AnnotationMethodHandlerAdapter实例,这两个实例分别在类级别和方法级别处理。
  15. 而annotation-driven配置帮助我们自动完成上述两个实例的注入。
  16. -->
  17. <mvc:annotation-driven/>
  18. <!--配置视图解析器:DispatcherServlet给他的ModelAndView-->
  19. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
  20. <!--前缀-->
  21. <property name="prefix" value="/WEB-INF/jsp/"/>
  22. <!--后缀-->
  23. <property name="suffix" value=".jsp"/>
  24. </bean>
  25. </beans>

可以看到对比使用配置的方式实现Spring MVC,采用注解的配置文件简单很多,不需要注册前端控制器、控制器映射器、控制器了(但视图解析器仍然需要手动注册,页面 ={ 视图解析器前缀 } + viewName +{ 视图解析器后缀 }),直接由Spring自动注册了,但是为了保证Spring能找到控制器,需要在配置文件中声明组件扫描:

  <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
    <context:component-scan base-package="com.wjh.controller"/>

@Controller注解类型用于声明Spring类的实例是一个控制器,@RequestMapping注解用于映射url到控制器类或一个特定的处理程序方法,可用于类或方法上。如果用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

package com.wjh.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author wjh
 * @date 2021/7/20 12:45
 * @Package com.wjh.controller
 */
@Controller
public class HelloController {
    @RequestMapping("/hello")
    public String sayHello(Model model) {
        //向模型中添加属性msg与值,可以在JSP页面中取出并渲染
        model.addAttribute("msg", "hello,SpringMVC with annotation");
        //web-inf/jsp/hello.jsp
        return "hello";
    }
}

如果使用注解开发,我们不需要返回ModleAndView对象了,只需要返回视图对象的前缀名即可,视图解析器会自动把参数Model对象传向视图层,而返回的String是视图解析器用于拼接视图对象的访问网站,如:上述代码返回的是hello,那么根据上述我们配置的视图解析器,会把它变成:/WEB-INF/jsp/hello.jsp,这里使用的方式是请求转发,如果使用的是重定向需要返回形如:redirect:index.jsp。不难发现,我们的两个请求都可以指向一个视图,但是页面结果的结果是不一样的,从这里可以看出视图是可以被复用的,控制器与视图之间是弱偶合关系。

RESTful风格

RESTful风格就是一个资源定位及资源操作的风格,不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。REST通常指的是REpresentational State Transfer的缩写(一般中文翻译为表述性状态转移),REST 是一种体系结构,而 HTTP 是一种包含了 REST 架构属性的协议,为了便于理解,把它的首字母拆分成不同的几个部分:

  • 表述性(REpresentational): REST 资源实际上可以用各种形式来进行表述,包括 XML、JSON 甚至 HTML——最适合资源使用者的任意形式;
  • 状态(State): 当使用 REST 的时候,我们更关注资源的状态而不是对资源采取的行为;
  • 转义(Transfer): REST 涉及到转移资源数据,它以某种表述性形式从一个应用转移到另一个应用。

简单地说,REST 就是将资源的状态以适合客户端或服务端的形式从服务端转移到客户端(或者反过来)。在 REST 中,资源通过 URL 进行识别和定位,然后通过行为(即 HTTP 方法)来定义 REST 来完成怎样的功能。
在Web开发中,常用的请求方式是GET和POST,但实际上,HTTP方法还有PATCH、DELETE、PUT 等其他值,这些方法通常会匹配CURD:

CRUD 动作 HTTP 方法
Create(增) POST
Read(查) GET
Update(改) PUT 或 PATCH
Delete(删) DELETE

但其实它们之间并没有严格的限制,有时候 PUT 也可以用来创建新的资源,POST 也可以用来更新资源。在RESTful风格中,我们可以使用同一个URL,通过约定不同的HTTP方法来完成不同的业务。如图:
使用注解开发Spring MVC - 图1
RESTful风格实例:

package com.wjh.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * @author wjh
 * @date 2021/7/20 12:45
 * @Package com.wjh.controller
 */
@Controller
public class HelloController {
    @RequestMapping(value = "/add/{a}/{b}", method = RequestMethod.GET)
    public String add(@PathVariable("a") int a, @PathVariable("b") int b, Model model) {
        model.addAttribute("msg", a + b);
        return "hello";
    }
}

运行结果(参数是手动输入的1和2):
image.png
@PathVariable是spring3.0的一个新功能:用于接收请求路径中占位符的值,通过该注解可以将URL中占位符参数{xxx}绑定到处理器类的方法形参中@PathVariable(“xxx”),注解属性值“xxx”对应URL中{}中的“xxx”。
@RequestMapping注解的method可以指定HTTP方法,所有地址默认请求都是GET方法,该注解的默认方法也是GET,只有对应的方法才能访问该接口,否则会报类似如下错误:
image.png
@RequestMapping注解有几组衍生注解:
@GetMapping 对应GET方法
@PostMapping 对应POST方法
@PutMapping 对应PUT方法
@DeleteMapping 对应DELETE方法
@PatchMapping 对应PATH方法

@GetMapping("/add/{a}/{b}")
    public String add(@PathVariable("a") int a, @PathVariable("b") int b, Model model) {
        model.addAttribute("msg", a + b);
        return "hello";
    }