目录
第一节 SpringMVC入门
1.1 简介
-
MVC
- M:Model
- V:View
- C:Controller - servlet/action/controller
-
Spring MVC是Spring提供的一个强大而灵活的web框架。借助于注解,Spring MVC提供了几乎是POJO的开发模式,使得控制器的开发和测试更加简单。这些控制器一般不直接处理请求,而是将其委托给Spring上下文中的其它bean,通过Spring的依赖注入功能,这些bean被注入到控制器中。
-
Spring MVC主要由DispatcherServlet、处理器映射【找控制器】、适配器【调用控制器的方法】、控制器【业务】、视图解析器、视图组成。
1.2 入门案例
第一步:创建一个javaweb项目,导入相关jar包
- 导入后记得Add as Library
第二步:在web.xml配置DispatcherServlet
<!--配置:所有的请求由SpringMVC管理-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
第三步:在WEB-INF目录下创建DispatcherServlet-servlet.xml
- 注意该文件默认读取的位置就在WEB-INF目录下,且文件名固定
<?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">
</beans>
第四步:配置DispatcherServlet-servlet.xml
<!-- 1.配置url处理器映射,SpringMVC默认的处理器映射
BeanNameUrlHandlerMapping:根据bean的name属性的url去找handlerController -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!-- 2.配置处理器适配器执行Controller -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!-- 3.配置一个控制器:相当于配置访问路径-->
<bean name="/user.do" class="com.it.web.controller.UserController"/>
<!-- 4.配置SpringMVC资源视图解析器
视图解析器解析的路径为:前缀 + 后缀 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views"/>
<property name="suffix" value=".jsp"/>
</bean>
第五步:在src下创建个Controller控制器
package com.it.web.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @ClassName UserController
* @Author shuyy
* @Date 2020/10/5 20:09
**/
public class UserController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//返回jsp的视图
ModelAndView modelAndView = new ModelAndView("/user/userList");//拼接访问路径
//设置数据让jsp页面获取
modelAndView.addObject("name","shu");
return modelAndView;
}
}
第六步:创建一个userList.jsp页面
- 在jsp页面取控制器保存的数据
第七步:运行项目
1.3 SpringMVC的执行流程
1.4 URL处理器映射【三种方式】【了解】
- URL处理映射:就是通过访问路径找到对应的控制器
第一种:BeanNameUrlHandlerMapping
- 功能:寻找Controller,根据url请求去匹配bean的name属性,从而获取Controller
第二种:SimpleUrlHandlerMapping
- 功能:寻找Controller,根据浏览器的url匹配简单url的key,key就是Controller的id,从而找到Controller
- 此时访问user.do、user1.do…user3.do都可以访问到
第三种:ControllerClassNameHandlerMapping
- 功能:寻找Controller,根据类名(UserController)类名.do来访问,类名首字母小写
- 如果在控制器里保留了name的配置,由于配置了第一种,通过user.do也能访问到
- 当然,如果保留id和name,再解开第二种的注释,那么以上的访问路径(user.do、user1.do…user3.do、userController.do)都可以访问到
<?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">
<!-- 1.配置url处理器映射,SpringMVC默认的处理器映射
第一种:BeanNameUrlHandlerMapping:根据bean的name属性的url去找handlerController -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--第二种:SimpleUrlHandlerMapping:简单的url处理映射,通过key找到bean的id的控制器-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/user1.do">userController</prop>
<prop key="/user2.do">userController</prop>
<prop key="/user3.do">userController</prop>
</props>
</property>
</bean>
<!--第三种:ControllerClassNameHandlerMapping:通过控制器的类名处理映射,
不用配置访问路径,默认的访问路径就是类名-->
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"></bean>
<!-- 2.配置处理器适配器执行Controller -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!-- 3.配置一个控制器:相当于配置访问路径 id="userController" name="/user.do" -->
<bean id="userController" name="/user.do" class="com.it.web.controller.UserController"/>
<!-- 4.配置SpringMVC资源视图解析器
视图解析器解析的路径为:前缀 + 后缀 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
1.5 控制器处理器适配器
第一种:SimpleControllerHandlerAdapter
-
最终由SimpleControllerHandlerAdapter来调用控制器
-
功能:执行controller,调用controller里面方法,返回modelAndView
-
简单控制器处理适配器源码
- 里面会调用handle方法处理请求,将handler转换成控制器调用handleRequest,里面传入request、response
- 里面会调用handle方法处理请求,将handler转换成控制器调用handleRequest,里面传入request、response
第二种:HttpRequestHandlerAdapter
- 执行控制器,负责调用实现HttpRequestHandler接口的控制器
<?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">
<!-- 1.配置url处理器映射,SpringMVC默认的处理器映射
第一种:BeanNameUrlHandlerMapping:根据bean的name属性的url去找handlerController -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--第二种:SimpleUrlHandlerMapping:简单的url处理映射,通过key找到bean的id的控制器-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/user1.do">userController</prop>
<prop key="/user2.do">userController</prop>
<prop key="/user3.do">userController</prop>
<prop key="/http1.do">http</prop>
</props>
</property>
</bean>
<!--第三种:ControllerClassNameHandlerMapping:通过控制器的类名处理映射,
不用配置访问路径,默认的访问路径就是类名-->
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"></bean>
<!-- 2.配置处理器适配器执行Controller -->
<!--调用controller里面的方法,返回modelAndView-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--负责调用HttpRequestHandler接口的控制器-->
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean>
<!-- 3.配置一个控制器:相当于配置访问路径 id="userController" name="/user.do" -->
<bean id="userController" name="/user.do" class="com.it.web.controller.UserController"/>
<bean id="http" name="/http.do" class="com.it.web.controller.HttpController"/>
<!-- 4.配置SpringMVC资源视图解析器
视图解析器解析的路径为:前缀 + 后缀 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
- 还需要在src下写个HttpController类
package com.it.web.controller;
import org.springframework.web.HttpRequestHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName HttpController
* @Author shuyy
* @Date 2020/10/6
**/
public class HttpController implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//使用原始的方法
request.setAttribute("name","shu1");
//转发(使用这种方法就要自己写好路径)
request.getRequestDispatcher("/WEB-INF/views/user/userList.jsp").forward(request,response);
}
}
- 访问http.do和http1.do都可以(但是访问httpController.do访问不到)
- 查看HttpRequestHandlerAdapter源码,与简单处理适配器类似,调用了handle方法,但是返回null
注意:上面两种处理器适配器可以共存
1.6 命令控制器【了解】
- SpringMVC通过命令设计模式接受页面参数
- 以下这种方式一般不使用,这里只是了解一下底层原理
第一步:先写一个简单的表单页面
- userAdd.jsp
<form action="${pageContext.request.contextPath}/command.do" method="post">
用户名:<input type="text" name="username"><br>
密码: <input type="text" name="password"><br>
性别: <input type="text" name="gender"><br>
生日: <input type="text" name="birthday"><br>
<input type="submit">
</form>
第二步:写一个User模型来装数据
- User.java,并为属性提供get/set、toString
第三步:写一个UserAddController控制器来显示表单
第四步:写一个CommandController控制器来接收表单参数
- AbstractCommandController是一个过时的方法,这里只是了解一下它的底层使用原理,一般不使用这种方式
package com.it.web.controller;
import com.it.model.User;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractCommandController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @ClassName CommandController
* @Author shuyy
* @Date 2020/10/6
**/
public class CommandController extends AbstractCommandController {
//指定哪个bean来接收参数
public CommandController(){
//告诉SpringMVC把表单数据存入User模型中
this.setCommandClass(User.class);
}
@Override
protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response,
Object command, BindException e) throws Exception {
//将command对象转成User对象
User user = (User) command;
//查看从表单传来的User信息
System.out.println(user);
ModelAndView modelAndView = new ModelAndView();
//将从表单写的user信息传入
modelAndView.addObject("user",user);
//返回显示到jsp页面
modelAndView.setViewName("/user/info");
return modelAndView;
}
}
第五步:再写一个jsp页面用于显示从控制器获取表单的信息
- info.jsp
<%--从控制器中取数据--%>
用户信息<br>
用户名:${user.username}<br>
密码:${user.password}<br>
性别:${user.gender}<br>
生日:${user.birthday}<br>
第六步:在DispatchServelt-sevlet.xml中配置控制器
<bean name="/userAdd.do" class="com.it.web.controller.UserAddController"/>
<bean name="/command.do" class="com.it.web.controller.CommandController"/>
第七步:运行项目
- 在表单页面输入信息后
- 提交后从控制器中取数据回显到info.jsp页面
- 后台打印的是在页面上输入进表单中的信息
日期问题
- 将birthday改成Date类型重写get/set
- 将表单中的birthday也改成date类型
- 此时日期的格式就必须是默认格式:yyyy/MM/dd,其它格式接收参数会为空
日期类型转换
- SpringMVC默认接收的日期格式为:yyyy/MM/dd,如果要添加其它格式,只需要重写一个方法(这里暂不使用注解)
- 直接在CommandController中手动重写一个initBinder方法
@Override
protected void initBinder(HttpServletRequest request,ServletRequestDataBinder binder){
String birthday = request.getParameter("birthday");
if (birthday.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));
}
}
- 效果
post请求乱码问题
- 中文乱码
- 后台也是
- 在web.xml中配置编码过滤器即可
- 顺便查看一下CharacterEncodingFilter源码
<!--post请求配置编码过滤器-->
<filter>
<filter-name>EncodingFilter</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>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 配置完成后,再次提交,乱码解决
get请求乱码问题
-
Tomcat8 默认进行了url编码,get请求不乱码,Tomcat7会乱码
-
解决方法(可以通过换成Tomcat8来解决,也可以用下面的方法)
-
修改Tomcat/conf/server.xml文件,在connector标签中添加一个URIEncoding="UTF-8"属性: