3、基于注解的SpringMVC
在 SpringMVC 实际开发中,我们通常都会采用注解开发。
3.1、配置文件
web.xml:注册 DispatcherServlet
- 关联配置文件
- 启动优先级
-
<url-pattern>
-
/
:匹配所有请求,不包括 JSP; -
/*
:匹配所有请求及 JSP - 如果填写了
/*
,Controller 处理业务后返回的 JSP页面会再次被拦截请求,会无限嵌套。
-
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 注册DispatcherServlet -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 关联配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!-- 启动优先级:越小越优先启动 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!-- 不能是/* -->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
springmvc-servlet.xml
与基于配置的SpringMVC
的配置相比:
- 添加注解支持,不再需要手动注册 Controller
- 内部资源视图解析器
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
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">
<!-- 扫描包 -->
<context:component-scan base-package="indi.jaywee.controller"/>
<!-- 过滤静态资源 -->
<mvc:default-servlet-handler/>
<!-- 注解驱动 -->
<mvc:annotation-driven/>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!-- 后缀 -->
<property name="suffix" value=".jsp"/>
</bean>
</beans>
3.2、Controller
HelloController
@Controller
public class HelloController {
/**
* 使用 @RequestMapping注解来处理映射关系,后接请求路径(如"/hello")
* 方式一:使用 ModelAndView来封装模型和视图,返回 ModelAndView
*/
@RequestMapping("/hello")
public ModelAndView hello(ModelAndView mv) {
// 可以调用Service层方法,获取模型对象
// 添加数据模型
mv.addObject("msg", "Hello Annotation:ModelAndView");
// 封装要渲染、跳转的视图
mv.setViewName("hello");
return mv;
}
/**
* 使用 @RequestMapping注解来处理映射关系,后接请求路径(如"/hello")
* 方式二:使用 Model来封装模型,返回 ViewName
*/
@RequestMapping("/hello1")
public String hello(Model model) {
// 可以调用Service层方法,获取模型对象
// 添加数据模型
model.addAttribute("msg", "Hello Annotation:Model");
// 返回视图
return "hello";
}
}
3.3、跳转页面及结果
hello.jsp
<h1>${msg}</h1>
测试结果
3.4、小结
注解开发 SpringMVC 全步骤
- 新建 Maven 工程,导入依赖;
- 删除 src 目录,作为父工程;
- 新建 module,添加 web 框架支持:在项目结构中手动添加 lib 目录;
-
web.xml:注册 DispatcherServlet
- 关联配置文件;
- 启动优先级;
- springmvc-servlet.xml:添加注解支持、内部资源视图解析器;
- 编写 Controller,使用注解;
- 编写页面。
基于配置 VS 基于注解
-
web.xml 完全相同;
-
springmvc-servlet.xml
-
基于配置:处理器映射、处理器适配器、内部资源视图解析器;
-
处理器映射:默认配置,不需要显式配置;
-
处理器适配器:默认配置,不需要显式配置;
-
内部资源视图解析器:必须显式配置;
-
将 Controller 注册到 IOC 容器中:相当于原来在 web.xml 中注册 Servlet。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 处理器映射 --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <!-- 处理器适配 --> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <!-- 视图解析 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <!-- 前缀 --> <property name="prefix" value="/WEB-INF/jsp/"/> <!-- 后缀 --> <property name="suffix" value=".jsp"/> </bean> <!-- 注册Controller --> <bean id="/hello" class="indi.jaywee.controller.HelloController"/> </beans>
-
-
基于注解:Spring 注解开发
-
扫描包:扫描指定包下的 Bean ,被扫描的 Bean 中包含的类级别的注解才会生效,Bean 才会被注册到容器中;
-
过滤静态资源:如 CSS、JS、HTML、MP3、MP4...
-
注解驱动:在 Spring 中一般使用 @RequestMapping 注解来处理映射关系,使用该注解需要注册
处理器映射
和处理器适配器
,annotation-driven 自动注入以上两个实例; -
内部资源视图解析器。
<!-- 扫描包 --> <context:component-scan base-package="indi.jaywee.controller"/> <!-- 过滤静态资源 --> <mvc:default-servlet-handler/> <!-- 注解驱动 --> <mvc:annotation-driven/> <!-- 视图解析 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <!-- 前缀 --> <property name="prefix" value="/WEB-INF/jsp/"/> <!-- 后缀 --> <property name="suffix" value=".jsp"/> </bean>
-
-
-
Controller
-
基于配置:
-
继承 Controller 接口,重写 handleRequest 方法;
-
通过 ModelAndView 封装模型和视图,返回 ModelAndView:
public class HelloController implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { ... } }
-
需要在 springmvc-servlet.xml 中注册 Bean 并映射请求路径;
<bean id="/hello" class="indi.jaywee.controller.HelloController"/>
-
如果有多个请求,通过获取参数判断方法名实现 Controller 复用,或编写多个 Controller。
-
-
基于注解
-
使用 @Controller 注解来注册 Bean,自定义方法;
-
通过 ModelAndView 封装模型和视图,返回 ModelAndView。或通过 Model 封装模型,返回视图名;
-
在方法上使用
@RequestMapping("/xxx")
来映射请求路径:@Controller public class HelloController { @RequestMapping("/hello1") public String hello(Model model) { ... } }
-
如果有多个请求,自定义编写多个方法。
-
-
@RequestMapping
@RequestMapping 注解用于映射请求 URL 到控制器类或处理程序方法,,可以作为类级别、类内部的注解。
-
在类上没有使用,只在方法上使用:直接访问
类内部注解的映射路径
:例如:映射的路径是
/hello
@Controller public class HelloController { @RequestMapping("/hello") public ModelAndView hello(ModelAndView mv) { ... } }
-
在类上和方法上都使用:访问
类级别注解的映射路径 / 类内部注解的映射路径
,即类级别注解的映射路径作为父路径:例如:映射的路径是
myHello / hello
@Controller @RequestMapping("/myHello ") public class HelloController { @RequestMapping("/hello") public ModelAndView hello(ModelAndView mv) { ... } }
4、RESTful风格
4.1、概念
RESTful 是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。
基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
4.2、功能
-
资源:互联网所有的事物都可以被抽象为资源
-
资源操作:使用不同方法操作资源,POST(添加)、DELETE(删除)、PUT(更新)、GET(查询);
传统方法操作资源:通过不同的请求参数来实现不同的功能,请求地址不同。
- 添加:
http://127.0.0.1/item/insertItem.action
- 删除:
http://127.0.0.1/item/deleteItem.action?id=1
- 更新:
http://127.0.0.1/item/updateItem.action
- 查询:
http://127.0.0.1/item/getItem.action?id=1
RESTful风格操作资源:通过不同的请求方式来实现不同的功能,请求地址相同。
- 添加:
http://127.0.0.1/item
- 删除:
http://127.0.0.1/item/1
- 更新:
http://127.0.0.1/item
- 查询:
http://127.0.0.1/item/1
4.3、测试
Controller
使用 @PathVariable 注解,将参数值绑定到 URI 模板变量上。
@Controller
public class RestfulController {
@RequestMapping("/addition/{a}/{b}")
public String addition(@PathVariable int a,@PathVariable int b, Model model) {
int result = a + b;
model.addAttribute("result", "结果:" + result);
return "test";
}
}
跳转视图:test.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>result</title>
</head>
<body>
${result}
</body>
</html>
测试
-
正确输入:
-
错误输入:客户端请求的语法错误
method属性
使用 method 属性约束请求的类型,指定类型的请求才可访问。
@RequestMapping(value = "/multiplication/{a}/{b}", method = RequestMethod.POST)
public String multiplication(@PathVariable int a, @PathVariable int b, Model model) {
int result = a * b;
model.addAttribute("result", "结果:" + result);
return "test";
}
也可以使用 @RequestMapping 的衍生注解:@PostMapping
@PostMapping("/multiplication/{a}/{b}")
public String multiplication(@PathVariable int a, @PathVariable int b, Model model) {
int result = a * b;
model.addAttribute("result", "结果:" + result);
return "test";
}
测试:通过地址栏访问默认是 GET 请求,而方法指定的是 POST 请求,报 405:
将方法改为 GET 请求之后,正常访问
4.4、请求类型
@RequestMapping 注解能够处理 HTTP 请求的方法,包括 GET, PUT, POST, DELETE , PATCH 等等。
-
所有的地址栏请求默认都会是 HTTP GET 类型的。
-
@RequestMapping 注解有以下几个变体,是组合注解
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PatchMapping
- 以上注解相当于:@RequestMapping(method =RequestMethod.XXX)