SpringMVC学习笔记_01
1、JAVAEE体系结构
- JAVAEE体系结构图如下所示:
![]()
2、什么是springmvc?
- 什么是mvc?
- Model1
![]()
- Model2
![]()
- Model1
- SpringMVC是什么?
- SpringMVC是一个web层mvc框架,类似struts2。
- SpringMVC和Spring?
- Springmvc是Spring的组成部分。
- SpringMVC执行流程(运行原理)
- 回忆Struts2执行流程:
- 前端控制器:StrutsPrepareAndExcuteFilter拦截请求(控制层):拦截请求,转发请求
- 寻找Action执行,处理请求数据
- ActionMapping去寻找执行类Action --> UserAction
- 找到ActionProxy:StrutsActionProxy extends DefaultActionProxy
- 通过代理类ActionProxy根据struts.xml寻找到真正的执行类Action
- SpringMVC执行流程(运行原理),如下图所示:
![]()
- 回忆Struts2执行流程:
3、springmvc第一个程序案例
3.1、不使用jsp视图解析器+使用jsp视图解析器
(1)使用eclipse,创建一个动态的web工程
其中Dynamic web module version版本选择 2.5,这样兼容性好一些;
Default output folder设置为 WebRoot\WEB-INF\classes;
Content directory设置为 WebRoot;
更改JRE System Library[J2SE-1.5]为 JRE System Library[jre1.7.0_80];
删掉没用的库:EAR Libraries;
增加服务器运行环境库 Server Runtime,不然jsp文件会报错。

创建完项目后,将整个项目的编码改为UTF-8。
操作步骤:选中项目右键 --> Properties --> Resource --> Text file encoding --> Other中选择UTF-8。
对于动态的java web项目,为了工程目录结构的清爽,我们将引入的jar包放到“Web App Libraries”中,可以通过“小三角”选择是否“Show 'Referenced Libraries' Node ”进行调节。
对于普通的java项目,为了工程目录结构的清爽,我们将引入的jar包放到“Referenced Libraries”中,可以通过“小三角”选择是否“Show 'Referenced Libraries' Node ”进行调节。
(2)导入springmvc的jar包
本案例共16个jar,如下图所示:
(3)在web.xml配置前端控制器:DispatcherServlet(入口)
<!-- 配置前端控制器:DispatcherServlet -->
<servlet >
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
我们还需要配置springmvc.xml文件的初始化参数,如下图所示:
(4)配置springmvc.xml
参考文件位置:spring-framework-3.2.0.RELEASE\docs\spring-framework-reference\html\xsd-config.html
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
<!-- 配置处理器映射器,springmvc默认的处理器映射器 -->
<!-- BeanNameUrlHandlerMapping:根据bean(自定义的Controller)的name属性的url去寻找执行类Handler(Action)即Controller -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- 配置处理器适配器,负责执行Controller,也是springmvc默认的处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- 配置自定义的Controller:UserController -->
<bean name="/hello.do" class="com.itheima.controller.UserController"></bean>
<!-- 配置jsp视图解析器,InternalResourceViewResolver负责解析出真正的逻辑视图 -->
<!-- 后台返回逻辑视图:index,jsp视图解析器解析出真正的物理视图:前缀+逻辑视图+后缀 ==>/WEB-INF/jsps/index.jsp -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsps/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
(5)自定义Controller(相当于Struts2里面的Action)
public class UserController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 接收请求,接收参数,验证参数,处理请求
// 封装参数,调用业务方法,返回处理结果数据ModelAndView
// 演示案例中我们只模拟下而已:向前台返回数据
ModelAndView mv = new ModelAndView();
mv.addObject("hello", "like xiaoyi");
// 指定跳转的视图
// 返回真实的物理视图,省略了8、9步
// mv.setViewName("/WEB-INF/jsps/index.jsp");
// 返回逻辑视图
mv.setViewName("index");
return mv;
}
}
(6)定义视图页面
根据视图解析路径:WEB-INF/jsps/index.jsp
<body>
<h1>${hello}</h1>
</body>
(7)浏览器访问
访问地址:http://localhost:8080/day63_SpringMVC_01/hello.do
4、根据程序分析springmvc执行流程(画图)
- 该图同SpringMVC执行流程图(运行原理)
5、处理器映射器
5.1、配置默认处理器映射器(BeanNameUrlHandlerMapping)
功能:寻找Controller
根据url请求去匹配bean的name属性url,从而获取Controller
5.2、配置集中处理器映射器(SimpleHandlerMapping)
功能:寻找Controller
根据浏览器url匹配简单url的key,key通过Controller的id找到Controller
5.3、配置类名处理器映射器(ClassNameHandlerMapping)
功能:寻找Controller
直接根据类名(UserController),类名.do来访问,类名首字母小写
3个处理器映射器可以共存。均可以访问成功。
6、处理器适配器
6.1、配置默认处理器适配器(SimpleControllerHandlerAdapt)
功能:执行Controller
负责执行实现了Controller接口的后端控制器,例如:UserController,调用Controller里面的方法,返回ModelAndView。

默认处理器适配器源码分析,如下图所示:
6.2、配置请求处理器适配器(HttpRequestHandlerAdapter)
功能:执行Controller
负责执行实现了HttpRequestHandler接口的后端控制器。

演示过程:
自定义实现了接口HttpRequestHandler的实现类HttpController,如下图所示:

在springmvc.xml中配置自定义的bean,即自定义的HttpController,如下图所示:

上面的这种方式无限接近servlet的开发。
2个处理器适配器可以共存。
7、命令控制器
7.1、Controller简介
1、收集、验证请求参数并绑定到命令对象;
2、将命令对象交给业务对象,由业务对象处理并返回模型数据;
3、返回ModelAndView(Model部分是业务对象返回的模型数据,视图部分是逻辑视图名)。
- 普通控制器(继承接口Controller,继承接口HttpRequestHandler)
- 命令控制器(继承抽象类AbstractCommandController)
- 例子:跳转到添加页面,进行页面跳转,参数提交get请求或者post请求
- 参数控制器(类ParameterizableViewController)
Springmvc通过命令设计模式接受页面参数。
7.2、演示:自定义命令控制器
示例如下:
(1)自定义命令控制器
package com.itheima.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractCommandController;
import com.itheima.domain.User;
// 从页面接收参数,封装到JavaBean中,本例中的JavaBean是User
@SuppressWarnings("deprecation")
public class CommandController extends AbstractCommandController {
// 指定把页面传过来的参数封装到对象,使用命令设计模式
public CommandController() {
this.setCommandClass(User.class);
}
@Override
protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object command,
BindException errors) throws Exception {
// 参数被封装进命令对象,这个过程很复杂,我们暂时不用管它,只要知道它使用的是命令设计模式即可
// 把命令对象强转成User对象
User user = (User) command;
// 设置Model的数据,值可以是任意pojo
ModelAndView mv = new ModelAndView();
mv.addObject("user", user);
// 指定返回页面
mv.setViewName("index");
return mv;
}
}
(2)定义javaBean
package com.itheima.domain;
import java.util.Date;
public class User {
private Integer id;
private String username;
private String age;
private Date birthday;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
(3)封装参数页面
文件位置:/day63_SpringMVC_01/WebRoot/WEB-INF/jsps/add.jsp
add.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/command.do" method="post">
姓名:<input type="text" name="username" id="username"><br>
年龄:<input type="text" name="age" id="age"><br>
生日:<input type="text" name="birthday" id="birthday"><br>
地址:<input type="text" name="address" id="address"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
(4)获取参数页面
文件位置:/day63_SpringMVC_01/WebRoot/WEB-INF/jsps/index.jsp
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>${user.username}---${user.age}---${user.birthday}---${user.address}</h1>
</body>
</html>
(5)跳转到add页面
由于add页面在WEB-INF下面不能直接访问,需要通过Controller来访问。
package com.itheima.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class ToAddController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 跳转到add页面
ModelAndView mv = new ModelAndView();
mv.setViewName("add");
return mv;
}
}
(6)在springmvc.xml中配置bean
<!-- 配置自定义的CommandController:CommandController -->
<bean name="/command.do" class="com.itheima.controller.CommandController"></bean>
<!-- 配置自定义的ToAddController:ToAddController -->
<bean name="/toAdd.do" class="com.itheima.controller.ToAddController"></bean>
7.3、中文乱码解决
(1)解决get请求乱码
配置tomcat的编码,如下图所示:

(2)解决post请求乱码
在web.xml中,配置spring编码过滤器,如下所示:
<!-- 配置spring编码过滤器 -->
<filter>
<filter-name>characterEcoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEcoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
7.4、时间类型转换
在CommandController类中重写initBinder()方法,示例代码如下:
// 从页面接收参数,封装到JavaBean中,本例中的JavaBean是User
@SuppressWarnings("deprecation")
public class CommandController extends AbstractCommandController {
// 指定把页面传过来的参数封装到对象,使用命令设计模式
public CommandController() {
this.setCommandClass(User.class);
}
@Override
protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception {
// 参数被封装进命令对象,这个过程很复杂,我们暂时不用管它,只要知道它使用的是命令设计模式即可
// 把命令对象强转成User对象
User user = (User) command;
// 设置Model的数据,值可以是任意pojo
ModelAndView mv = new ModelAndView();
mv.addObject("user", user);
// 指定返回页面
mv.setViewName("index");
return mv;
}
@Override
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
String str = request.getParameter("birthday");
if (str.contains("/")) {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy/MM/dd"), true));
} else {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
}
}
}
7.5、参数控制器ParameterizableViewController
在springmvc.xml中配置参数控制器
- 注意:使用参数控制器:不用自己定义Controller了,可以直接使用toIndex.do进行访问。
8、注解开发
8.1、注解开发第一个入门程序
- 步骤如下:
- 创建一个动态的web工程,导入jar文件
- 配置web.xml
- 配置springmvc.xml文件:配置处理器映射器、配置处理器适配器、配置jsp视图解析器
- 自定义Controller类,使用注解开发:添加,返回到成功页面进行回显,点击修改回到添加页面,初步理解参数传递。
(1)创建一个动态的web工程,导入jar文件
详细过程同3、springmvc第一个程序案例
(2)配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>day63_SpringMVC_01</display-name>
<!-- 配置spring编码过滤器 -->
<filter>
<filter-name>characterEcoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEcoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置前端控制器:DispatcherServlet -->
<servlet >
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 隐式默认加载springmvc.xml文件,该文件需要满足2个规范:
命名规范:servlet-name-servlet.xml => springmvc-servlet.xml
路径规范:该文件必须放在WEB-INF目录下面
-->
<!-- 显示配置加载springmvc.xml文件,即配置springmvc.xml文件的初始化参数 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</



