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>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
(3)配置springmvc.xml文件
配置扫描,把Controller交给spring管理、配置处理器映射器、配置处理器适配器、配置jsp视图解析器
<?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 ">
<!-- 配置扫描,把Controller交给spring管理 -->
<context:component-scan base-package="com.itheima"></context:component-scan>
<!-- 配置注解的处理器映射器,作用:寻找执行类Controller -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
<!-- 配置注解的处理器适配器,作用:调用Controller方法,执行Controller -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></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>
(4)自定义Controller类
@Controller // 相当于<bean id="userController" class="com.itheima.controller.UserController">,即相当于创建了一个UserController对象
@RequestMapping("/user")
public class UserController {
// 请求映射注解
@RequestMapping("hello") // 相当于访问/hello.do
public String myHello() {
// 表示springmvc返回了一个逻辑视图hello.jsp
return "hello";
}
}
(5)定义hello页面
根据视图解析,需要在WEB-INF下面定义jsps文件夹,在里面定义一个hello.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>欢迎访问SpringMVC</h1>
</body>
</html>
(6)访问地址:http://localhost:8080/day63_SpringMVC_02/user/hello.do
8.2、注解开发流程图
注解开发流程图如下:
8.3、RequestMapping
功能:请求映射
几种写法:
@RequestMapping("hello") -- 这种方式可以匹配任何的扩展名
@RequestMapping("/hello.do")
@RequestMapping(value="/hello.do")
@RequestMapping(value="/hello.do",method=RequestMethod.GET)
@RequestMapping(value="/hello.do",method=RequestMethod.POST)
@RequestMapping(value="/hello.do", method={RequestMethod.GET,RequestMethod.POST})
浏览器直接访问、a标签都是get请求。
表单提交(指定post)、ajax指定post提交。
如果是get请求,写成了post浏览器会报405错误,如下图所示:
8.4、RequestMapping的根路径
@RequestMapping("/user")
public class UserController {
@RequestMapping("save")
public String save() {
}
@RequestMapping("update")
public String update() {
}
@RequestMapping("find")
public String find() {
}
}
访问地址:http://localhost:8080/项目名/user/save.do
@RequestMapping("/items")
public class ItemsController {
@RequestMapping("save")
public String save() {
}
@RequestMapping("update")
public String update() {
}
@RequestMapping("find")
public String find() {
}
访问地址:http://localhost:8080/项目名/items/save.do
演示:自定义根路径
@Controller // 相当于<bean id="userController" class="com.itheima.controller.UserController">,即相当于创建了一个UserController对象
@RequestMapping("/user")
public class UserController {
// 请求映射注解
@RequestMapping("hello") // 相当于访问/hello.do
// @RequestMapping(value="/hello.do",method=RequestMethod.POST)
public String myHello() {
// 表示springmvc返回了一个逻辑视图hello.jsp
return "hello";
}
}
访问地址:http://localhost:8080/day63_SpringMVC_02/user/hello.do
8.5、RequestParam
value:参数名字,即入参的请求参数名字,如value="studentid"
表示请求的参数区中的名字为studentid的参数的值将传入。
required:是否必须,默认是true,表示请求中一定要有相应的参数
,否则将报400错误码。
defaultValue:默认值,表示如果请求中没有同名参数时的默认值
。
示例如下:
public String userList(@RequestParam(defaultValue="2",value="group",required=true) String groupid) {
}
1、形参名称为groupid,但是这里使用value="group"限定参数名为group,所以页面传递参数的名必须为group。
2、这里通过required=true限定groupid参数为必需传递,如果不传递则报400错误,由于使用了defaultvalue="2"默认值,即使不传group参数它的值仍为"2"。
3、所以页面不传递group也不会报错,如果去掉defaultvalue="2"且定义required=true,则如果页面不传递group就会报错。
示例如下图所示:
@RequestParam的作用:给传递的参数起别名。
9、封装参数
- springmvc没有成员变量,那页面提交过来的参数该如何接收和进行传递呢?
- 答:把需要传递的参数对象放入方法里面,当你请求这个方法,向这个方法传递参数的时候,这个方法里面的对象会自动被创建,需要的参数会自动被封装到方法的对象里面。
分析接受参数类型:
基本类型
int、String等基本类型。
Pojo类型
包装类型
集合类型
Springmvc默认支持类型:
HttpSession、HttpRequstServlet、Model等等。
Struts2参数封装:基于属性驱动封装。
Springmvc参数封装:基于方法进行封装。
9.1、封装int类型参数
页面传递的参数都是字符串。
页面的代码:
<hr size="12" color="blue">
<form action="${pageContext.request.contextPath}/user/recieveInt.do" method="post">
ID:<input type="text" name="id" id="id"><br>
<input type="submit" value="提交">
</form>
接受参数的方法:
// 接收int类型参数
@RequestMapping("recieveInt")
public String recieveInt(Integer id) {
System.out.println(id);
return "success";
}
- 特别注意:
标签input的name的属性值id要与方法的形式参数名称id相同。
9.2、封装String类型参数
页面的代码:
<hr size="12" color="blue">
<form action="${pageContext.request.contextPath}/user/recieveString.do" method="post">
姓名:<input type="text" name="username" id="username"><br>
<input type="submit" value="提交">
</form>
接受参数的方法:
// 接收String类型参数
@RequestMapping("recieveString")
public String recieveString(String username) {
System.out.println(username);
return "success";
}
9.3、封装数组类型参数
- 分析:
封装数组是批量删除时使用,使用checkbox复选框,其value属性必须有值。
页面的代码:
<hr size="12" color="blue">
<form action="${pageContext.request.contextPath}/user/recieveArray.do" method="post">
ID:<input type="checkbox" name="ids" value="1" id="ids"><br>
ID:<input type="checkbox" name="ids" value="2" id="ids"><br>
ID:<input type="checkbox" name="ids" value="3" id="ids"><br>
<input type="submit" value="提交">
</form>
接受参数的方法:
// 接收数组类型参数
@RequestMapping("recieveArray")
public String recieveArray(Integer[] ids) {
System.out.println(ids);
return "success";
}
9.4、封装pojo类型参数
创建一个pojo类:
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;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", age=" + age + ", birthday=" + birthday + ", address="
+ address + "]";
}
}
页面的代码:
<hr size="12" color="blue">
<form action="${pageContext.request.contextPath}/user/recieveUser.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>
接受参数的方法:
// 接收pojo类型参数
@RequestMapping("recieveUser")
public String recieveString(User user) {
System.out.println(user);
return "success";
}
9.4、封装包装类型参数
创建一个包装类:
public class UserCustom {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
页面的代码:
<hr size="12" color="blue">
<form action="${pageContext.request.contextPath}/user/recieveUserCustom.do" method="post">
姓名:<input type="text" name="user.username" id="username"><br>
年龄:<input type="text" name="user.age" id="age"><br>
生日:<input type="text" name="user.birthday" id="birthday"><br>
地址:<input type="text" name="user.address" id="address"><br>
<input type="submit" value="提交">
</form>
接受参数的方法:
// 接收包装类型参数
@RequestMapping("recieveUserCustom")
public String recieveUserCustom(UserCustom userCustom) {
System.out.println(userCustom);
return "success";
}
9.5、封装集合类型参数
9.5.1、封装List集合类型参数
- 注意:
不能直接传递集合类型,需要把集合类型封装到包装类中。
我们先把List集合封装到包装类中。即:在包装类中定义List集合。提供getter和setter方法。
private List<User> userList;
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
页面的代码:
<hr size="12" color="blue">
<form action="${pageContext.request.contextPath}/user/recieveList.do" method="post">
姓名:<input type="text" name="userList[0].username" id="username"><br>
年龄:<input type="text" name="userList[0].age" id="age"><br>
姓名:<input type="text" name="userList[1].username" id="username"><br>
年龄:<input type="text" name="userList[1].age" id="age"><br>
<input type="submit" value="提交">
</form>
接受参数的方法:
// 接收List结合类型参数
@RequestMapping("recieveList")
public String recieveList(UserCustom userCustom) {
System.out.println(userCustom);
return "success";
}
9.5.2、封装Map集合类型参数
我们先把Map集合封装到包装类中。即:在包装类中定义Map集合。提供getter和setter方法。
private Map<String, Object> maps = new HashMap<String, Object>();
public Map<String, Object> getMaps() {
return maps;
}
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
页面的代码:
<hr size="12" color="blue">
<form action="${pageContext.request.contextPath}/user/recieveMap.do" method="post">
姓名:<input type="text" name="mps['username']" id="username"><br>
年龄:<input type="text" name="mps['age']" id="age"><br>
<input type="submit" value="提交">
</form>
接受参数的方法:
// 接收Map结合类型参数
@RequestMapping("recieveMap")
public String recieveMap(UserCustom userCustom) {
System.out.println(userCustom);
return "success";
}
9.6、思考:有了struts2,为什么还需要sprigmvc呢?
- 实现机制:
- struts2 底层是基于`过滤器`实现的。过滤器的底层是servlet。
- springmvc 底层基于`servlet`实现。servlet比过滤器快。
- 运行速度:
- struts2 是`多例`。
- 一个请求来了以后,struts2创建多少个对象?如下:
- ActionContext、ValueStack、UserAction、ActionSuport、ModelDriven等等。
- UserAction里面属性:User对象,userList集合对象等。属于成员变量,存活时间长。
- springmvc 是`单例`,因为是基于servlet的,servlet是单例的。
- 一个请求来了以后,springmvc 创建多少个对象?如下:
- Controller等等。
- 方法的参数属于局部变量,存活时间短。
- struts2 是`多例`。
- 参数封装来分析:
- struts 基于`属性驱动`进行封装。
- springmvc 基于`方法`进行封装,粒度更细。
10、页面回显
- springmvc使用
Model对象
进行页面数据回显,Model对象相当于javaweb时所学的application对象(应用域对象)
,所以Model对象中的数据可以通过EL表达式
进行获取。 - 有了Model对象,才可以向对象中放值,那么Model对象该如何创建呢?
- 答:`springmvc中放到方法里面的对象会自动被创建`,那么我们就把Model对象放到方法里面。
10.1、查询所有
页面的代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%--引入jstl标签 --%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!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>
<table border="1" style="color: blue">
<tr>
<td>姓名</td>
<td>年龄</td>
<td>生日</td>
<td>地址</td>
<td>操作</td>
<tr/>
<c:forEach items="${userList}" var="user">
<tr>
<td>${user.username}</td>
<td>${user.age}</td>
<td>${user.birthday}</td>
<td>${user.address}</td>
<td>
<a href="${pageContext.request.contextPath}/user/updateById.do?id${user.id}">修改</a>
</td>
<tr/>
</c:forEach>
</table>
</body>
</html>
接受参数的方法:
// 查询所有
@RequestMapping("listAll")
public String listAll(Model model) {
// 由于演示我们没有查询数据库,所以下面我们模拟几条数据
List<User> userList = new ArrayList<User>();
User user1 = new User();
user1.setId(1);
user1.setUsername("晓艺");
user1.setAge("26");
user1.setAddress("物资学院");
user1.setBirthday(new Date());
User user2 = new User();
user2.setId(2);
user2.setUsername("黑泽");
user2.setAge("26");
user2.setAddress("青年路");
user2.setBirthday(new Date());
User user3 = new User();
user3.setId(3);
user3.setUsername("奇遇");
user3.setAge("28");
user3.setAddress("物资学院");
user3.setBirthday(new Date());
userList.add(user1);
userList.add(user2);
userList.add(user3);
// Model相当于application域对象
model.addAttribute("userList", userList);
return "list";
}
浏览器显示效果:
11、URL模版映射
- URL模版映射主要是为了实现请求
Restfull软件架构设计模式
。 - Restfull软件架构设计模式使得请求更简洁、更安全,方便于搜索引擎收录。
11.1、普通模式修改
页面的代码:
<td>
<a href="${pageContext.request.contextPath}/user/updateByIdNormal.do?id=${user.id}">修改</a>
</td>
接受参数的方法:
// 普通模式修改
@RequestMapping("updateByIdNormal")
public String updateByIdNormal(Integer id) {
System.out.println(id);
return "redirect:listAll.do";
}
访问的地址为:http://localhost:8080/day63_SpringMVC_02/user/updateByIdNormal.do?id=1
11.2、Restfull风格设计模式修改
(1)初始Restfull风格设计模式修改
页面的代码:
<td>
<a href="${pageContext.request.contextPath}/user/updateByIdRestfull/${user.id}.do">修改</a> <!-- 把参数放在了请求的里面了 -->
</td>
接受参数的方法:
// 初始Restfull模式修改
@RequestMapping("updateByIdRestfull/{id}")
public String updateByIdRestfull(@PathVariable Integer id) {
System.out.println(id);
return "redirect:/user/listAll.do"; // 请求重定向
}
访问的地址为:http://localhost:8080/day63_SpringMVC_02/user/updateByIdRestfull/1.do
(2)最终Restfull风格设计模式修改
约定:在web.xml配置拦截方式:在rest目录下所有请求都被拦截,servlet可以拦截目录。
web.xml中配置代码如下:
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
页面的代码:
<td>
<a href="${pageContext.request.contextPath}/rest/user/updateByIdRestfull/${user.id}">修改</a>
</td>
接受参数的方法:
// 最终Restfull模式修改
@RequestMapping("updateByIdRestfull/{id}")
public String updateByIdRestfull(@PathVariable Integer id) {
System.out.println(id);
return "redirect:/user/listAll.do"; // 请求重定向
}
访问的地址为:http://localhost:8080/day63_SpringMVC_02/rest/user/updateByIdRestfull/1
其中:
{id}:表示匹配接受页面url路径中的参数
@PathVariable:表示{id}里面参数注入后面参数id里面
url模版映射需要@RequestMapping和@PathVariable结合使用。
画图理解URL模版映射,如下图所示:
11.3、在线安装eclipse提示插件--Spring tools suite
步骤:Help --> Eclipse Marketplace… --> 在Find中输入Spring tools suite,点击安装即可。
安装成功后的截图如下:
12、转发和重定向
12.1、转发
- 本类中进行转发:本类中方法与方法之间进行forward
- 关键字:forward
- 转发方式一:return "forward:listAll.do";
- 转发方式二:return "/user/forward:listAll.do";
- 注意:`user根路径前面必须有/。`
- 跨类进行转发:
- 转发方式:return "forward:/items/listAll.do";
测试代码如下:
// 测试forward
@RequestMapping("forward")
public String forward() {
// return "forward:listAll.do"; // 本类中转发方式一
// return "/user/forward:listAll.do"; // 本类中转发方式二
return "forward:/items/listAll.do"; // 跨类进行转发
}
12.2、重定向
- 本类中进行重定向:本类中方法与方法之间进行redirect
- 关键字:redirect
- 重定向方式一:return "redirect:listAll.do";
- 重定向方式二:return "redirect:/user/listAll.do";
- 跨类进行重定向:
- 重定向方式:return "redirect:/items/listAll.do";
测试代码如下:
// 测试redirect
@RequestMapping("redirect")
public String redirect() {
// return "redirect:listAll.do"; // 本类中重定向方式一
// return "/user/redirect:listAll.do"; // 本类中重定向方式二
return "redirect:/items/listAll.do"; // 跨类进行重定向
}
13、标签< mvc:annotation-driven />的使用
详解如下:
标签<mvc:annotation-driven /> 表示默认创建处理器映射器RequestMappingHandlerMapping、处理器映射器RequestMappingHandlerAdapter,还表示默认启动json格式数据的支持。
所以在springmvc.xml中就不要再配置处理器映射器和处理器映射器了。
只需要配置这一句就可以了。
14、RequestBody 和 ResponseBody
- @RequestBody 和 @ResponseBody,这两个注解主要是为了
提供对json格式数据的支持。
- @RequestBody的作用:把前台页面请求的json格式数据直接封装成JavaBean,使用ajax进行数据传递。
- @ResponseBody的作用:在后台,把JavaBean强制转换成json格式数据返回给前台页面。
这两个注解不能直接使用,需要依赖两个Jackson的jar包。
(1)先导入Jackson的jar包
(2)在springmvc.xml中配置json格式转换
注意:我们也可以直接使用
<mvc:annotation-driven />
,因为该标签默认启动json格式数据的支持。
<!-- 配置注解的处理器适配器,作用:调用Controller方法,执行Controller -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<!-- 配置对json格式数据的支持 -->
<property name="messageConverters">
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
</property>
</bean>
(3)请求json格式数据,返回json格式数据
(4)请求pojo格式数据,返回json格式数据
/day63_SpringMVC_02/WebRoot/WEB-INF/jsps/requestjson.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>
<!-- 引入jquery.js的支持 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery.js"></script>
</head>
<body>
<input type="button" value="请求是json格式数据,返回是json格式数据" onclick="requestJson();">
<br>
<input type="button" value="请求是pojo格式数据,返回是json格式数据" onclick="requestPojo();">
<script type="text/javascript">
function requestJson() {
// 演示:构造一个json格式数据
var jsonObj = JSON.stringify({'username':'晓艺','age':'26','address':'物资学院'}); // stringify的作用:把json格式的数据数强转成json对象
// 发送ajax请求
$.ajax({
type:'post',
url:'${pageContext.request.contextPath}/user/requestJson.do',
contentType:'application/json;charset=UTF-8', // 默认: "application/x-www-form-urlencoded"
data:jsonObj,
success:function(data) { // 回调函数
alert(data);
}
});
}
function requestPojo() {
// 演示:构造一个pojo格式数据
var pojoObj = 'username=黑泽&age=26&address=青年路';
// 发送ajax请求
$.ajax({
type:'post',
url:'${pageContext.request.contextPath}/user/requestPojo.do',
data:pojoObj,
success:function(data) { // 回调函数
alert(data);
}
});
}
</script>
</body>
</html>
后台代码:
// 跳转方法,跳转到requestjson.jsp页面
@RequestMapping("toJson")
public String tiJson() {
return "requestjson";
}
// 接收json格式数据,使用 @RequestBody 把json格式数据封装进JavaBean对象中(本例中是User对象)
// 返回json对象,使用 @ResponseBody 把User对象转换成json对象
@RequestMapping("requestJson")
public @ResponseBody User requestJson(@RequestBody User user) {
System.out.println(user);
return user;
}
// 接收pojo格式数据
// 返回json对象,使用@ResponseBody 把User对象转换成json对象
@RequestMapping("requestPojo")
public @ResponseBody User requestPojo(User user) {
System.out.println(user);
return user;
}