文章目录
Servlet 有两个非常明显的缺点
- 一个servlet只能处理一个请求
- 接收参数
7.SpringMVC的应用
7.1 Spring MVC 的概述
7.1.1 程序三层架构与MVC设计模式
7.1.1.1 程序三层架构
-
数据持久层(DAO) : 主要完成数据库操作,CURD
1. JDBC(2000)–>DButils(2013)–>JdbcTemplate(2013)–>MyBatis(2016)–>Spring Data JPA(2018) -
业务层(Service) : 主要负责业务逻辑
1. Spring(XML)–>SpringBoot(注解)
2. 主要涉及逻辑 : 异常处理 参数处理 声明式事务AOP -
展示层(WEB) : 主要负责页面控制,
1. servlet–>Struts(过滤器)–>SpringMVC(Servlet) -
综合来看 :
1. SSH(spring+sturts+hibernate)(过时框架体系)
2. SSM(spring+springMVC+mybatis)(主流应用框架) 16年兴起的 所以保质期5年 2021年肯定就过时 版本迭代
3. SSS(spring+springMVC+spring Data jpa+spring cloud) 单机版框架 --> 分布式框架 3个版本迭代(2023-2028年) Spring全家桶进行学习 hadoop生态圈
4. SSD (Spring(对象管理)+SpringMVC(页面控制)+Dbutis(数据库操作)) 自己整合的简单小框架实现
7.1.1.2 MVC模型
MVC模型 : MVC设计模式,框架都是遵循这个模式开发出来的,MVC三层各司其职 方便模块化 并且还能解耦和
很久很久以前 90年 javaweb -->停留小脚本阶段
- M1 model1模式 jsp 写java代码 <% System.out.print(“Hello,小脚本”) %> 非常混乱 难以维护 并且代码复用性不强
- M2 model2模式 JSP 与 Java代码 --> jsp与servlet的区别 --> 每一个请求对应一个servlet 如果修改的话会发生公共耦合 不方便维护
- MVC 设置模式 C 控制器(SpringMVC 基于Servlet 小控制器) V JSP --> HMTL M service+dao+entity --> 封装好的对象
1. M : model模型 : DAO+Service+实体类 封装 模型
2. C : controller控制器 : 每个框架的核心类其实都是控制器
3. V : view展示层 : 只要能展示数据的都是V
OOP AOP MVC -->JavaEE
面试题 :
JSP是一个Servlet(正确) 还是servlet(抽象的概念 JSP 过滤器)是一个JSP(错误)
7.1.2 SpringMVC概述
- 什么是SpringMVC : 实现了MVC设计模式的轻量级的WEB框架,基于servlet进行封装而来的WEB层优秀框架,可以看做spring在web领域简化了servlet操作而来的一项旧技术
- 什么时候用springmvc?–>如果你觉得servlet很烦的时候(1.一个项目 一个请求就得一个servlet 2. 数据封装)
- 在哪用springMVC? --> springMVC是活跃在web层 com.hnxy.web @Controller
- 怎么用? 1) jar webXXX 2) 配置文件
7.1.3 SpringMVC优势
- 清晰地角色划分
- 灵活的配置功能
- 提供了大量的控制器接口和实现类
- 真正做到与View层的实现无关(JSP、Velocity、Xslt等)
- 国际化支持
- 面向接口编程
- pring提供了Web应用开发的一整套流程,不仅仅是MVC,他们之间可以很方便的结合一起
7.2 SpringMVC的入门使用
7.2.1 SpringMVC 最简单的HelloWorld
springMVC HelloSpringMVC入门案例搭建
7.2.1.1 创建项目 : 项目类型为mavenweb项目
创建完项目之后有一个报错
web.xml 是我们web项目的核心配置文件也就是说你要配置web项目的一些设置都是在这个文件里完成报错我们的springweb配置 和 springMVC的web配置
解决这个报错,项目上直接右键 --> “JavaEE Tools” -->“Generate Deployment Descriptor Stub”
7.2.1.2 项目初始化配置
<properties>
<!-- maven项目整体编码 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 项目编译的时候,源码(.java)使用哪个版本JDK -->
<maven.compiler.source>1.7</maven.compiler.source>
<!-- 项目编译的时候,可执行文件(.class)使用哪个版本JDK -->
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
更新项目配置
效果
7.2.1.3 导入需要用到的jar包
<dependencies>
<!-- 普通的 -->
<!-- spring容器包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!-- 特殊取值范围的 -->
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- JSP中用Httpservlet对象时需要导入 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!-- Servlet中用HttpServlet对象时需要导入 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
7.2.1.4 编写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>系统首页</title>
</head>
<body>
<div>
<form action="hello" method="post">
<p>
年轻的挑战者呀,请输入你的大名:<input type="text" name="userName" />
</p>
<p>
<input type="submit" value="提交" />
</p>
</form>
</div>
</body>
</html>
7.2.1.5 编写后端控制器(处理页面请求)
@RequestMapping 作用
帮助你指定由什么资源处理什么样的request请求 request请求 绑定某个类的方法 以前是某个request请求绑定某个servlet类
注意
spring可以直接为某个类的方法配置请求直接请求即可,但是方法重名危险大,所以还是和以前一样类名/方法名 的形式访问URL
package com.hnxy.web;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class UserViewAction {
// 请求映射器 能把你的request请求跟具体方法进行关联
@RequestMapping("/hello")
public String sayHello(HttpServletRequest request, String userName) {
System.out.println("request的值" + request);
// 处理输出
System.out.println(userName + "正在访问我的程序!");
request.setAttribute("msg", "你好," + userName + "欢迎来到springMVC的世界");
// request.getRequestDispatcher("WEB-INF/pages/note.jsp").forward(arg0,
// arg1);
// 返回 jsp名称
return "forward:/note.jsp";
}
}
7.2.1.6 编写前段控制器(拦截页面请求)
<?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"
version="2.5">
<display-name>spring_class2_tp2</display-name>
<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>
<!-- 启动springMVC -->
<servlet>
<servlet-name>springmvcds</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置springmvc的配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvcds</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
springMVC的拦截规则是 /
代表所有的request请求都交给SpringMVC来处理
过滤器的拦截规则是 / 要注意区分*
7.2.1.7 编写SpringMVC的配置文件 spring-mvc.xml
- SpringMVC的Spring配置文件(固定)
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
">
<!-- 1.配置注解bean的包扫描器 -->
<context:component-scan base-package="com.hnxy.web" />
<!-- 2.开启springMVC的注解功能 -->
<mvc:annotation-driven />
<!-- 3.告诉springMVC哪些请求是静态资源请求是不需要进行拦截的 -->
<!-- 3.设置web项目中静态资源(不需要springMVC处理的请求) -->
<mvc:resources location="/js/" mapping="/js/**"/>
<mvc:resources location="/fonts/" mapping="/fonts/**"/>
<mvc:resources location="/css/" mapping="/css/**"/>
</beans>
导入springMVC的核心功能
至此,SpringMVC的入门程序配置完成
7.3 SpringMVC访问原理详解
7.3.1 编写一个web项目 --> 部署到TOMCAT
我们在WEB.XML中配置一个一个Servlet 前段控制器 作用就是拦截用户请求 然后交给不同的额处理器去处理
<!-- 启动springMVC -->
<servlet>
<servlet-name>springmvcds</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置springmvc的配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvcds</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
这个Servlet主要完成两件事
- 加载SpringMVC的配置文件
- 设置哪些请求应该交给springMVC做处理
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
">
<!-- 设置注解bean的包扫描器 -->
<context:component-scan base-package="com.hnxy.web" />
<!-- 开启springMVC的核心功能 -->
<mvc:annotation-driven />
</beans>
因为在类中使用了注解配置bean,所以你要扫描一下
package com.hnxy.web;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class UserAction {
@RequestMapping("/hello")
public String hello(HttpServletRequest request,String userName)throws Exception{
System.out.println(userName);
// 保存UserName信息
request.setAttribute("msg", "欢迎您,"+userName+"欢迎来到SpringMVC的世界!");
// 转发到下一个页面
return "forward:/show.jsp";
}
}
在使用的时候 web.xml有一个特性 当你的tomcat开启的时候 部署在它里面的web项目的web.xml里面配置都会执行
SpringMVC 在处理页面请求的时候 是以方法为基础进行请求的处理
以前 Servlet doGet doPost 指定处理请求 设定过于死板
SpringMVC 它的请求处理方法没有任何限制 任意方法都能当做执行方法处理 只有一个要求 设置好页面的请求地址即可
7.3.2 @Controller
@Controller 标记这是一个web层控制器的bean 有了这个标记 spring就会帮你创建对象
7.3.3 @RequestMapping
设定方法与页面的请求进行映射的标签,它的主要作用是设置类中的哪个方法处理页面的什么请求
以后我们用springMVC 一个类可以处理页面的N个请求 每一个请求都对应一个方法
User表的页面操作
添加 修改 删除 分页查询 按ID查询
分成两个java类
按照事务原则
UserOperateAction
添加 删除 修改
UserViewAction
分页查询 按ID查询
7.3.4 部署访问效果
访问
结果
中文乱码可以交给过滤器来维护,不知道大家还记不记得过滤器的配置?
最后看一下控制台
7.4 SpringMVC请求参数绑定
SpringMVC参数绑定问题
参数的传递问题 :
- 简单数据 : string int double long
- 复杂数据 : 对象 数组 map list 自定义类对象
7.4.1 如何接收页面请求里包含的参数?
7.4.1.1 基本数据类型参数绑定 addperosn.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>演示各种参数的接收</title>
</head>
<body>
<div>
<p>案例1:SpringMVC接收简单的数据(添加一个人)</p>
<form action="getParams1" method="get">
<p>编号 : <input type="number" name="id" placeholder="请输入人员编号" required="required" /></p>
<p>姓名 : <input type="text" name="name" placeholder="请输入人员姓名" required="required" /></p>
<p>性别 :
<select name="sex" required="required">
<option value="">---请选择---</option>
<option value="男">男</option>
<option value="女">女</option>
</select>
</p>
<p>年龄 : <input type="number" name="age" placeholder="请输入人员年龄" required="required" /></p>
<p>籍贯 : <input type="text" name="from" placeholder="请输入人员籍贯" required="required" /></p>
<p>
<button type="submit">确定</button>
</p>
</form>
</div>
</body>
</html>
接收action
@RequestMapping("/getParams1")
public String getParams1(Integer id,String name,String sex,Integer age,String from)throws Exception{
System.out.println("编号:" + id);
System.out.println("姓名:" + name);
System.out.println("性别:" + sex);
System.out.println("年龄:" + age);
System.out.println("籍贯:" + from);
return "forward:/note.jsp";
}
效果 :
页面
结果
7.4.1.2 实体类
在接收简单数据的时候我们注意到一个问题,就是参数多了不好写,其实这个时候我们需要考试是否要封装一个实体类传输数据
修改案例1,先创建实体类
package com.hnxy.entity;
/**
* 实体类
* @author My
*
*/
public class UserInfo {
private Integer id;
private String name;
private String sex;
private Integer age;
private String from;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
@Override
public String toString() {
return "UserInfo [id=" + id + ", name=" + name + ", sex=" + sex + ", age=" + age + ", from=" + from + "]";
}
}
编写实体类的时候一定要注意就是 实体类的属性和页面标签的name属性值必须是能对应上的!
修改案例的后端控制器
@RequestMapping("/getParams1")
public String getParams1(UserInfo user)throws Exception{
System.out.println(user);
return "forward:/note.jsp";
}
看下效果
控制台打印效果
怎么样是不是很神奇,SpringMVC直接可以接受实体类对象,但是必须满足一个条件就是 实体类属性必须和 页面的input标签的name的属性值是一一对应的,这样SpringMVC才能找到这些属性并赋值
7.4.1.3 集合
咱案例2中使用实体类接收了一些页面的简单数据,但是如果实体类中包含一个集合,SpringMVC该如何处理呢?
修改页面 用于填写用户特征
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>演示各种参数的接收</title>
</head>
<body>
<div>
<p>案例1:SpringMVC接收简单的数据(添加一个人)</p>
<form action="getParams1" method="get">
<p>编号 : <input type="number" name="id" placeholder="请输入人员编号" required="required" /></p>
<p>姓名 : <input type="text" name="name" placeholder="请输入人员姓名" required="required" /></p>
<p>性别 :
<select name="sex" required="required">
<option value="">---请选择---</option>
<option value="男">男</option>
<option value="女">女</option>
</select>
</p>
<p>年龄 : <input type="number" name="age" placeholder="请输入人员年龄" required="required" /></p>
<p>籍贯 : <input type="text" name="from" placeholder="请输入人员籍贯" required="required" /></p>
<p>
请描述一下你是一个什么样的人:<br />
<input type="checkbox" name="features" value="特别帅气" />特别帅气<br />
<input type="checkbox" name="features" value="非常善良" />非常善良<br />
<input type="checkbox" name="features" value="家里有矿" />家里有矿<br />
<input type="checkbox" name="features" value="乐于助人" />乐于助人<br />
</p>
<p>
<button type="submit">确定</button>
</p>
</form>
</div>
</body>
</html>
注意此处多了一个 features 的String类型的集合数据
修改实体类
package com.hnxy.entity;
import java.util.ArrayList;
import java.util.List;
/**
* 实体类
* @author My
*
*/
public class UserInfo {
private Integer id;
private String name;
private String sex;
private Integer age;
private String from;
private List<String> features = new ArrayList<String>(0);
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public List<String> getFeatures() {
return features;
}
public void setFeatures(List<String> features) {
this.features = features;
}
@Override
public String toString() {
return "UserInfo [id=" + id + ", name=" + name + ", sex=" + sex + ", age=" + age + ", from=" + from
+ ", features=" + features.toString() + "]";
}
}
看下效果
控制台接收
总结 : 对于SpringMVC来说,只要后端控制器接收数据的时候把参数名称对应好,就可以接收数据了;
7.5 解决SpringMVC中文乱码情况
7.5.1 POST形式的乱码,过滤器解决
<!-- 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>
7.5.2 GET形式的乱码
(了解即可我们现在用的Tomcat8 已经模式get方式就是UTF-8不需要做任何的修改!)
X:\apache-tomcat-X.X.XX\conf\server.xml
加一句话 URIEncoding="utf-8"即可
修改前 :
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
修改后 :
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" useBodyEncodingForURI="true" URIEncoding="utf-8"/>
资料:
useBodyEncodingForURI=true -> 使用http header中指定charset进行decode(例如:Content-Type: charset=UTF-8),若未指定,则使用默认值ISO-8859-1
useBodyEncodingForURI=false -> 使用默认值ISO-8859-1
若只配置了URIEncoding=“utf-8”,则query string的编码也会被设置为utf-8,且http header中设置的charset不会重写这个编码。
若同时设置了两项,则对于query string的编码,则与设置useBodyEncodingForURI=true的作用是一样的(会被http header中的charset重写)
但是需要注意的是 : tomcat8已经修复了get请求乱码问题,所以在tomcat8的环境下是不需要对get请求做乱码处理的;
页面效果
:添加了过滤器之后就不会出现乱码问题了,从这个过滤器的配置我们也能看出框架的好处,框架把编码阶段的工作都完成了,而我们直接配置想要的功能既可以了;
7.5.3 解决请求参数名与方法参数名不一致问题
@RequestParam 注解
1) value 设置与请求参数的名称绑定
2) required 是否是必须的
3) defaultValue 设置默认值
示例:
页面代码 :
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>演示各种参数的接收</title>
</head>
<body>
<div>
<p>案例2:SpringMVC参数传递(名称对应不上的时候)</p>
<form action="getParams2" method="get">
<p>用户名 : <input type="text" name="user" placeholder="请输入用户名" required="required" /></p>
<p>密码 : <input type="text" name="pass" placeholder="请输入密码" required="required" /></p>
<p>
<button type="submit">确定</button>
</p>
</form>
</div>
</body>
</html>
action代码
@RequestMapping("/getParams2")
public String getParams2(String loginName,String loginPass)throws Exception{
System.out.println("用户名:"+loginName);
System.out.println("密码"+loginPass);
return "forward:/note.jsp";
}
注意 页面传递的参数是
http://127.0.0.1:8080/spring_class2_tp2/getParams2?user=admin&pass=admin
但是我们接收的时候用的却是 loginName 和 loginPass,名称对应不上所以值也获取不到
那怎么办呢?
这个时候就可以在执行方法的参数上添加一个@RequestParam注解,修改之后的代码:
@RequestMapping("/getParams2")
public String getParams2(
@RequestParam(value="user",required=false,defaultValue="无") String loginName,
@RequestParam(value="pass",required=false,defaultValue="无") String loginPass)throws Exception{
System.out.println("用户名:"+loginName);
System.out.println("密码"+loginPass);
return "forward:/note.jsp";
}
效果 :
直接访问 http://127.0.0.1:8080/spring_class2_tp2/getParams2
7.6 SpringMVC时间类型处理
SpringMVC 虽然能够处理各种类型的参数,但是有一种类型却不能默认处理,那就是时间类型;
看代码:
JSP上有一个日期要传给后台
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>演示各种参数的接收</title>
</head>
<body>
<div>
<p>案例3:SpringMVC时间日期类型处理</p>
<form action="getParams3" method="get">
<p>出生日期 : <input type="date" name="birthday" required="required" /></p>
<p>
<button type="submit">确定</button>
</p>
</form>
</div>
</body>
</html>
后端控制器接收数据
@RequestMapping("/getParams3")
public String getParams3(String birthday)throws Exception{
System.out.println("生日" + birthday);
return "forward:/note.jsp";
}
注意 此处我用的是String类型,先看看能不能接收到
后端控制器是可以接收到这个值的
但是我要转换成java.util.Date类型…
@RequestMapping("/getParams3")
public String getParams3(java.util.Date birthday)throws Exception{
System.out.println("生日" + birthday);
return "forward:/note.jsp";
}
结果:
页面报错
控制台:
警告: Failed to bind request element: org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.util.Date'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.util.Date] for value '2018-11-03'; nested exception is java.lang.IllegalArgumentException
从控制台的错误信息我们不难发现,SprngMVC默认不能从页面的String转换为Date,这是因为SpringMVC不知道该怎么转换,所以我们需要告诉SpringMVC怎么把String转Date;
在后端控制器中添加如下代码
@InitBinder
public void dateBind(WebDataBinder binder){
// 告诉SpringMVCString转Date怎么转
binder.registerCustomEditor(java.util.Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
}
WebDataBinder : 用于从Web请求参数到JavaBean对象的数据绑定的专用数据集。
registerCustomerEditor : 为给定类型和属性或给定类型的所有属性注册给定的自定义属性编辑器。
此处我们为java.uitl.Date 这个类型指定了一个编辑器CustomDateEditor
CustomDateEditor 专门是为java.util.Date进行数据格式转换的编辑器,此处我们使用了它的构造函数
构造函数和描述
CustomDateEditor(java.text.DateFormat dateFormat, boolean allowEmpty)
创建一个新的CustomDateEditor实例,使用给定的DateFormat进行解析和呈现。
来保证如果页面传递过来 yyyy-MM-dd 格式的字符串,SpringMVC会根据我们的设定将其转为Date类型;
指定完之后进行代码测试
控制台
成功转换!
注意 : 这个方法是固定写法,所以以后你的项目中如果涉及到时间类型的处理你就可以使用这个配置!
7.7 SpringMVC返回值设定
7.7.1 SpringMVC返回值分类
7.7.1.1 字符串 :
根据视图解析器,拼接好页面之后进行转发
7.7.1.2 void :
利用servletAPI进行转发与从定向
@RequestMapping("/login1")
public void login1(HttpServletRequest request, HttpServletResponse response){
// 获取页面参数
String loginname = request.getParameter("loginname");
String loginpass = request.getParameter("loginpass");
// 非空判断
String msg = "很遗憾登录失败";
if("admin".equals(loginname) && "123456".equals(loginpass)){
msg = "欢迎您管理员!";
}
// 存储
request.setAttribute("msg",msg);
// 转发
try {
request.getRequestDispatcher("/ctshow.jsp").forward(request,response);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
7.7.1.3 @ ModelAndView(重点):
将参数与返回封装到一个map中进行统一管理
ModelAndView保存一个值 调用的是addObject(key,val),那么默认存值保存在request作用域中
// ModelAndView model 用来存储数据(request) view来设定是转发 还是重定向
// 保存一个数据展示到下一个页面
// 创建方法的返回值
实例:
@RequestMapping("/method5")
public ModelAndView method5(){
// ModelAndView model 用来存储数据(request) view来设定是转发 还是重定向
// 保存一个数据展示到下一个页面
// 创建方法的返回值
ModelAndView mv = new ModelAndView();
// 1. 保存数据
mv.addObject("realName", "李建军"); // request.setAttribute(key,val);
// 2. 转发到下一个页面
mv.setViewName("forward:/note.jsp");
// 返回
return mv;
}
7.7.2 转发与重定向
转发 : forward:/WEB-INF/pages/xxx.jsp
不会走视图解析器 因为你调用就是前端控制器的转发功能
重定向 : redirect:Action地址/方法名
比如添加方法
一般情况下 添加成功了 是不是都要重现查询全部数据 UserViewAction/findAllUsers
mv.setViewName(“redirect:UserViewAction/findAllUsers”); // 增加 删除 修改
查询
mv.setViewName(“forward:/user_list”);
当你使用springmvc的时候 怎么选用返回值呢 ?
- 如果你想往页面传输 数据 ModelAndView
- 只想做重定向 和 转发的话 那么返回值首选String
1. 转发 forward:地址 --> 访问jsp
2. 重定向 redirect:地址 --> action–>action
7.8 课程总结
7.8.1 Spring的注解Bean配置
Spring中我们自己类的bean都应该是注解配置
那么注解bean应该怎么配置呢?
- spring配置文件中你应该开启注解bean的包扫描器
Spring配置文件里引入一个标签
xmlns:context=“http://www.springframework.org/schema/context”
引入这个标签的XSD文件
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd - 直接配置要扫描的包
<!-- 设置注解bean的包扫描器 -->
<context:component-scan base-package="com.hnxy.web" />
- 注解bean
最大的注解bean @Component 所有类上都可以加这个注解 完成 spring bean对象的创建
但是有一个问题 @Component 语意不够明确 所以才有其他三种注解bean的配置
专门给DAO层配置的
@Repository
专门给Service配置的
@Service
控制的bean
@Controller
7.8.2 SpringMVC的应用
SpringMVC 到底帮助我们干什么的呀?
如果 我页面发起一次request请求 --> tomcat --> springMVC核心Servlet --> 请求地址决定交给哪个类的哪个方法来处理
SpringMVC 它是页面请求的处理框架 专门处理页面请求
SpringMVC把所有的页面请求 都当做是一个java方法来处理
- SpringMVC使用过程
SpringMVC只能应用于JavaWEB项目 SpringMVC就是我们之前配置的Servlet 现在其实我们写的也是Servlet当中的doGet() 和 doPost()
SpringMVC 在使用的时候需要注意的
- SpringMVC与WEB项目的整合 我们怎么区分一个项目是java–> 没有web.xml 没有webapp目录 javaWEB 有一个webapp 有一个web.xml
<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>
<!-- 启动springMVC -->
<servlet>
<servlet-name>springmvcds</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置springmvc的配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvcds</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
- 需要注意的是 控制器的编写
package com.hnxy.web;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.hnxy.entity.Account;
import com.hnxy.entity.UserInfo;
@Controller
public class UserAction {
@RequestMapping("/hello")
public String hello(HttpServletRequest request,String userName)throws Exception{
System.out.println(userName);
request.setAttribute("msg", "欢迎您,"+userName+"欢迎来到SpringMVC的世界!");
return "forward:/show.jsp";
}
}