SpringMVC实现了MVC设计模式的轻量级的WEB框架,基于servlet进行封装而来的WEB层优秀框架,可以看做spring在web领域简化了servlet操作而来的一项技术
1)数据持久层(DAO):主要完成数据库的CURD操作
JDBC(2000) -> DButils(2013) -> JdbcTemplate(2013) -> MyBatis(2016) -> Spring Data JPA(2018)
2)业务层(Service):主要负责业务逻辑
Spring(XML) -> Spring Boot(注解)
主要涉及的逻辑有:异常处理、参数处理、声明式事务AOP
3)展示层(WEB):主要负责页面控制
Servlet -> Struts(过滤器) -> Spring MVC(servlet)
SSH(Spring+struts+hibernate):过时框架体系
SSM(Spring+Spring MVC+MyBaits):主流应用框架
SSS(Spring+Spring MVC+Spring Data JPA+Spring Cloud):单机版框架 -> 分布式框架
MVC模型:MVC设计模式,框架都是遵循这个模式开发,MVC三层各司其职,方便模块化以及解耦合。
M : model模型 : DAO+Service+实体类,封装模型
C : controller控制器 : 每个框架的核心类都是控制器
V : view展示层 : 只要能展示数据的都是V
Model1(小脚本方式):JSP中嵌入java代码。代码非常混乱,难以维护,代码复用性比较低。
Model2(JSP与Servlet):将JSP中的Java代码写入了Servlet中,但是每个请求对应一个Servlet,耦合度较高,不方便维护。
MVC设计模式:M(service+dao+entity,封装好的对象);C控制器(SpringMVC 基于Servlet的小控制器); V JSP(或HTML,展示页面)
<properties>
<project.build.sourceEncoding>utf-8project.build.sourceEncoding>
<maven.compiler.source>1.7maven.compiler.source>
<maven.compiler.target>1.7maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.0.2.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.0.2.RELEASEversion>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>jsp-apiartifactId>
<version>2.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
<version>2.5version>
<scope>providedscope>
dependency>
<dependency>
<groupId>jstlgroupId>
<artifactId>jstlartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>taglibsgroupId>
<artifactId>standardartifactId>
<version>1.1.2version>
dependency>
dependencies>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用户登录title>
head>
<body>
<form action="hello" method="post">
<h2>恭喜通关!h2>
<div>
请留下您的大名:
<input type="text" name="userName" required="required" placeholder="请在这输入..." />
div>
<div>
<input type="submit" value="提交" />
<input type="reset" value="取消" />
div>
form>
body>
html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>挑战成功title>
<style type="text/css">
h1 {
color: red;
font-weight: bold;
font-style: 楷体;
}
style>
head>
<body>
<h1>${msg }h1>
body>
html>
package com.gaj.web;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.gaj.entity.Person;
import com.gaj.entity.Person2;
@Controller
public class UserViewAction {
// 请求映射器 能把你的request请求跟具体方法进行关联
@RequestMapping("/hello")
public String sayHello(HttpServletRequest request, String userName){
// 在控制台输出request值
System.out.println("request值:" + request);
// 在控制台输出userName
System.out.println("userName:" + userName);
// 保存值到request中
request.setAttribute("msg", "恭喜" + userName + "挑战成功!");
// 使用返回String的方式 重定向到新页面
return "forward:/message.jsp";
}
}
@RequestMapping("/请求")注解的作用:指定由特定的方法处理request请求,将request请求绑定到某个类的方法。Model2中是一个request请求绑定一个Servlet类。
注:Spring可以直接为类的方法配置请求,但方法重名会影响项目的运行。
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring-mvc.xmlparam-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
springMVC的拦截规则是 / ,代表所有的request请求都交给SpringMVC来处理。
注:过滤器的拦截规则是/*,要注意区分。
<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">
<context:component-scan base-package="com.gaj.web" />
<mvc:annotation-driven />
beans>
编写Web项目,部署到tomcat服务器。
需要在web.xml中配置servlet前端控制器,作用是拦截用户请求,然后交给不同的处理器去处理。
主要完成两件事:1)加载SpringMVC的配置文件;2)设置SpringMVC需要处理哪些请求
编写springMVC的配置文件
主要任务:1)配置注解bean扫描的目录;2)开启springMVC核心功能
在使用的时候,web.xml有一个特性,当tomcat开启的时候,部署的web项目的web.xml里面配置都会执行,SpringMVC在处理页面请求的时候,是以方法为基础进行请求的处理。
@Controller标记是一个web层控制器的bean,有了这个标记 spring会自动创建对象。
@RequestMapping设定方法与页面的请求进行映射的标签,它的主要作用是设置类中的不同方法处理页面的不同的请求
springMVC一个类可以处理页面的N个请求,每一个请求都对应一个方法
使用过滤器解决,在web.xml中配置filter
<filter>
<filter-name>EncodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>utf-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>EncodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
Tomcat8已经模式get方式就是UTF-8不需要做任何的修改
X:\apache-tomcat-X.X.XX\conf\server.xml中加入一句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请求做乱码处理的;
<div>
<h1>案例1:SpringMVC接收简单数据h1>
<form action="getParams1" method="get">
<p>
编号: <input type="number" name="id" required="required"
placeholder="请输入人员编号" />
p>
<p>
姓名: <input type="text" name="name" required="required"
placeholder="请输入人员 姓名" />
p>
<p>
性别: <select name="sex" required="required">
<option value="">---请选择---option>
<option value="男">男option>
<option value="女">女option>
select>
p>
<p>
年龄: <input type="number" name="age" required="required"
placeholder="请输入人员年龄" />
p>
<p>
籍贯: <input type="text" name="from" required="required"
placeholder="请输入人员籍贯 " />
p>
<p>
<button type="submit">提交button>
<button type="reset">取消button>
p>
form>
div>
@RequestMapping("/getParams1")
public String getParams1(Integer id, String name, String sex, Integer age, String from){
// 在控制台打印这些基本信息
System.out.println("编号:" + id);
System.out.println("姓名:" + name);
System.out.println("性别:" + sex);
System.out.println("年龄:" + age);
System.out.println("籍贯:" + from);
return "forward:/page2.jsp";
}
在接收简单数据的时候有一个问题,就是参数多了不好写,其实这个时候需要考虑是否要封装一个实体类进行传输数据
package com.gaj.entity;
/**
* Person实体类
* @author Jan
*
*/
public class Person {
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 "Person [id=" + id + ", name=" + name + ", sex=" + sex + ", age=" + age + ", from=" + from + "]";
}
}
编写实体类需要注意:1)实体类的属性和页面标签的name属性值必须是能对应上;2)实体类的属性首字母一定不能大写
<div>
<h1>案例2:SpringMVC接收对象信息h1>
<form action="getParams2" method="get">
<p>
编号: <input type="number" name="id" required="required"
placeholder="请输入人员编号" />
p>
<p>
姓名: <input type="text" name="name" required="required"
placeholder="请输入人员 姓名" />
p>
<p>
性别: <select name="sex" required="required">
<option value="">---请选择---option>
<option value="男">男option>
<option value="女">女option>
select>
p>
<p>
年龄: <input type="number" name="age" required="required"
placeholder="请输入人员年龄" />
p>
<p>
籍贯: <input type="text" name="from" required="required"
placeholder="请输入人员籍贯 " />
p>
<p>
<button type="submit">提交button>
<button type="reset">取消button>
p>
form>
div>
@RequestMapping("/getParams2")
public String getParams2(Person person){
System.out.println(person);
return "forward:/page2.jsp";
}
<div>
<h1>案例3:SpringMVC接收数组h1>
<form action="getParams3" method="get">
<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>
<button type="reset">取消button>
p>
form>
div>
@RequestMapping("/getParams3")
public String getParams3(String [] features){
System.out.println(Arrays.toString(features));
return "forward:/page2.jsp";
}
需要将List集合封装到类中,否则接不到数据
package com.gaj.entity;
import java.util.ArrayList;
import java.util.List;
/**
* Person实体类
* @author Jan
*
*/
public class Person2 {
private Integer id;
private String name;
private String sex;
private Integer age;
private String from;
private List<String> features = new ArrayList<String>();
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 "Person2 [id=" + id + ", name=" + name + ", sex=" + sex + ", age=" + age + ", from=" + from
+ ", features=" + features + "]";
}
}
<div>
<h1>案例4:SpringMVC接收集合信息(需要将集合封装到类中,否则接不到数据)h1>
<form action="getParams4" method="get">
<p>
编号: <input type="number" name="id" required="required"
placeholder="请输入人员编号" />
p>
<p>
姓名: <input type="text" name="name" required="required"
placeholder="请输入人员 姓名" />
p>
<p>
性别: <select name="sex" required="required">
<option value="">---请选择---option>
<option value="男">男option>
<option value="女">女option>
select>
p>
<p>
年龄: <input type="number" name="age" required="required"
placeholder="请输入人员年龄" />
p>
<p>
籍贯: <input type="text" name="from" required="required"
placeholder="请输入人员籍贯 " />
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>
<button type="reset">取消button>
p>
form>
div>
@RequestMapping("/getParams4")
public String getParams4(Person2 person){
System.out.println(person);
return "forward:/page2.jsp";
}
<div>
<h1>案例5:SpringMVC接收日期时间类型h1>
<form action="getParams5" method="get">
<p>
出生日期: <input type="date" name="birthday" required="required" />
p>
<p>
<button type="submit">提交button>
<button type="reset">取消button>
p>
form>
div>
@InitBinder
public void dateBind(WebDataBinder binder){
// 为java.uitl.Date类型指定一个编辑器CustomDateEditor
// 用于保证如果页面传递过来yyyy-MM-dd格式的字符串,SpringMVC会根据我们的设定将其转为Date类型;
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
}
@RequestMapping("/getParams5")
public String getParams5(Date birthday){
System.out.println("出生日期:" + birthday);
return "forward:/page2.jsp";
}
由于Http协议传输的是String类型,需要转换为Date类型。
转换为Date类型,需要在后端控制器中设置绑定属性类型
// 构造函数和描述
// 创建一个新的CustomDateEditor实例,使用给定的DateFormat进行解析和呈现。
CustomDateEditor(java.text.DateFormat dateFormat, boolean allowEmpty)
@RequestParam 注解
参数:
1) value 设置与请求参数的名称绑定
2) required 是否是必须的
3) defaultValue 设置默认值
若使用defaultValue默认值,需要required=false的配合
<div>
<h1>案例6:SpringMVC参数传递(名称不能对应)h1>
<form action="getParams6" method="get">
<p>
用户名: <input type="text" name="user" placeholder="请输入用户名" />
p>
<p>
密码: <input type="password" name="pass" placeholder="请输入密码" />
p>
<p>
<button type="submit">提交button>
<button type="reset">取消button>
p>
form>
div>
@RequestMapping("/getParams6")
public String getParams6(
@RequestParam(value="user",required=false,defaultValue="无") String loginName,
@RequestParam(value="pass",required=false,defaultValue="无") String loginPass){
System.out.println("用户名:" + loginName);
System.out.println("密码:" + loginPass);
return "forward:/page2.jsp";
}
若方法参数和表单name对应不上,是接收不到值的,因此为null
<div>
<h1>案例7:SpringMVC后端处理器的返回值为voidh1>
<form action="login1" method="get">
<p>
用户名: <input type="text" name="user" placeholder="请输入用户名" />
p>
<p>
密码: <input type="password" name="pass" placeholder="请输入密码" />
p>
<p>
<button type="submit">提交button>
<button type="reset">取消button>
p>
form>
div>
@RequestMapping("/login1")
public void userLogin1(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
// 获取页面参数
String loginName = request.getParameter("user");
String loginPass = request.getParameter("pass");
// 业务逻辑处理
String msg = "很遗憾,登录失败!";
if("admin".equals(loginName) && "admin".equals(loginPass)){
msg = "欢迎" + loginName + "管理员登录成功!";
}
// 保存
request.setAttribute("msg", msg);
// 转发
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
<div>
<h1>案例8:SpringMVC后端处理器的返回值为ModelAndViewh1>
<form action="login2" method="get">
<p>
用户名: <input type="text" name="user" placeholder="请输入用户名" />
p>
<p>
密码: <input type="password" name="pass" placeholder="请输入密码" />
p>
<p>
<button type="submit">提交button>
<button type="reset">取消button>
p>
form>
div>
@RequestMapping("/login2")
public ModelAndView userLogin2(String user, String pass){
// Model 用来存储数据(request)
// View 决定转发还是重定向
ModelAndView mav = new ModelAndView();
String msg = "很遗憾,登录失败!";
if("admin".equals(user) && "admin".equals(pass)){
msg = "欢迎" + user + "管理员登录成功!";
}
// 保存数据
mav.addObject("msg", msg);
// 转发到下一个页面
mav.setViewName("forward:/message.jsp");
// 返回
return mav;
}
最大的注解bean:@Component,所有类上都可以加这个注解 完成Spring bean对象的创建,但是@Component语意不够明确 因此有其他三种注解bean的配置
专门给DAO层配置的bean:@Repository
专门给Service层配置的bean:@Service
专门给Web控制层配置的bean:@Controller
页面发起一次request请求 --> tomcat --> springMVC核心Servlet --> 请求地址决定交给哪个类的哪个方法来处理
web.xml
<filter>
<filter-name>EncodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>utf-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>EncodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring-mvc.xmlparam-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
1)开启注解bean的包扫描器
引入context标签
xmlns:context="http://www.springframework.org/schema/context"
再引入标签的xsd文件
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
2)配置需要扫描的包
<context:component-scan base-package="com.hnxy.web" />
3)开启Spring MVC的核心功能
引入mvc标签
xmlns:mvc="http://www.springframework.org/schema/mvc"
再引入标签的xsd文件
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
4)开启SpringMVC核心功能
<mvc:annotation-driven />
spring-mvc.xml放在resource目录下即可
<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">
<context:component-scan base-package="com.gaj.web" />
<mvc:annotation-driven />
beans>