一、SpringMVC 概述:
Spring 为展现层提供的基于 MVC 设计理念的优秀的
Web 框架,是目前最主流的 MVC 框架之一
• Spring3.0 后全面超越 Struts2,成为最优秀的 MVC 框架
•Spring MVC 通过一套 MVC 注解,让 POJO 成为处理请 求的控制器,而无须实现任何接口。
•支持 REST 风格的 URL 请求
• 采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性
Spring MVC是结构最清晰的MVC Model 2实现。
它的Action也不叫Action,而是称做Controller;Controller接收request, response参数,然后返回ModelAndView(其中的Model不是Object类型,而是Map类型)。但在其它的Web Framework中,Action返回值一般都只是一个View Name;Model则需要通过其它的途径(如request.attribute,Context参数,或Action本身的属性数据)传递上去。
SpringMVC工作流程:
Spring MVC 特点
清晰的角色划分,每一个角色都可以由一个专门的对象来实现:
控制器(controller)
验证器(validator)
命令对象(command object)
表单对象(form object)
模型对象(model object)
Servlet分发器(DispatcherServlet)
处理器映射(handler mapping)
视图解析器(view resolver)等。
可以非常简单的设计出干净的WEB层,和薄薄的WEB层
使用Spring MVC可以更加简洁地开发WEB层
天生与Spring框架集成(IOC、AOP等)
二、SpringMVC核心组件
1、DispatcherServlet:前端控制器,核心
作用:接收请求,响应结果,相当于转发器,中央处理器,降低了组件之间的耦合性。
用户发送请求交给DispatcherServlet,DispatcherServlet是整个流程控制的中心,由它调用其他组件处理用户请求,分发到具体的对应Controller,从而获取到需要的业务数据Model,Model再通过DispatcherServlet传递给View完成页面呈现;DispatcherServlet的存在降低了组件的之间的耦合性。
配置DispatcherServlet:
2、HandlerMapping:处理器映射器
作用:根据请求的URL,找到对应的Handler,帮助DispatcherServlet找到对应的Controller
HandlerMapping负责根据用户请求找到Handler即处理器,SpringMVC提供了多种不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
HandlerMapping执行流程
3、HandlerInterceptor:Handler执行前后拦截器
HandlerInterceptor是个接口,里面包含三个方法:preHandle、postHandle、afterCompletion
分别在Handler执行前、执行中、执行完成后执行的三个方法
4、HandlerExecutionChain:HandlerMapping返回给DispatcherServlet的执行链
HandlerMapping返回给DispatcherServlet的不光有Handler,还有HandlerInterceptor
preHandle——>ControllerMethod——>postHandle——>afterCompletion
这个链如何实现的呢?使用了Java的反射机制reflection
5、HandlerAdapter:处理器适配器
作用:将各种Controller适配成DispatcherServlet可以使用的Handler,通过特定规则(HandlerAdapter要求的规则)去执行Handler
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
6、Handler:处理器(需要工程师开发)
注意:编写Handler时需要HandlerAdapter的要求去做,这样HandlerAdapter才可以正确执行Handler
Handler是继DispatcherServlet前端控制器的后台控制器,在DispatcherServlet控制下对用户请求进行处理,Handler涉及业务需求,所以需要工程师针对用户需求进行开发,最终返回业务数据
7、ModelAndView:SpringMVC中对Model的一种表示形式
SpringMVC中有Model、Map,但是SpringMVC都会将其转化为ModelAndView,Model、Map都是ModelAndView的具体表现
8、ViewResolver:视图解析器
作用:进行视图解析,根据逻辑视图名解析成真正的视图View
ViewResolver负责将处理结果生成View视图,ViewResolver首先根据逻辑视图名解析成具体的页面地址,然后对View进行渲染,将处理结果通过页面展示给用户;SpringMVC提供了很多类型View视图,包括:jstlView、freemarkerView、pdfView、jsp、html等。
9、View:视图(需要工程师开发jsp、html)
View是一个接口,实现类支持不同的类型(jsp、html、freemarker、pdf等)
三,SpringMVC三种部署方式
1.SpringMVC的基本配置
使用SpringMVC开发前需要把meave依赖和Spring所依赖的jar包导进来,idea和ecilpse有所不同,自行百度吧(还可以设置成阿里云的在线依赖库,速度相对比较快些),下面我使用的是ieda
使用IDEA创建一个基于spring的Java项目:
步骤1:选择New Project,在弹出窗口中勾选spring和Web Application(此项也可以不选)。
当勾选Spring选项时,窗口下方的liraries出现load version…进度条,表示在网上检查Spring的可用版本。等待一定时间后,会显示最新可用版本,如下所示。
步骤2:选择下一步,此时会自动从互联网下载spring相关的jar包。
创建SpringMVC工程,架构如下:
重要两个配置文件为: web.xml和springmvc-config.xml。打开web.xml文件,文件配置如下所示:
SpringMVC Demo
*.jsp
*.jspf
UTF-8
true
/WEB-INF/jsp/base.jspf
true
text/html
EncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
EncodingFilter
/*
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
/WEB-INF/config/springmvc-config.xml
1
springmvc
/
打开springmvc-config.xml配置文件,文件内容如下所示:
text/plain;charset=UTF-8
text/html;charset=UTF-8
application/json;charset=UTF-8
步骤1:在controller包中添加HelloWorldController类,该类为Spring MVC控制器类,主要参考代码如下:
package jee.course.ch10.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpSession;
@Controller
public class HelloWorldController {
//返还字符串,类似servlet的out。println()
//演示一个简单的spring MVC应用,返回字符串
@ResponseBody
@RequestMapping(value="/hello")
public String hello(){
return "hello";
}
//演示返回一个jsp页面传递数据
@RequestMapping("/viewJsp")
public String viewJsp(Model model){
model.addAttribute("value","i am from springmvc value");
return "hello";
}
//演示使用session传递参数
@RequestMapping("/session")
public String useSession(HttpSession session){
session.setAttribute("msg","我是使用session使用session传递参数");
return "session";
}
}
JSP页面结构如下:
(1)测试/hello路径的访问,
return “hello”; 表示在页面中输出一个字符串hello,重点在于理解@ResponseBody,该注解表示返回一个字符串,而不是返回一个HTML页面。看函数注解。测试如下:
(2)测试http://localhost:8080/springmvc1/viewJsp, 重点理解@RequestMapping("/viewJsp")的使用,return "hello";表示跳转到hello.jsp页面。同时
public String viewJsp(Model model) 表示将model传入到控制器。其中Model为spring内置类。
model.addAttribute("value", "I am from SpringMvc Value");
表示往该页面传递一个参数,名称为value。
在hello.jsp页面中输出从控制器传递过来的参数。hello.jsp代码如下:
程序测试结果如下:
(3)测试http://localhost:8080/springmvc1/session。该方法和上一个相似,把值通过session传递到jsp页面。
同时将session作为参数传入到控制。
public String useSession(HttpSession session)
测试结果如下:
2.基于Spring MVC获取请求参数:
book.java
/*******************************************************************
* * Copyright (C) 电子科技大学中山学院计算机学院
* * All rights reserved.
* *
* 文件名:springMvc_1 Book.java
* 描述:TODO
*
* @Author:Hevean
* @Date:2017年3月7日
* @Version:1.0.0
* *
* *******************************************************************/
package jee.course.ch10.entity;
public class Book {
String bookname;
String author;
double price;
int category;
String description;
String press;
public Book() {
}
@Override
public String toString() {
return "Book{" +
"bookname='" + bookname + '\'' +
", author='" + author + '\'' +
", price=" + price +
", category=" + category +
", description='" + description + '\'' +
", press='" + press + '\'' +
'}';
}
/**
* 构造函数:@param bookname
* 构造函数:@param author
* 构造函数:@param price
* 构造函数:@param category
* 构造函数:@param picUrl
* 构造函数:@param description
* 构造函数:@param press
*/
public Book(String bookname, String author, double price, int category,
String description, String press) {
super();
this.bookname = bookname;
this.author = author;
this.price = price;
this.category = category;
this.description = description;
this.press = press;
}
public String getBookname() {
return bookname;
}
public void setBookname(String bookname) {
this.bookname = bookname;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getCategory() {
return category;
}
public void setCategory(int category) {
this.category = category;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPress() {
return press;
}
public void setPress(String press) {
this.press = press;
}
}
步骤1:添加BookController控制器类,该类主要演示如何获取客户端传递的参数。BookController的参考代码如下:
package jee.course.ch10.controller;
import jee.course.ch10.entity.Book;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/book")
public class BookController {
//跳转到addbook.jsp
//限制HTTP的请求类型为get
@RequestMapping(value = "/add",method = RequestMethod.GET)
public String toBookForm(){
return "addBook";
}
//演示使用pojo实体类自动填充表单数据
//使用model传值
@RequestMapping(value = "/add",method = RequestMethod.POST)
public String addBook(Book book,Model model){
System.out.println(book);
model.addAttribute("book",book);
return "viewBook";
}
//演示url传递参数
//查看ID为10的图书/book/10
@RequestMapping(value = "/{id}",produces = "text/html;charset=UTF-8")
@ResponseBody
public String getBook(@PathVariable("id") Long id){
return "您目前查看的图书ID为:"+id;
}
//演示使用@RequParam获取参数
@RequestMapping("/view")
@ResponseBody
public String viewBook(@RequestParam("id") Long id){
return "您查看的图书ID为"+id;
}
//演示重定向到我另外一个控制器
@RequestMapping(value = "toHello")
public String toHelloController(){
return "redirect:/hello";
}
}
(1)测试http://localhost:8080/springmvc1/book/add。跳转到添加图书界面。
相应的代码为:
(2)点击添加图书,后台对应的代码为:
同时跳转到viewBook.jsp页面,viewBook.jsp代码为:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
图书信息
图书添加成功!
图书信息
图书名称: ${book.bookname}
图书价格: ${book.price}
出版社: ${book.press}
类别: ${book.category}
页面结果如下:
(3)测试通过@RequestParam获取客户端提交的参数。
http://localhost:8080/springmvc1/book/view?id=100
(4)测试通过@PathVariable获取路径参数。代码为:
(5)测试重定向到另一个控制器。
说明:默认情况下控制器方法返回一个字符串值,表示返回的视图为一个jsp页面。如果要从一个控制器跳转到另一个控制器,可以使用下面方法:
在控制器的return语句字符串前面添加forward:或者redirect:。 其中forward:表示可以带数据的跳转,和request的forward相同,使用redirect:表示重定向。
return "forward:aaaa/bbbb.do";
return "redirect:aaaa/bbbb.do";
访问地址:http://localhost:8080/springmvc1/book/toHello
代码如下:
测试结果如下:
3.Spring MVC获和Ajax的结合使用
步骤1:ajax.html页面代码。
Title
test
1.演示获取JSON格式的数据对象
2.演示获取JSON格式的数据对象
3.演示使用Ajax提交图书数据
运行界面如下
后台代码AjaxParamsController如下:
package jee.course.ch10.controller;
import jee.course.ch10.entity.Book;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
//用于演示与ajax提交数据的交互
@Controller
public class AjaxParamsController {
//1.演示使用@RequestBody读取Ajax提交的JSON格式的数据
//说明:读取Ajax发送过来的数组对象并转换为List对象
@ResponseBody
@RequestMapping(value = "/delTickets", method = RequestMethod.POST)
public String delMultiTickets(@RequestBody List idList){
//打印输出要删除id
System.out.println("接收到Ajax请求.");
StringBuffer sb = new StringBuffer();
for (Long id: idList) {
sb.append(id+",");
}
String resMsg = "##成功删除的票据id为:"+sb.toString();
return resMsg;
}
//2.演示使用@RequestBody读取Ajax表单提交的JSON格式数据
//说明:读取Ajax发送过来的数组对象并转换为Book类型
@ResponseBody
@RequestMapping(value = "/ajaxAddBook", method = RequestMethod.POST)
public String ajaxAddBook(@RequestBody Book book){
//打印输出要删除id
System.out.println("接收到Ajax请求.");
System.out.println("添加的图书:" + book);
String resMsg = "操作成功:"+book.toString();
return resMsg;
}
@RequestMapping(value = "/json_book", method = RequestMethod.GET)
@ResponseBody
public Book getJsonBook(){
Book book = new Book();
book.setAuthor("金庸");
book.setBookname("笑傲江湖");
book.setPress("广东文学出版社");
book.setPrice(90.5);
return book;
}
}
发送表单数据: