Spring MVC
Posted xue_yun_xiang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring MVC相关的知识,希望对你有一定的参考价值。
一、概述
mvc:MVC 设计模式,m(model 模型) v(view 视图) c(controller 控制器)
springmvc:就是 spring 按照mvc 模式开发的一个轻量级 mvc 框架,。它与Struts2框架一样,都属于MVC框架
Struts2 也是实现 mvc ,但是springmvc 替代Struts2
springmvc 就等价于以前用到的BaseServlet ,BaseServlet用于路径的分发,在springmvc也有类似的Servlet 叫做DispatcherServlet,用于路径分发
区别:整个应用中只有一个DispatcherServlet,不存在其他Servlet
Spring MVC具有以下特点:
- 是Spring框架的一部分,可以方便的利用Spring所提供的其他功能。
- 灵活性强,易于与其他框架集成。
- 提供了一个前端控制器DispatcherServlet,使开发人员无需额外开发控制器对象。
- 可自动绑定用户输入,并能正确的转换数据类型。
- 内置了常见的校验器,可以校验用户输入。如果校验不能通过,那么就会重定向到输入表单。
- 支持国际化。可以根据用户区域显示多国语言。
- 支持多种视图技术。它支持JSP、Velocity和FreeMarker等视图技术。
- 使用基于XML的配置文件,在编辑后,不需要重新编译应用程序。
2、入门实例
1、创建maven的web工程
2、导入依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<!--在当前pom 或者父类pom 中声明属性 -->
<spirng.version>5.0.16.RELEASE</spirng.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- 添加 servlet 依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<!-- spring 核心-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spirng.version}</version>
</dependency>
<!--
spring aop
-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spirng.version}</version>
</dependency>
<!--
spring aop aspectj
-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.12</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.12</version>
</dependency>
<!--
spring mvc 相关
-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spirng.version}</version>
</dependency>
</dependencies>
3、配置web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--
声明DispatcherServlet
-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--
配置该sever 对应的 springmvc 路径
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<!--
路径是 servlet-name-servlet.xml 标准格式
-->
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--
如果 访问台服务器的资源 找不到对应的路径 ,springmvc servlet
localhost:8080/test 没有
将/test 给到 DispatcherServlet ,找对应的 /test 对应处理方法
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
4、在resource 下创建springmvc-servlet.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
在容器加入后端控制器 并设置id 为/hellController
该控制器中的 public ModelAndView handleRequest()对应 路径为 /hellController
当前方法 handleRequest() 可以处理前端浏览器发起的请求 localhost:8080/hellController
-->
<bean id="/hellController" class="com.qfedu.controller.HellController"></bean>
</beans>
5、创建HellController
/**
* 创建一个后端控制器 控制类
*
* 实现controller
*/
public class HellController implements Controller {
@Override// handleRequest 处理请求 当前方法就是一个 处理器
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
// 封装了 模型 和 视图
ModelAndView modelAndView = new ModelAndView();
// 设置视图的路径
// 从 webapp 下根路径开始算
modelAndView.setViewName("/hello.jsp");
//相当于在 httpServletRequest设置 属性
modelAndView.addObject("msg", "HellController");
return modelAndView;
}
}
6、在webapp 创建hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
msg:${msg}
</body>
</html>
7、添加tomcat运行
三、springmvc 请求流程
DistpacherServlet:前端控制器 一个servelt 用来分发请求 相当于BaseServelet
HelloController:后端控制器 一个类 用来处理前端请求
public ModelAndView handleRequest: 处理器(hander) 用来处理前端请求,响应数据
BeanNameUrlHandlerMapping:处理器映射器 map<“路径”,“控制器 及处理器方法 还有参数”>
SimpleControllerHandlerAdapter:处理器适配器 兼容处理器(根据处理器类型不同,调用他方法)
InternalResourceViewResolver:视图解析器 解析处理器返回的结果集 转化为视图jsp
顺序:
1、用户发送请求至前端控制器DispatcherServlet。
2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、Controller执行完成返回ModelAndView。
7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、ViewReslover解析后返回具体View.
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet响应用户。
<?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">
<!--
在容器加入后端控制器 并设置id 为/hellController
该控制器中的 public ModelAndView handleRequest()对应 路径为 /hellController
当前方法 handleRequest() 可以处理前端浏览器发起的请求 localhost:8080/hellController
-->
<bean id="/hellController" class="com.qfedu.controller.HellController"></bean>
<!--
处理器映射器 map <路径,HellController对象 及处理器方法(handleRequest) >
如果我们不显示写,容器也会为我们加载
-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!--
处理器适配器 兼容各种处理器,调用处理器方法(handleRequest 只是一种处理器)
插排:墙上插孔只有一个三叉, 如果需要手机充电 需要一个 插排 手机插在插排 两插孔
以上就是一种适配
可以驱动 三插 两插 欧规插座
墙上的插排:只能三插
-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!--
视图解析器: 作用就是用来解析 处理器返回的结果(ModelAndView ) 转换为视图(jsp)
如果我们不显示写,容器也会为我们加载
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
</bean>
</beans>
4、springmvc 核心类 及注解
DispatcherServlet
DispatcherServlet:前端控制器,是整个springmvc 的中枢,负责路径分发道不同的处理器,需要在web.xml声明
<!--
声明DispatcherServlet
-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--
配置该sever 对应的 springmvc 路径
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<!--
路径是 servlet-name-servlet.xml 标准格式
-->
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--
如果 访问台服务器的资源 找不到对应的路径 ,springmvc servlet
localhost:8080/test 先找对应的Servlet 没有
将/test 给到 DispatcherServlet ,找对应的 /test 对应处理器方法
/ 再找不到其他路径时的 默认处理 叫给DispatcherServlet
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
@Controller注解
实现处理器两种方式:
1.实现Controller接口 重写 public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
2.创建一个类使用 @Controller 标记 在其内部的方法中使用 @RequestMapping 标记方法,这个方法就是处理器
/**
* 第一个 控制器
*/
@Controller // 1.将当前类加入到容器 2.标记当前类是一个 控制器 类
public class FirstController {
// @RequestMapping("/test1") // 标记当前方法是处理器 对应路径 为 /test1
// @RequestMapping(value = {"/test1_a","/test1_b"}) // 为当前处理器配置多个路径
// @RequestMapping(path = {"/test1_c","/test1_d"}) // 为当前处理器配置多个路径 path value 不能同时设置
@RequestMapping(path = {"/test1_c","/test1_d"},method = {RequestMethod.POST}) // 当前处理器支持 get post
public ModelAndView test1(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("/hello.jsp");
modelAndView.addObject("msg", "test1");
return modelAndView;
}
}
激活mvc 功能
<!--
包扫描器 将com.qfedu.controller 所有 生成bean的注解 和 注入属性的注解 生效
-->
<context:component-scan base-package="com.qfedu.controller"></context:component-scan>
<!--
激活 注解mvc 相关功能
-->
<mvc:annotation-driven></mvc:annotation-driven>
@RequestMapping
两种用法
标记在方法上 ,该方法就是一个处理器 必须的写
标记在类上,所有访问该控制器下的处理器 都必须补全当前@RequestMapping 内的路径
可以不写
/**
* 第一个 控制器
*/
@Controller // 1.将当前类加入到容器 2.标记当前类是一个 控制器 类
@RequestMapping("/first") // 标记在控制器上面 所有访问该 控制器下的处理器路径时都必须补全当前 @RequestMapping("/first")
// /first/test1_c /first/test2
public class FirstController {
// @RequestMapping("/test1") // 标记当前方法是处理器 对应路径 为 /test1
// @RequestMapping(value = {"/test1_a","/test1_b"}) // 为当前处理器配置多个路径
// @RequestMapping(path = {"/test1_c","/test1_d"}) // 为当前处理器配置多个路径 path value 不能同时设置
@RequestMapping(path = {"/test1_c","/test1_d"},method = {RequestMethod.POST}) // 当前处理器支持 get post
public ModelAndView test1(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("/hello.jsp");
modelAndView.addObject("msg", "test1");
return modelAndView;
}
@RequestMapping("/test2") // 标记在方法上 该方法就是一个处理器
public ModelAndView test2(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("/hello.jsp");
modelAndView.addObject("msg", "test2");
return modelAndView;
}
}
组合注解
Spring框架的4.3版本中,引入了新的组合注解,来帮助简化常用的HTTP方法的映射,并更好的表达被注解方法的语义。
- @GetMapping:匹配GET方式的请求;
- @PostMapping:匹配POST方式的请求;
- @PutMapping:匹配PUT方式的请求;
- @DeleteMapping:匹配DELETE方式的请求;
- @PatchMapping:匹配PATCH方式的请求。
// @RequestMapping(value = "/test3",method = RequestMethod.GET) // 表明当前处理器支持 get 请求
@GetMapping("/test3") // 复合注解 等价于 @RequestMapping(value = "/test3",method = RequestMethod.GET)
public ModelAndView test3(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("/hello.jsp");
modelAndView.addObject("msg", "test3");
return modelAndView;
}
@PostMapping("/test4")// 复合注解 当前请求支持 post 请求
public ModelAndView test4(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("/hello.jsp");
modelAndView.addObject("msg", "test4");
return modelAndView;
}
请求处理方法自带的参数和返回类型
处理器返回值类型有三种
ModelAndView: 数据和视图的混合体
String : 返回字符串
jsp路径
以 forward:/路径 转发
以redirect:/路径 重定向
void: 没有返回值
处理器方法 中默认传递的参数:
javax.servlet.ServletRequest / javax.servlet.http.HttpServletRequest 请求相关
javax.servlet.ServletResponse / javax.servlet.http.HttpServletResponse 响应相关
javax.servlet.http.HttpSession 会话先关
java.util.Map / org.springframework.ui.Model /org.springframework.ui.ModelMap 和request中属性相关
/**
*
* Map map
* Model map
* ModelMap map
* 都是向request 中添加属性
*
*
* @param request
* @param map
* @return
*/
@RequestMapping("/test5") // 当前处理器中的 默认参数如果写了 Dispatcher 调用是会给传进来
public String test5(HttpServletRequest request, Model model){
// 在请求中写入属性
// request.setAttribute("msg", "test5");
// 相当于 request.setAttribute("msg", "test5");
// ModelMap map
// map.put("msg", "test5");
model.addAttribute("msg", "test5");
// jsp 路径
return "/hello.jsp";
}
/**
* 没有返回结果
* @param request
* @param response
* @throws IOException
*/
@RequestMapping("/test6") // 当前处理器中的 默认参数如果写了 Dispatcher 调用是会给传进来
public void test6(HttpServletRequest request, HttpServletResponse response) throws IOException {
//从请求得到 参数
String msg = request.getParameter("msg");
response.getWriter().write("/test6-msg:"+msg);
}
/**
* 返回字符串 以forward:开头进行转发
* @return
*/
@RequestMapping("/test7")
public String test7(){
// 转发到 test6 处理器中
return "forward:/first/test6";
}
/**
* 返回字符串 以redirect:开头进行重定向
* @return
*/
@RequestMapping("/test8")
public String test8(){
// 转发到 test6 处理器中
return "redirect:/first/test6";
}
ViewResolver视图解析器
视图解析器:作用就是将处理器返回的数据(String ModelAnView)转换视图
附件功能 可以为我们自动补全 jsp 的路径
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--
后续所有 处理器返回的 jsp 路径 会自动补全前缀和后缀
配置jsp 路径前缀 /jsp/
/jsp/message.jsp
-->
<property name="prefix" value="/jsp/"></property>
<!--
配置jsp 路径后缀
-->
<property name="suffix" value=".jsp"></property>
</bean>
常见错误:
5、数据绑定介绍
数据绑定 就是处理器如何接受 前端传递的数据
接受基本类型参数
/**
*
* int id 接受基本类型数据
* @param id
* @param model
* @return
*/
// http://localhost:8080/findStudentById?id=100 id 必须传递 否则有类型转换错以上是关于Spring MVC的主要内容,如果未能解决你的问题,请参考以下文章
ASP.net MVC 代码片段问题中的 Jqgrid 实现
通过 Spring MVC 框架包含其他 JSP 是个好主意吗?