其它相关文章:
文章目录
一、SpringMVC的介绍
什么是MVC设计模式?
Controller:负责接收并处理请求,响应客户端。
Model:模型数据,业务逻辑。
View:呈现模型,与用户进行交互。
具体流程如图:
什么是SpringMVC?
目前最好的实现MVC设计模式的框架。
Spring框架的一个后续产品。
Spring框架的一个子模块,二者可以很好的结合使用,不需要整合。
MVC框架要做哪些事情:
(a)将url映射到Java类或Java类的方法。
(b)封装用户提交的数据。
(c)处理请求一调用相关的业务处理一封装响应的数据。
(d)将响应数据的数据进行渲染,jsp,html,freemarker等。
Spring MVC是一个轻量级的,基于请求响应的MVC框架。
为什么要学习Spring MVC?
性能比struts2好(虽然struts2开发效率是高)
Spring MVC简单、便捷、易学,天生和Spring无缝集成(使用Spring ioc、aop)
使用约定优于配置,能够进行简单junit测试。
支持Restful风格,异常处理,本地化、国际化,数据验证、类型转换等,拦截器等------使用的人、公司多。
简单了解结构
请求来了到了控制器(Controller),然后将请求委托给了处理器,处理器会去调用HandlerMapping类和HandlerAdaper类(其实是适配器)处理,处理完成后封装返回ModerAndView的对象,控制器拿到后,会去调用一个视图渲染器,把ModerAndView对象给它,处理完成后会返回控制器,最后控制器做出响应。
SpringMVC详解
SpringMVC核心组件:
1、DispatcherServlet:前置控制器。
2、HandlerMapping:将请求映射到Handler。
3、Handler:后端控制器,完成具体业务逻辑。
4、HandlerInterceptor:处理器拦截器。
5、HandlerExecutionChain:处理器执行链。
6、HandlerAdapter:处理器适配器。
7、ModelAndView:装载模型数据和视图信息。
8、ViewResolver:视图解析器。
SpringMVC实现流程
1、客服端请求被DispatcherServlet接收。
2、DispatcherServlet将请求映射到Handler。
3、生成Handler以及HandlerInterceptor。
4、返回HandlerExectionChain(Handler+HandlerInterceptor).
5、DispatcherServlet通过HandlerAdapter执行Handler。
6、返回一个ModeIandView。
7、DispatcherServlet通过ViewResolver进行解析。
8、返回填充了模型数据的View,响应给客服端。
其流程图为:
二、SpringMVC的使用
1、大部分组件由框架提供,开发者只需通过配置进行关联。
2、开发者只需手动编写Handler,View。
因为我使用的是idea的Maven的webapp,在创建后加载框架时,为了减少加载时间可以添加如下语句,archetypeCatalog:internal
基于XML配置的使用
1、SpringMVC基础配置。
2、XML配置Controller,HandlerMapping组件映射。
3、XML配置ViewResolver组件映射。
pom.xml:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--导入springmvc需要的jar-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.1.RELEASE</version>
</dependency>
<!--导入servlet相关jar-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!--C标签的使用依赖包-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
springmvc.xml:
<!--配置HandlerMapping,将url请求映射到Handler-->
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<!--配置test请求对应的handler-->
<prop key="/test">testHandler</prop>
</props>
</property>
</bean>
<!--配置Handler-->
<bean id="testHandler" class="com.imooc.handler.MyHandler"></bean>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--配置前缀-->
<property name="prefix" value="/"></property>
<!--配置后缀-->
<property name="suffix" value=".jsp"></property>
</bean>
show.jsp:
<%@ page isELIgnored="false" %>
<body>
${name}
</body>
webapp下的WEB-INF的web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--配置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>/</url-pattern>
</servlet-mapping>
</web-app>
MyHandler.java:
package com.imooc.handler;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyHandler implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//装载模型数据和逻辑视图
ModelAndView modelAndView = new ModelAndView();
//添加模型数据
modelAndView.addObject("name","Tom");
//添加逻辑视图
modelAndView.setViewName("show");
return modelAndView;
}
}
最后进行tomcat的配置,配置完成后运行
其运行结果为:
在其中我遇到了一个报错:Artifact SpringMVC_Test2:war: Error during artifact deployment. See server log for details.
最后在tomcat的日志文件中发现了错误,其从web.xml开始排查,最好的办法就是不断的简化配置文件,最后解决了问题。
基于注解方式的使用
1、SpringMVC基础配置
2、Controller,HandlerMapping通过注解进行映射。
3、XML配置ViewResolver组件映射。
AnnotationHandler.java:
package com.imooc.handler;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.Map;
@Controller
public class AnnotationHandler {
/**
* 业务方法:ModelAndView完成数据的传递,视图的解析
*/
@RequestMapping("/modelAndViewTest")
public ModelAndView modelAndViewTest(){
//创建ModelAndView对象
ModelAndView modelAndView = new ModelAndView();
//填充模型数据
modelAndView.addObject("name","Tom");
//设置逻辑视图
modelAndView.setViewName("show");
return modelAndView;
}
/**
* 业务方法:Model传值,String进行视图解析
*/
@RequestMapping("/ModelTest")
public String ModelTest(Model model){
//填充模型数据
model.addAttribute("name","Jerry");
//设置逻辑视图
return "show";
}
/**
* 业务方法:Map传值,String进行视图解析
*/
@RequestMapping("/MapTest")
public String MapTest(Map<String,String> map) {
//填充模型数据
map.put("name","Cat");
//设置逻辑视图
return "show";
}
}
springmvc.xml:
<?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:context="http://www.springframework.org/schema/context"
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">
<!--将AnnotationHandler自动扫描到IOC容器中-->
<context:component-scan base-package="com.imooc.handler"></context:component-scan>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--配置前缀-->
<property name="prefix" value="/"></property>
<!--配置后缀-->
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
其结果分别为:
XML和注解开发的区别
注解与XML配置的区别
注解: 是一种分散式的元数据,与源代码紧绑定。
xml: 是一种集中式的元数据,与源代码无绑定(在开发过程中,xml配置文件和代码类是区分开的。不需要绑定到代码中)。
XML的优点:
1、使用xml配置可以让软件更具有扩展性;
2、对象之间的关系一目了然;
3、xml定义:可扩展标记语言,标准通用标记语言的子集,简称XML。从这个定义中我们可以发现,xml最大的优势就在于,开发者(程序员)能够为软件量身使用的标记,使得xml更通俗易懂;
4、成熟的校验机制,来保证正确。可以使用Schema或者是DTD来对xml的正确性进行校验。
5、基于xml配置的时候,只需要修改xml即可,不需要对现有的程序进行修改。
6、容易与其他系统进行数据交互。数据共享方便
XML的缺点:
1、应用程序中如果使用了xml配置,需要解析xml的工具或者是是第三方类库的支持;
2、解析xml的时候必然会占用资源,势必会影响到应用程序的性能;
以java为例,无论是将xml一次性装置到内存中,还是一行一行读取解析的,都会占用资源的。
3、xml配置文件过多,会导致维护变得困难
4、在程序编译期间无法对其配置项的正确性进行验证,只能在运行期发现。
5、出错后,排错变得困难。往往在配置的时候,一个手误就会出现莫名其妙的错误(虽然事出必有妖,但是排查真难);
比如,xml配置bean信息的时候,如果class的值带有空格,这种不好检查的,是比较麻烦的。排查起来很费事。
6、开发的时候,既要维护代码又要维护配置文件,使得开发的效率降低;
7、代码与配置项之间有时候会存在很多“潜规则”.改变了任意一方,都有可能影响到另一方的使用。这是个大坑
比如:自定义的标记,如果其他开发不清楚这些的话,修改了无论是代码还是xml的配置,都会导致程序不能正常运行。
8、开发工具对xml的验证支持的不是很好。
比如idea,对xml正确性,如果是自定义的,验证就不是很好。
注解的好处: (数据绑定用注解,很少改变的用注解,类型安全)
1、XML配置起来有时候冗长,此时注解可能是更好的选择,如jpa的实体映射;注解在处理一些不变的元数据时有时候比XML方便的多,比如springmvc的数据绑定,如果用xml写的代码会多的多。
2、注解最大的好处就是简化了XML配置;其实大部分注解一定确定后很少会改变,所以在一些中小项目中使用注解反而提供了开发效率。
3、注解如果有问题,在编译期间,就可以验证正确性,如果出错更容易找。
注解的缺点:
1、注解的开启/关闭必须修改源代码,因为注解是源代码绑定的,如果要修改,需要改源码,这个有这个问题,所以如果是这种情况,还是使用XML配置方式,比如数据源。
2、在程序中注解太多的话,会影响代码质量,代码简洁会有影响
3、通用配置还是走XML吧,比如事务配置,比如数据库连接池等等,即通用的配置集中化,而不是分散化,如很多人使用@Transactional来配置事务,在很多情况下这是一种太分散化的配置。
4、XML方式比注解的可扩展性和复杂性维护上好的多,比如需要哪些组件,不需要哪些;在面对这种情况,注解扫描机制比较逊色,因为规则很难去写或根本不可能写出来。
最后可以发现没有一个是最好的,都是要根据不同的场景进行选择使用。
三、一个小demo
需求: 添加商品信息,信息包括商品名称和价格,添加好之后在后台对数据进行封装,封装好之后做一个展示,最后回到前台。
add.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>add</title>
</head>
<body>
<form class="form-horizontal" role="form" action="addGoods" method="post">
<div class="form-group">
<label class="col-sm-1 control-label">名称</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="name" placeholder="请输入商品名称">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">价格</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="price" placeholder="请输入商品价格">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-1 col-sm-3">
<button type="submit" class="btn btn-default">提交</button>
</div>
</div>
</form>
</body>
</html>
实体类:Goods.java:
package com.imooc.entity;
public class Goods {
private String name;
private double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
springmvc.xml:
<?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:context="http://www.springframework.org/schema/context"
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">
<!--将AnnotationHandler自动扫描到IOC容器中-->
<context:component-scan base-package="com.imooc.handler"></context:component-scan>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--配置前缀-->
<property name="prefix" value="/"></property>
<!--配置后缀-->
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
show.jsp:
<%@ page isELIgnored="false" %>
<body>
商品名称:${requestScope.goods.name}<br/> <%--requestScope判断goods是否添加到request--%>
商品价格:${requestScope.goods.price}
</body>
AnnotationHandler.java:
/**
* 添加商品并展示
*/
@RequestMapping("/addGoods")
public ModelAndView addGoods(Goods goods) {
System.out.println(goods.getName() + "---" + goods.getPrice());
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("goods",goods);
modelAndView.setViewName("show");
return modelAndView;
其结果为:
a…是不是发现一个问题,既然出现了中文乱码,所以为了解决这一问题,便出现了如下操作:
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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
最后结果为:
到此便是我的一个小demo ψ(*`ー´)ψ
四、SpringMVC 数据绑定
什么是数据绑定?
将HTTP请求中的参数绑定到Handler业务方法的形参。
常见的数据绑定类型?
1、基本数据类型
2、包装类
3、数组
4、对象
5、集合(List、Set、Map)
6、JSON
下面便一一演示:
DataBindController.java
package com.imooc.controller;
import com.imooc.dao.CourseDao;
import com.imooc.entity.Course;
import com.imooc.entity.CourseList;
import com.imooc.entity.CourseMap;
import com.imooc.entity.CourseSet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
@Controller //作为一个控制器
public class DataBindController {
@Autowired
private CourseDao courseDao;
/**
* 基本数据类型
*/
@RequestMapping(value = "/baseType")
@ResponseBody //直接将业务返回的值响应给客户端,而不会跳转jsp页面
public String baseType(@RequestParam(value = "id")int id) { //@RequestParam(value = "id")这个能将前端请求的值id拿出来绑定到新id里面
return "id:" + id;
}
/**
* 包装类
*/
@RequestMapping(value = "/packageType")
@ResponseBody
public String packageType(@RequestParam(value = "id",required = false)Integer id) {
return "id:" + id;
}
/**
* 数组
*/
@RequestMapping(value = "/arrayType")
@ResponseBody
public String arrayType(String[] name) {
StringBuffer sbf = new StringBuffer();
for (String item : name) {
sbf.append(item).append(" ");
}
return "name:"+sbf.toString();
}
/**
* 对象
*/
@RequestMapping(value = "/pojoType")
public ModelAndView pojoType(Course course) {
courseDao.add(course);
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
modelAndView.addObject("courses",courseDao.getAll());
return modelAndView;
}
/**
* List集合
*/
@RequestMapping(value = "/listType")
public ModelAndView listType(CourseList courseList) {
for (Course course : courseList.getCourses()) {
courseDao.add(course);
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
modelAndView.addObject("courses",courseDao.getAll());
return modelAndView;
}
/**
* Map集合
*/
@RequestMapping(value = "/mapType")
public ModelAndView mapType(CourseMap courseMap) {
for (String key:courseMap.getCourses().keySet()) {
Course course = courseMap.getCourses().get(key);
courseDao.add(course);
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
modelAndView.addObject("courses",courseDao.getAll());
return modelAndView;
}
/**
* Set集合
*/
@RequestMapping(value = "/setType")
public ModelAndView setType(CourseSet courseSet) {
for (Course course : courseSet.getCourses()) {
courseDao.add(course);
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
modelAndView.addObject("courses",courseDao.getAll());
return modelAndView;
}
/**
* JSON
*/
@RequestMapping(value = "/jsonType")
@ResponseBody
public Course jsonType(@RequestBody Course course) {
course.setPrice(course.getPrice()+100);
return course;
}
}
1、基本数据类型
当我们id输入不是基本数据类型时:
相对应的idea就会报输入错误的异常。
而当我们输入null值时也是会报错的
2、包装类
包装类与基本数据类型的区别,在于可以输入null值:
3、数组
输入两个name:xiaobai、xiaoxin
接下来都会跳转的页面:
index.jsp:
<%--
Created by IntelliJ IDEA.
User: Administrator.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>课程列表</title>
</head>
<body>
<div class="container">
<!-- 标题 -->
<div class="row">
<div class="col-md-12">
<h1>imooc-课程管理</h1>
</div>
</div>
<!-- 显示表格数据 -->
<div class="row">
<div class="col-md-12">
<table class="table table-hover" id="emps_table">
<thead>
<tr>
<th>
<input type="checkbox" id="check_all"/>
</th>
<th>编号</th>
<th>课程名</th>
<th>价格</th>
<th>讲师</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<c:forEach items="${courses}" var="course">
<tr>
<td><input type='checkbox' class='check_item'/></td>
<td>${course.id}</td>
<td>${course.name}</td>
<td>${course.price}</td>
<td>${course.author.name}</td>
<td>
<button class="btn btn-primary btn-sm edit_btn">
<span class="glyphicon glyphicon-pencil">编辑</span>
</button>
<button class="btn btn-danger btn-sm delete_btn">
<span class="glyphicon glyphicon-trash">删除</span>
</button>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
4、对象
实体类:
Author.java:
public class Author {
private int id;
private String name;
生成各自的get和set方法
}
Course.java:
public class Course {
private int id;
private String name;
private double price;
private Author author;
生成各自的get和set方法
}
因为是对象,所以用前端添加课程为例:
add.jsp:
<%--
Created by IntelliJ IDEA.
User: Administrator.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>add</title>
</head>
<body>
<div id="main">
<!-- 标题 -->
<div class="row">
<div class="col-md-12">
<h1>imooc-添加课程</h1>
</div>
</div>
<form class="form-horizontal" role="form" action="pojoType" method="post">
<div class="form-group">
<label class="col-sm-1 control-label">课程编号</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="id" placeholder="请输入课程编号">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">课程名称</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="name" placeholder="请输入课程名称">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">课程价格</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="price" placeholder="请输入课程价格">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">讲师编号</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="author.id" placeholder="请输入讲师编号">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">讲师姓名</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="author.name" placeholder="请输入讲师姓名">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-1 col-sm-3">
<button type="submit" class="btn btn-default">提交</button>
</div>
</div>
</form>
</div>
</body>
</html>
运行程序后,访问add.jsp:
提交后跳转index.jsp:
5、 List集合
实体类:
CourseList.java:
import java.util.List;
public class CourseList {
private List<Course> courses;
public List<Course> getCourses() {
return courses;
}
public void setCourses(List<Course> courses) {
this.courses = courses;
}
}
6、Map集合
实体类:
CourseMap.java:
import java.util.Map;
public class CourseMap {
private Map<String,Course> courses;
public void setCourses(Map<String,Course> courses) {
this.courses = courses;
}
public Map<String, Course> getCourses() {
return courses;
}
}
7、Set集合
实体类:
public class Course {
private int id;
private String name;
private double price;
private Author author;
生成各自的get和set方法
}
这三个集合的前端添加都相同,使用简单添加一下后:
jihe.jsp:
<%--
Created by IntelliJ IDEA.
User: Administrator.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>add</title>
<style type="text/css">
body{
overflow-x:hidden;
}
#main{
width:1200px;
height:600px;
margin-left:500px;
}
</style>
</head>
<body>
<div id="main">
<!-- 标题 -->
<div class="row">
<div class="col-md-12">
<h1>imooc-添加课程</h1>
</div>
</div>
<form class="form-horizontal" role="form" action="listType" method="post">
<div class="form-group">
<label class="col-sm-1 control-label">课程1编号</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses[0].id" placeholder="请输入课程编号">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">课程1名称</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses[0].name" placeholder="请输入课程名称">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">课程1价格</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses[0].price" placeholder="请输入课程价格">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">讲师编号</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses[0].author.id" placeholder="请输入讲师编号">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">讲师姓名</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses[0].author.name" placeholder="请输入讲师姓名">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">课程2编号</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses[1].id" placeholder="请输入课程编号">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">课程2名称</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses[1].name" placeholder="请输入课程名称">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">课程2价格</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses[1].price" placeholder="请输入课程价格">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">讲师编号</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses[1].author.id" placeholder="请输入讲师编号">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">讲师姓名</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses[1].author.name" placeholder="请输入讲师姓名">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-1 col-sm-3">
<button type="submit" class="btn btn-default">提交</button>
</div>
</div>
</form>
</div>
</body>
</html>
经过一系列添加,最后结果:
8、JSON
json.jsp:
<%--
Created by IntelliJ IDEA.
User: Administrator.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<script type="text/javascript" src="js/jquery-1.8.3.min.js"></script>
<script type="text/javascript">
$(function(){
var course = {
"id":"8",
"name":"SSM框架整合",
"price":"200"
};
$.ajax({
url:"jsonType",
data:JSON.stringify(course),
type:"post",
contentType:"application/json;charse=UTF-8",
dataType:"json",
success:function(data){
alert(data.name+"---"+data.price);
}
})
})
</script>
<body>
</body>
</html>
数据绑定的总结:
SpringMVC数据绑定的实现流程
借助于Spring框架将Http请求里的参数直接绑定到Handler的业务方法的形参列表当中这个就是数据绑定。
实现流程:通过HandlerAdapter调用HttpMessageConverter这个组件将Http里的参数取出来进行数据类型的转换
包括对象的封装,将这个封装的结果直接赋值给Handler的业务方法的形参,这样的话,我们的业务方法就可以直接拿到这个形参进行后续的业务逻辑的操作
五、SpringMVC-RESTful风格
什么是RESTful?(只是一种开发方式,架构思想)
REST:Representational State Transfer(表达性状态转移)
REST并不是一种创新技术,它指的是一组框架约束条件和原则
符合REST的约束条件和原则的框架,就称它为RESTful架构
RESTful核心内容:
1、资源与URI(资源:只要它有被引用的必要,它就是资源,它可以是个文本、图片、歌曲,甚至是一种服务,总之它就是一个具体真实存在的资源;有资源那就需要标识进行识别,在web中就只要一个唯一标识:URI,使用URI其实就是地址)
2、资源的表述(资源在客户端和服务器之间的传送,这个就是资源的表述)
3、状态转移(状态转移就是资源在客户端发生变迁,然后进入到一个后续的状态,也就是客户端获取资源之后,可能对资源做出修改,使它与服务器保存的状态不一样,这就是状态转移)
RESTful架构特点:
1、统一了客户端访问资源的接口
2、url更加简洁,易于理解,便于扩展
3、有利于不同系统之间的资源共享
RESTful具体来讲就是HTTP协议的四种形式表示四种基本操作:
GET:获取资源
POST:新建资源
PUT:修改资源
DELETE:删除资源
下面便进行增删改查的演示:
web.xml:
<!--配置一个过滤器-->
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
实体类, Course.java:
public class Course {
private int id;
private String name;
private double price;
生成get和set方法
}
添加页面,add.jsp:
<%--
Created by IntelliJ IDEA.
User: Administrator.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<head>
<title>add</title>
<style type="text/css">
body{
overflow-x:hidden;
}
#main{
width:1200px;
height:600px;
margin-left:500px;
}
</style>
</head>
<body>
<div id="main">
<!-- 标题 -->
<div class="row">
<div class="col-md-12">
<h1>imooc-添加课程</h1>
</div>
</div>
<form class="form-horizontal" role="form" action="${pageContext.request.contextPath}/add" method="post">
<div class="form-group">
<label class="col-sm-1 control-label">课程编号</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="id" placeholder="请输入课程编号">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">课程名称</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="name" placeholder="请输入课程名称">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">课程价格</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="price" placeholder="请输入课程价格">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-1 col-sm-3">
<button type="submit" class="btn btn-default">提交</button>
</div>
</div>
</form>
</div>
</body>
</html>
跳转页面,index.jsp:
<%--
Created by IntelliJ IDEA.
User: Administrator.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>课程列表</title>
<link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<!-- 标题 -->
<div class="row">
<div class="col-md-12">
<h1>imooc-课程管理</h1>
</div>
</div>
<!-- 显示表格数据 -->
<div class="row">
<div class="col-md-12">
<table class="table table-hover" id="emps_table">
<thead>
<tr>
<th>
<input type="checkbox" id="check_all"/>
</th>
<th>编号</th>
<th>课程名</th>
<th>价格</th>
<th>编辑</th>
<th>删除</th>
</tr>
</thead>
<tbody>
<c:forEach items="${courses}" var="course">
<tr>
<td><input type='checkbox' class='check_item'/></td>
<td>${course.id}</td>
<td>${course.name}</td>
<td>${course.price}</td>
<td>
<form action="${pageContext.request.contextPath}/getById/${course.id}" method="get">
<button class="btn btn-primary btn-sm edit_btn" type="submit">
<span class="glyphicon glyphicon-pencil">编辑</span>
</button>
</form>
</td>
<td>
<form action="${pageContext.request.contextPath}/delete/${course.id}" method="post">
<button class="btn btn-danger btn-sm delete_btn" type="submit">
<input type="hidden" name="_method" value="DELETE"/>
<span class="glyphicon glyphicon-trash">删除</span>
</button>
</form>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
edit.jsp:
<%--
Created by IntelliJ IDEA.
User: Administrator.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<head>
<title>add</title>
<style type="text/css">
body{
overflow-x:hidden;
}
#main{
width:1200px;
height:600px;
margin-left:500px;
}
</style>
</head>
<body>
<div id="main">
<!-- 标题 -->
<div class="row">
<div class="col-md-12">
<h1>imooc-修改课程</h1>
</div>
</div>
<form class="form-horizontal" role="form" action="${pageContext.request.contextPath}/update" method="post">
<div class="form-group">
<label class="col-sm-1 control-label">课程编号</label>
<div class="col-sm-3">
<input type="text" value="${course.id}" name="id" readonly="readonly" class="form-control">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">课程名称</label>
<div class="col-sm-3">
<input type="text" value="${course.name}" name="name" class="form-control">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">课程价格</label>
<div class="col-sm-3">
<input type="text" value="${course.price}" name="price" class="form-control">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-1 col-sm-3">
<input type="hidden" name="_method" value="PUT"/>
<button type="submit" class="btn btn-default">提交</button>
</div>
</div>
</form>
</div>
</body>
</html>
CourseDao.java:
import com.imooc.entity.Course;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@Repository
public class CourseDao {
private Map<Integer, Course> courses = new HashMap<Integer, Course>();
/**
* 新增课程
* @param course
*/
public void add(Course course) {
courses.put(course.getId(),course);
}
/**
* 查询全部课程
* @return
*/
public Collection<Course> getAll() {
return courses.values();
}
/**
* 通过id查询课程
*/
public Course getById(int id) {
return courses.get(id);
}
/**
* 修改课程
*/
public void update(Course course) {
courses.put(course.getId(),course);
}
/**
* 删除课程
*/
public void deleteById(int id) {
courses.remove(id);
}
}
CourseController.java:
import com.imooc.dao.CourseDao;
import com.imooc.entity.Course;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class CourseController {
@Autowired
private CourseDao courseDao;
/**
* 添加课程
*/
@PostMapping(value = "/add")
public String add(Course course) {
courseDao.add(course);
return "redirect:/getAll";
}
/**
* 查询全部课程
* @return
*/
@GetMapping(value = "/getAll")
public ModelAndView getAll() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
modelAndView.addObject("courses",courseDao.getAll());
return modelAndView;
}
/**
* 通过id查询课程
*/
@GetMapping(value = "/getById/{id}")
public ModelAndView getById(@PathVariable(value = "id")int id) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("edit");
modelAndView.addObject("course",courseDao.getById(id));
return modelAndView;
}
/**
* 修改课程
*/
@PutMapping(value = "/update")
public String update(Course course) {
courseDao.update(course);
return "redirect:/getAll";
}
/**
* 删除课程
*/
@DeleteMapping(value = "/delete/{id}")
public String delete(@PathVariable(value = "id")int id) {
courseDao.deleteById(id);
return "redirect:/getAll";
}
}
添加课程后,可进行编辑和删除
六、Spring MVC 拦截器
什么是拦截器?
拦截器(Interceptor): 用于在某个方法被访问之前进行拦截,然后在方法执行之前或之后加入某些操作,其实就是AOP的一种实现策略。它通过动态拦截Action调用的对象,允许开发者定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。
拦截器的作用:
拦截用户的请求并进行相应的处理,比如:判断用户是否登陆,是否在可购买时间内,记录日志信息等。
SpringMVC拦截器与过滤器的区别:
1、拦截器是使用JDK动态代理实现的,拦截的是对应调用方法的拦截
2、过滤器是使用Filter实现的,拦截是的request对象
3.二者适用范围不同。Filter是Servlet规范规定的,只能用于Web程序中,而拦截器既可以用于Web程序,也可以用于Application、Swing程序中。
4.规范不同。Filter是在Servlet规范定义的,是Servlet容器支持的,而拦截器是在Spring容器内的,是Spring框架支持的。
5.使用的资源不同。同其他代码块一样,拦截器也是一个Spring的组件,归Spring管理,配置在Spring文件中,因此能使用Spring里的任何资源、对象(各种bean),而Filter不行。
6.深度不同。Filter只在Servlet前后起作用,而拦截器能够深入到方法前后、异常跑出前后等,拦截器的使用有更大的弹性。
拦截器的具体操作:
首先要导入相关的依赖用的包:
pom.xml:
<!--便于日后开发项目中进行版本升级-->
<properties>
<spring-version>4.3.27.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--导入springmvc需要的jar-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-version}</version>
</dependency>
<!--导入servlet相关jar-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!--C标签的使用依赖包-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
webapp–>WEB-INF–>web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--
springmvc的核心servlet
第一种:[servlet-name]-servlet.xmlm比如:springmvc-servlet.xml
第二种:改变命名空间 namespace
这两种缺陷:必须配置文件放入web-inf目录下
第三种:通过contextConfigLocation
-->
<!--第一种:-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--第二种:-->
<init-param>
<param-name>namespace</param-name>
<param-value>springmvc-servlet</param-value>
</init-param>
<!-- 第三种:
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:WEB-INF/springmvc-servlet.xml</param-value>
</init-param> -->
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
webapp–>WEB-INF–>springmvc-servlet.xml:
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 配置自定义扫描包 -->
<context:component-scan base-package="com.imooc.web"></context:component-scan>
<!-- 映射物理路径 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
indexController.java:
package com.imooc.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class indexController {
@RequestMapping("/index")
public String index() {
return "index";
}
}
最后配置一下tomcat。
运行结果为:
到这里我们便搭建了一个完整的SpringMVC的框架。
其中具体的操作步骤为,这是我理解的,如有错误,望提醒:
因为我们的项目已经交给了tomcat,当一个用户发起请求,springmvc的核心servlet会进行拦截,因为我设计的是url-pattern> / </url-pattern,它拦截所有请求,然后DispatcherServlet里面是有很多注册的配置的,接下来它会读到我们的核心,就是说springmvc的控制器servlet会读取到和它项目规则相匹配的配置文件,刚好呢,配置文件认识我们的类indexController.java(控制器的类)就会加载到我们的内存中,后@RequestMapping就会注册当前的方法和信息,然后我们的servlet会根据我们的地址来找到对应的路由和里面的方法,找到方法后就跳转执行我们的逻辑,执行完我们的逻辑后就找视图。
在这里买个关,视图是怎么找到我们的页面的呢?
那就要看你当前springmvc的配件中,已定义的视图解析器是什么类型,类型包含(jsp配置等很多优秀的模板引擎),像现在我用的jsp配置是根据前缀和后缀
进行拼接来完成我们整个页面的返回和跳转,它里面默认的跳转方式是转发.
SpringMVC 拦截器的配置和应用:
SpringMVC也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器必须实现HandlerInterceptor接口
—preHandle():这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求request进行处理。
—如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回true;如果程序员决定不需要再调用其他
的组件去处理请求,则返回false。
—postHandle():这个方法在业务处理器处理完请求后,但是DispatcherServlet向客户端返回响应前被调用,在该方法中对用户请求request进行处理。
—afterCompletion():这个方法在DispathcherServlet完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。
SpringMVC拦截器拦截器方法的执行流程:
主要在springmvc-servlet.xml进行拦截器的注册:
<!-- 拦截器的注册 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/A/**"/>
<!--拦截所有资源-->
<bean class="com.imooc.core.LogInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<!-- 需要被拦截的方法
<mvc:mapping path="/A/B"/>
<mvc:mapping path="/A/C"/>
<mvc:mapping path="A/D"/>-->
<!-- *只能匹配一级
<mvc:mapping path="/A/*"></mvc:mapping>
**可匹配N级 -->
<mvc:mapping path="/A/**"></mvc:mapping>
<!--exclude-mapping在所有拦截中进行排除,一般在通配符会有意义。-->
<mvc:exclude-mapping path="/A/B"></mvc:exclude-mapping>
<mvc:exclude-mapping path="/A/C/*"></mvc:exclude-mapping>
<!--对日志进行请求处理-->
<bean class="com.imooc.core.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
拦截器注册运行程序的流程:
笔记的记录就到这里,上面我们说到SpringMVC的核心配置文件有三种,我们选择自己擅长的一种即可,若要更好的理解Spring系列的运用,那看源码是个不错的选择ψ(*`ー´)ψ
最后SSM框架的技术树: