1、清晰的角色划分:
前端控制器(DispatcherServlet)
请求到处理器映射(HandlerMapping)
处理器适配器(HandlerAdapter)
视图解析器(ViewResolver)
处理器或页面控制器(Controller)
验证器( Validator)
命令对象(Command 请求参数绑定到的对象就叫命令对象)
表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)。
2、分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要。
3、由于命令对象就是一个 POJO,无需继承框架特定 API,可以使用命令对象直接作为业务对象。
4、和 Spring 其他框架无缝集成,是其它 Web 框架所不具备的。
5、可适配,通过 HandlerAdapter 可以支持任意的类作为处理器。
6、可定制性,HandlerMapping、ViewResolver 等能够非常简单的定制。
7、功能强大的数据验证、格式化、绑定机制。
8、利用 Spring 提供的 Mock 对象能够非常简单的进行 Web 层单元测试。
9、本地化、主题的解析的支持,使我们更容易进行国际化和主题的切换。
10、强大的 JSP 标签库,使 JSP 编写更容易。
………………还有比如RESTful风格的支持、简单的文件上传、约定大于配置的契约式编程支持、基于注解的零配
置支持等等。

sprimgMVC工作流程和图

springMVC - 图1

1、用户发送请求至前端控制器DispatcherServlet
2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(二者组成HandlerExecutionChain),并将其一并返回给DispatcherServlet。
4、DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
5、执行处理器(Controller,也叫后端控制器)。
6、Controller执行完成返回ModelAndView
7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器
9、ViewReslover解析后返回具体View
10、DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet对用户进行响应

简而言之,SpringMVC通过DispatcherServlet这个前端控制器(也叫中央调度器,我认为中央调度器更能体现其作用),来调用mvc的三大件:Controller、Model、View。这样就保证MVC的每一个组件只与DispatcherServlet耦合,而彼此之间独立运行,大大降低了程序的耦合性。

再来说一下,SpringMVC这个框架时如何实现MVC模式的。
注意SpringMVC中并没有涉及有关于Controller接口规范的实现,SpringMVC是通过调用Handler来实现Controller这一层的。

SpringMVC使用了适配器模式,前端控制器使用HandlerAdapter来调用不同的Controller,然后才是Controller调用Model产生数据模型;
产生的数据模型将会再次返回到前端控制器,并由前端控制器决定使用不同的模板引擎将页面进行渲染。

springMVC - 图2

入门

idea springmvc工程启动两种方式

  • 配置tomcat服务器 server deployment
  • pom中加入tomcat7源 tomcat7:run

入门案例的执行流程

  1. 当启动Tomcat服务器的时候,因为配置了load-on-startup标签,所以会创建DispatcherServlet对象,
    就会加载springmvc.xml配置文件
  2. 开启了注解扫描,那么HelloController对象就会被创建
  3. 从index.jsp发送请求,请求会先到达DispatcherServlet核心控制器,根据配置@RequestMapping注解
    找到执行的具体方法
  4. 根据执行方法的返回值,再根据配置的视图解析器,去指定的目录下查找指定名称的JSP文件
  5. Tomcat服务器渲染页面,做出响应

入门案例中的组件分析

  1. 前端控制器(DispatcherServlet)
  2. 处理器映射器(HandlerMapping)
  3. 处理器(Handler)
  4. 处理器适配器(HandlAdapter)
  5. 视图解析器(View Resolver)
  6. 视图(View)

DispatcherServlet :前端控制器
用户请求到达前端控制器,它就相当于 mvc 模式中的 c,dispatcherServlet 是整个流程控制的中心,由
它调用其它组件处理用户的请求,dispatcherServlet 的存在降低了组件之间的耦合性。
2.3.2 HandlerMapping :处理器映射器
HandlerMapping 负责根据用户请求找到 Handler 即处理器,SpringMVC 提供了不同的映射器实现不同的
映射方式,例如:配置文件方式,实现接口方式,注解方式等。

HandlAdapter :处理器适配器
通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理
器进行执行。

View Resolver :视图解析器
View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名
即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。

View :视图
SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView
等。我们最常用的视图就是 jsp。
一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开
发具体的页面。

mvc:annotation-driven 说明

在 SpringMVC 的各个组件中,处理器映射器、处理器适配器、视图解析器称为 SpringMVC 的三大组件。
使 用 mvc:annotation-driven自 动加载 RequestMappingHandlerMapping (处理映射器) 和
RequestMappingHandlerAdapter ( 处 理 适 配 器 ) , 可 用 在 SpringMVC.xml 配 置 文 件 中 使 用
mvc:annotation-driven替代注解处理器和适配器的配置

springMVC - 图3

springMVC - 图4

  1. <!DOCTYPE web-app PUBLIC
  2. "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  3. "http://java.sun.com/dtd/web-app_2_3.dtd" >
  4. <web-app>
  5. <display-name>Archetype Created Web Application</display-name>
  6. <servlet>
  7. <servlet-name>dispatcherServlet</servlet-name>
  8. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  9. <!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 -->
  10. <init-param>
  11. <!--
  12. 3. 编写springmvc.xml的配置文件
  13. 4. 编写index.jsp和HelloController控制器类
  14. 1. index.jsp-->
  15. <param-name>contextConfigLocation</param-name>
  16. <param-value>classpath:springmvc.xml</param-value>
  17. </init-param>
  18. <!-- 配置servlet启动时加载对象 -->
  19. <load-on-startup>1</load-on-startup>
  20. </servlet>
  21. <servlet-mapping>
  22. <servlet-name>dispatcherServlet</servlet-name>
  23. <url-pattern>/</url-pattern>
  24. </servlet-mapping>
  25. </web-app>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       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/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 配置spring创建容器时要扫描的包 -->
    <context:component-scan base-package="cn.itcast"></context:component-scan>
    <!-- 配置视图解析器 -->
    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    <!-- 配置spring开启注解mvc的支持-->
    <mvc:annotation-driven></mvc:annotation-driven>
</beans>
package cn.itcast.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {
    @RequestMapping(path = "/hello")
    //@RequestMapping(value = "/hello",method={RequestMethod.GET})
    public String sayHello(){
        System.out.println("hello spring-mvc");
        return "success";
    }
}

RequestMapping 注解

源码:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
}

出现 位置:
类上:
请求 URL 的第一级访问目录。此处不写的话,就相当于应用的根目录。写的话需要以/开头。
它出现的目的是为了使我们的 URL 可以按照模块化管理:
例如:
账户模块:
/account/add
/account/update
/account/delete

订单模块:
/order/add
/order/update
/order/delete
红色的部分就是把 RequsetMappding 写在类上,使我们的 URL 更加精细。
方法上:
请求 URL 的第二级访问目录。
属性:
value:用于指定请求的 URL。它和 path 属性的作用是一样的。
method:用于指定请求的方式。
params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的 key 和 value 必须和
配置的一模一样。
例如:
params = {“accountName”},表示请求参数必须有 accountName
params = {“moeny!100”},表示请求参数中 money 不能是 100。
headers:用于指定限制请求消息头的条件。
注意:
以上四个属性只要出现 2 个或以上时,他们的关系是与的关系。

配置式开发

springMVC - 图5

springMVC - 图6

//web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
  <display-name>springmvc-1-primary</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <!-- 静态资源无法访问第一种解决方案 -->
  <!-- 
  <servlet-mapping>
      <servlet-name>default</servlet-name>
      <url-pattern>*.png</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
      <servlet-name>default</servlet-name>
      <url-pattern>*.js</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
      <servlet-name>default</servlet-name>
      <url-pattern>*.css</url-pattern>
  </servlet-mapping>
   -->
  <!-- 注册springmvc前端控制器(中央调度器) -->
  <servlet>
      <servlet-name>springmvc</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <!-- 指定springmvc配置文件的路径以及名称 -->
      <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>
//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>
    ${msg}
</body>
</html>
//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 MyController implements Controller {

    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView mv = new ModelAndView();
        System.out.println("进入到后端控制器方法!");
        mv.addObject("msg", "Hello SpringMVC!");
        mv.setViewName("/jsp/welcome.jsp");
        return mv;
    }

}
//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" 
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 注册后端控制器 -->
    <bean id="/my.do" class="com.bjsxt.handlers.MyController"></bean>
     <!-- 静态资源无法访问第二种解决方案 -->
    <!-- <mvc:default-servlet-handler/> -->
    <!-- 静态资源无法访问第三种解决方案 -->
    <mvc:resources location="/images/" mapping="/images/**"></mvc:resources>
</beans>

注解式开发

springMVC - 图7

其他和配置开发一样,修改controller和mvc.xml

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController {

    @RequestMapping("/handleRequest")
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView mv = new ModelAndView();
        System.out.println("进入到后端控制器方法!");
        mv.addObject("msg", "Hello SpringMVC!");
        mv.setViewName("/jsp/welcome.jsp");
        return mv;
    }

}
<?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"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">
   <!-- 注册组件扫描器 -->
    <context:component-scan base-package="com.bjsxt.handlers"></context:component-scan>
    <!-- 注册注解驱动 -->
    <mvc:annotation-driven/>

    <!-- 静态资源无法访问第二种解决方案 -->
    <!-- <mvc:default-servlet-handler/> -->
    <!-- 静态资源无法访问第三种解决方案 -->
    <mvc:resources location="/images/" mapping="/images/**"></mvc:resources>
</beans>

视图解析器

//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController {

    @RequestMapping("/hello")
    public String hello() {
        return "welcome";
    }

}
<?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"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">
   <!-- 注册组件扫描器 -->
    <context:component-scan base-package="com.bjsxt.handlers"></context:component-scan>
    <!-- 注册注解驱动 -->
    <mvc:annotation-driven/>
    <!-- 注册视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <!-- 静态资源无法访问第二种解决方案 -->
    <!-- <mvc:default-servlet-handler/> -->
    <!-- 静态资源无法访问第三种解决方案 -->
    <mvc:resources location="/images/" mapping="/images/**"></mvc:resources>
</beans>

参数

springMVC - 图8

乱码
//web.xml 
<!-- 配置编码方式过滤器,注意一点:要配置在所有过滤器的前面 -->
  <filter>
    <filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

如果是基本类型或者 String 类型:
要求我们的参数名称必须和控制器中方法的形参名称保持一致。(严格区分大小写)
是 如果是 POJO 类型 ,或者 它的关联对象 :
要求表单中参数名称和 POJO 类的属性名称保持一致。并且控制器方法的参数类型是 POJO 类型。
如果是集合类型, 有两种方式 :

第一种:
要求集合类型的请求参数必须在 POJO 中。在表单中请求参数名称要和 POJO 中集合属性名称相同。
给 List 集合中的元素赋值,使用下标。
给 Map 集合中的元素赋值,使用键值对。
第二种:
接收的请求参数是 json 格式数据。需要借助一个注解实现

逐个接受
//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController{
    @RequestMapping("/hello")
    public ModelAndView hello(@RequestParam("username") String name,int age){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("username", name);
        modelAndView.addObject("age", age);
        modelAndView.setViewName("welcome");
        return modelAndView;
    }

}

对象接受
//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController{
    @RequestMapping("/hello")
    public ModelAndView hello(Star star){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("username", star.getUsername());
        modelAndView.addObject("age", star.getAge());
        modelAndView.setViewName("welcome");
        return modelAndView;
    }

}

域属性接受
package com.bjsxt.pojo;

public class Star {
    private String username;
    private int age;

    //域属性,也称为对象属性
    private Parter parter;

    public Parter getParter() {
        return parter;
    }
    public void setParter(Parter parter) {
        this.parter = parter;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }


}
public class Parter {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}
<form action="springmvc/hello" method="POST">
        用户名:<input type="text" name="username"></br>
        年龄:<input type="text" name="age"></br>
        伴侣名称:<input type="text" name="parter.name"></br>
        <input type="submit" value="提交">
    </form>
//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController{
    @RequestMapping("/hello")
    public ModelAndView hello(Star star){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("username", star.getUsername());
        modelAndView.addObject("age", star.getAge());
        modelAndView.addObject("partnerName", star.getParter().getName());
        modelAndView.setViewName("welcome");
        return modelAndView;
    }

}

数组集合接受
实体类代码:
/**
* 用户实体类
* @author 黑马程序员
* @Company http://www.ithiema.com
* @Version 1.0
*/
public class User implements Serializable {
private String username;
private String password;
private Integer age;
private List<Account> accounts;
private Map<String,Account> accountMap;
//getters and setters
@Override
public String toString() {
return "User [username=" + username + ", password=" + password + ", age="
+ age + ",\n accounts=" + accounts
+ ",\n accountMap=" + accountMap + "]";
}
}
jsp  代码:
<!-- POJO 类包含集合类型演示 -->
<form action="account/updateAccount" method="post">
用户名称:<input type="text" name="username" ><br/>
用户密码:<input type="password" name="password" ><br/>
用户年龄:<input type="text" name="age" ><br/>
账户 1 名称:<input type="text" name="accounts[0].name" ><br/>
账户 1 金额:<input type="text" name="accounts[0].money" ><br/>
账户 2 名称:<input type="text" name="accounts[1].name" ><br/>
账户 2 金额:<input type="text" name="accounts[1].money" ><br/>
账户 3 名称:<input type="text" name="accountMap['one'].name" ><br/>
账户 3 金额:<input type="text" name="accountMap['one'].money" ><br/>
账户 4 名称:<input type="text" name="accountMap['two'].name" ><br/>
账户 4 金额:<input type="text" name="accountMap['two'].money" ><br/>
<input type="submit" value=" 保存 ">
</form>
控制器代码:
/**
* 更新账户
* @return
*/
@RequestMapping("/updateAccount")
public String updateAccount(User user) {
System.out.println("更新了账户。。。。"+user);
return "success";
}
<form action="springmvc/hello" method="POST">
        <input type="checkbox" name="interest" value="a1">a1</br>
        <input type="checkbox" name="interest" value="a2">a2</br>
        <input type="checkbox" name="interest" value="a3">a3</br>
        <input type="submit" value="提交">
    </form>
//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController{
    //数组接收参数
    /*
    @RequestMapping("/hello")
    public void  hello(String[] interest){
        for (String string : interest) {
            System.out.println(string);
        }
    }
    */
    //集合接收参数 @RequestParam是必须的
    @RequestMapping("/hello")
    public void  hello1(@RequestParam List<String> interest){
        for (String string : interest) {
            System.out.println(string);
        }
    }

}

restful接受
//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController{
    //restful风格传参
    @RequestMapping("/{name}/{age}/hello")
    public void  hello1(@PathVariable String name,@PathVariable int age){
            System.out.println(name+age);
    }

}

json接受

springMVC - 图9

<!-- 静态资源无法访问第三种解决方案 -->
    <mvc:resources location="/images/" mapping="/images/**"></mvc:resources>
    <mvc:resources location="/js/" mapping="/js/**"></mvc:resources>
$(function(){
        $("#myButton").click(function(){
            var data1={username:"zhangsan",age:23};
            $.ajax({
                url:"${pageContext.request.contextPath}/springmvc/hello",
                type: "POST",
                contentType:"application/json",
                data:JSON.stringify(data1),
            })
        })

    })
//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController{
    //接收json字符串并封装成对象
    @RequestMapping("/hello")
    public void  hello1(@RequestBody Star star){
        System.out.println(star);
    }

}
public class Star {
    private String username;
    private int age;

    //域属性,也称为对象属性
    private Parter parter;

    public Parter getParter() {
        return parter;
    }
    public void setParter(Parter parter) {
        this.parter = parter;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Star [username=" + username + ", age=" + age + ", parter=" + parter + "]";
    }

}

请求头接受
//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController{
    //接收json字符串并封装成对象
    @RequestMapping("/hello")
    public void  hello1(@RequestHeader String host,@RequestHeader String cookie){
        System.out.println(host + " ----------"+cookie);
    }

}

自定义类型转换器

<%--自定义类型转换器--%>
    <form action="param/saveUser" method="post">
        用户姓名:<input type="text" name="uname" /><br/>
        用户年龄:<input type="text" name="age" /><br/>
        用户生日:<input type="text" name="date" /><br/>
        <input type="submit" value="提交" />
    </form>
package cn.itcast.utils;

import org.springframework.core.convert.converter.Converter;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 把字符串转换日期
 */
public class StringToDateConverter implements Converter<String,Date>{

    /**
     * String source    传入进来字符串
     * @param source
     * @return
     */
    public Date convert(String source) {
        // 判断
        if(source == null){
            throw new RuntimeException("请您传入数据");
        }
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");

        try {
            // 把字符串转换日期
            return df.parse(source);
        } catch (Exception e) {
            throw new RuntimeException("数据类型转换出现错误");
        }
    }

}
/**
     * 自定义类型转换器
     * @param user
     * @return
     */
    @RequestMapping("/saveUser")
    public String saveUser(User user){
        System.out.println("执行了...");
        System.out.println(user);
        return "success";
    }
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       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/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 配置spring创建容器时要扫描的包 -->
    <context:component-scan base-package="cn.itcast"></context:component-scan>
    <!-- 配置视图解析器 -->
    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <!--配置自定义类型转换器-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="cn.itcast.utils.StringToDateConverter"/>
            </set>
        </property>
    </bean>

    <!-- 配置spring开启注解mvc的支持-->
    <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
</beans>

获取servletAPI

<a href="param/testServlet">Servlet原生的API</a>
    /**
     * 原生的API
     * @return
     */
    @RequestMapping("/testServlet")
    public String testServlet(HttpServletRequest request, HttpServletResponse response){
        System.out.println("执行了...");
        System.out.println(request);

        HttpSession session = request.getSession();
        System.out.println(session);

        ServletContext servletContext = session.getServletContext();
        System.out.println(servletContext);

        System.out.println(response);
        return "success";
    }

常用注解

RequestParam

统一传入参数和方法参数

<a href="anno/testRequestParam?name=哈哈">RequestParam</a>
@RequestMapping("/testRequestParam")
    public String testRequestParam(@RequestParam(name="name") String username){
        System.out.println("执行了...");
        System.out.println(username);
        return "success";
    }

RequestBody

用于获取请求体内容。直接使用得到是 key=value&key=value…结构的数据。
get 请求方式不适用

    <form action="anno/testRequestBody" method="post">
        用户姓名:<input type="text" name="username" /><br/>
        用户年龄:<input type="text" name="age" /><br/>
        <input type="submit" value="提交" />
    </form>
/**
     * 获取到请求体的内容
     * @return
     */
    @RequestMapping("/testRequestBody")
    public String testRequestBody(@RequestBody String body){
        System.out.println("执行了...");
        System.out.println(body);
        return "success";
    }

PathVaribale

用于绑定 url 中的占位符。例如:请求 url 中 /delete/{id},这个{id}就是 url 占位符。
url 支持占位符是 spring3.0 之后加入的。是 springmvc 支持 rest 风格 URL 的一个重要标志

<a href="anno/testPathVariable/10">testPathVariable</a>
/**
     * PathVariable注解
     * @return
     */
    @RequestMapping(value="/testPathVariable/{sid}")
    public String testPathVariable(@PathVariable(name="sid") String id){
        System.out.println("执行了...");
        System.out.println(id);
        return "success";
    }

RequestHeader

用于获取请求消息头

jsp  中代码:
<!-- RequestHeader 注解 -->
<a href="springmvc/useRequestHeader">获取请求消息头</a>
控制器中代 码:
/**
* RequestHeader 注解
* @param user
* @return
*/
@RequestMapping("/useRequestHeader")
public String  useRequestHeader(@RequestHeader(value="Accept-Language",
required=false)String requestHeader){
System.out.println(requestHeader);
return "success";
}

CookieValue

用于把指定 cookie 名称的值传入控制器方法参数

/**
     * 获取Cookie的值
     * @return
     */
    @RequestMapping(value="/testCookieValue")
    public String testCookieValue(@CookieValue(value="JSESSIONID") String cookieValue){
        System.out.println("执行了...");
        System.out.println(cookieValue);
        return "success";
    }

ModelAttribute

该注解是 SpringMVC4.3 版本以后新加入的。它可以用于修饰方法和参数。
出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可
以修饰有具体返回值的方法。
出现在参数上,获取指定的数据给参数赋值。

当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据。
例如:
我们在编辑一个用户时,用户有一个创建信息字段,该字段的值是不允许被修改的。在提交表单数
据是肯定没有此字段的内容,一旦更新会把该字段内容置为 null,此时就可以使用此注解解决问题。

 /**
     * ModelAttribute注解
     * @return
     */
    @RequestMapping(value="/testModelAttribute")
    public String testModelAttribute(@ModelAttribute("abc") User user){
        System.out.println("testModelAttribute执行了...");
        System.out.println(user);
        return "success";
    }

    @ModelAttribute
    public void showUser(String uname, Map<String,User> map){
        System.out.println("showUser执行了...");
        // 通过用户查询数据库(模拟)
        User user = new User();
        user.setUname(uname);
        user.setAge(20);
        user.setDate(new Date());
        map.put("abc",user);
    }

SessionAttribute

用于多次执行控制器方法间的参数共享。

@SessionAttributes(value={"msg"})   // 把msg=美美存入到session域对中
public class AnnoController {

/**
     * SessionAttributes的注解
     * @return
     */
    @RequestMapping(value="/testSessionAttributes")
    public String testSessionAttributes(Model model){
        System.out.println("testSessionAttributes...");
        // 底层会存储到request域对象中
        model.addAttribute("msg","美美");
        return "success";
    }

    /**
     * 获取值
     * @param modelMap
     * @return
     */
    @RequestMapping(value="/getSessionAttributes")
    public String getSessionAttributes(ModelMap modelMap){
        System.out.println("getSessionAttributes...");
        String msg = (String) modelMap.get("msg");
        System.out.println(msg);
        return "success";
    }

    /**
     * 清除
     * @param status
     * @return
     */
    @RequestMapping(value="/delSessionAttributes")
    public String delSessionAttributes(SessionStatus status){
        System.out.println("getSessionAttributes...");
        status.setComplete();
        return "success";
    }

返回值

ModelAndView 既要跳转也要传值

return String
<form action="${pageContext.request.contextPath}/springmvc/hello" method="POST">
        姓名:<input type="text" name="username"><br/>
        年龄:<input type="text" name="age"><br/>
        <input type="submit" value="提交"><br/>
    </form>
//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController{
    //接收json字符串并封装成对象
    @RequestMapping("/hello")
    public String  hello1(String username,int age,Model model,Map<String, Object> map,ModelMap modelMap){
        System.out.println(username + " ----------"+age);
        model.addAttribute("username", username);
        map.put("age", age);
        modelMap.addAttribute("gender", "female");
        return "welcome";
    }

}
<body>
    欢迎页面!${username}--${age}--${gender}
</body>

void
   /**
     * 是void
     * 请求转发一次请求,不用编写项目的名称
     */
    @RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("testVoid方法执行了...");
        // 编写请求转发的程序
        // request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);

        // 重定向
        // response.sendRedirect(request.getContextPath()+"/index.jsp");

        // 设置中文乱码
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        // 直接会进行响应
        response.getWriter().print("你好");

        return;
    }

ModelAndView
    /**
     * 返回ModelAndView
     * @return
     */
    @RequestMapping("/testModelAndView")
    public ModelAndView testModelAndView(){
        // 创建ModelAndView对象
        ModelAndView mv = new ModelAndView();
        System.out.println("testModelAndView方法执行了...");
        // 模拟从数据库中查询出User对象
        User user = new User();
        user.setUsername("小凤");
        user.setPassword("456");
        user.setAge(30);

        // 把user对象存储到mv对象中,也会把user对象存入到request对象
        mv.addObject("user",user);

        // 跳转到哪个页面
        mv.setViewName("success");

        return mv;
    }

返回中文
$(function(){
        $("#myButton").click(function(){
            $.ajax({
                url:"${pageContext.request.contextPath}/springmvc/hello",
                type: "POST",
                success: function(data){
                    alert(data);
                }
            })
        })

    })
//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController{
    //接收json字符串并封装成对象
    @RequestMapping(value="/hello",produces="text/html;charset=utf-8")
    @ResponseBody
    public String  hello1(){
        return "china:瓷器";
    }

}

@ResponseBody是作用在方法上的,@ResponseBody 表示该方法的返回结果直接写入 HTTP response body 中,一般在异步获取数据时使用【也就是AJAX】,在使用 @RequestMapping后,返回值通常解析为跳转路径,但是加上 @ResponseBody 后返回结果不会被解析为跳转路径,而是直接写入 HTTP response body 中。 比如异步获取 json 数据,加上 @ResponseBody 后,会直接返回 json 数据。@RequestBody 将 HTTP 请求正文插入方法中,使用适合的 HttpMessageConverter 将请求体写入某个对象。

@ResponseBody需要jackson包

返回流
$(function(){
        $("#myButton").click(function(){
            $.ajax({
                url:"${pageContext.request.contextPath}/springmvc/hello",
                type: "POST",
                success: function(data){
                    var data1 = eval("("+data+")");
                    alert(data1.flavor);
                }
            })
        })

    })
//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController{
    //接收json字符串并封装成对象
    @RequestMapping(value="/hello",produces="text/html;charset=utf-8")
    public void  hello1(HttpServletResponse response) throws IOException{
        String json="{\"name\":\"weilong\",\"flavor\":\"hot\"}";
        response.getWriter().print(json);
    }

}

返回OBJECT
//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController{
    @RequestMapping(value="/hello",produces="text/html;charset=utf-8")
    @ResponseBody  //将当前方法的返回值放到响应体中,并且转换成json格式
    public Object  hello1(){
        return "aaa";
    }

}

响应AJAX
//spring.xml
<!--前端控制器,哪些静态资源不拦截-->
    <mvc:resources location="/css/" mapping="/css/**"/>
    <mvc:resources location="/images/" mapping="/images/**"/>
    <mvc:resources location="/js/" mapping="/js/**"/>
<script src="js/jquery.min.js"></script>

    <script>
        // 页面加载,绑定单击事件
        $(function(){
            $("#btn").click(function(){
                // alert("hello btn");
                // 发送ajax请求
                $.ajax({
                    // 编写json格式,设置属性和值
                    url:"user/testAjax",
                    contentType:"application/json;charset=UTF-8",
                    data:'{"username":"hehe","password":"123","age":30}',
                    dataType:"json",
                    type:"post",
                    success:function(data){
                        // data服务器端响应的json的数据,进行解析
                        alert(data);
                        alert(data.username);
                        alert(data.password);
                        alert(data.age);
                    }
                });

            });
        });

    </script>
    /**
     * 模拟异步请求响应
     */
    @RequestMapping("/testAjax")
    public @ResponseBody User testAjax(@RequestBody User user){
        System.out.println("testAjax方法执行了...");
        // 客户端发送ajax的请求,传的是json字符串,后端把json字符串封装到user对象中
        System.out.println(user);
        // 做响应,模拟查询数据库
        user.setUsername("haha");
        user.setAge(40);
        // 做响应
        return user;
    }

需要jackson

<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.0</version>
    </dependency>

转发和重定向

 /**
     * 使用关键字的方式进行转发或者重定向
     * @return
     */
    @RequestMapping("/testForwardOrRedirect")
    public String testForwardOrRedirect(){
        System.out.println("testForwardOrRedirect方法执行了...");

        // 请求的转发
        // return "forward:/WEB-INF/pages/success.jsp";

        // 重定向
        return "redirect:/index.jsp";
    }
//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController{
    @RequestMapping("/hello")
    public ModelAndView hello(String username,int age){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("username", username);
        modelAndView.addObject("age", age);
        //modelAndView.setViewName("welcome"); 请求转发
        //重定向 接收不到参数了 只有接收地址栏参数
        modelAndView.setViewName("redirect:/jsp/welcome.jsp");
        return modelAndView;
    }

}
<body>
    欢迎页面!${param.username}--${param.age}
</body>

处理器重定向

//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController{
    @RequestMapping("/hello")
    public ModelAndView hello(String username,int age){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("username", username);
        modelAndView.addObject("age", age);
        modelAndView.setViewName("redirect:some");
        return modelAndView;
    }
    @RequestMapping("/some")
    public ModelAndView some(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("welcome");
        return modelAndView;
    }

}

文件上传

单个

springMVC - 图10

<!-- 注册组件扫描器 -->
    <context:component-scan base-package="com.bjsxt.handlers"></context:component-scan>
    <!-- 注册注解驱动 -->
    <mvc:annotation-driven/>
    <!-- 注册视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    <!-- 注册文件上传解析器 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="utf-8"></property>
    </bean>

    <!-- 静态资源无法访问第二种解决方案 -->
    <!-- <mvc:default-servlet-handler/> -->
    <!-- 静态资源无法访问第三种解决方案 -->
    <mvc:resources location="/images/" mapping="/images/**"></mvc:resources>
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController{
    @RequestMapping("/fileUpload")
    public String fileUpload(MultipartFile img){
        String path="d:/";
        String fileName = img.getOriginalFilename();
        File file = new File(path, fileName );
        try {
            img.transferTo(file);
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return "welcome";
    }

}
<form action="springmvc/fileUpload" method="POST" enctype="multipart/form-data">
    <input type="file" name="img"></br>
    <input type="submit" value="上传">
</form>

多个

//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController{
    @RequestMapping("/fileUpload")
    public String fileUpload(@RequestParam MultipartFile[] imgs,HttpSession session){
        String path=session.getServletContext().getRealPath("/");
        for (MultipartFile img : imgs) {
            String fileName = img.getOriginalFilename();
            File file = new File(path, fileName );
            try {
                img.transferTo(file);
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "welcome";
    }

}

跨服务器

  /**
     * 跨服务器文件上传
     * @return
     */
    @RequestMapping("/fileupload3")
    public String fileuoload3(MultipartFile upload) throws Exception {
        System.out.println("跨服务器文件上传...");

        // 定义上传文件服务器路径
        String path = "http://localhost:9090/uploads/";

        // 说明上传文件项
        // 获取上传文件的名称
        String filename = upload.getOriginalFilename();
        // 把文件的名称设置唯一值,uuid
        String uuid = UUID.randomUUID().toString().replace("-", "");
        filename = uuid+"_"+filename;

        // 创建客户端的对象
        Client client = Client.create();

        // 和图片服务器进行连接
        WebResource webResource = client.resource(path + filename);

        // 上传文件
        webResource.put(upload.getBytes());

        return "success";
    }
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
    </dependency>

    <dependency>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-core</artifactId>
      <version>1.18.1</version>
    </dependency>
    <dependency>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-client</artifactId>
      <version>1.18.1</version>
    </dependency>

文件下载

//后端控制器
@Controller //该注解表将当前类交给spring容器管理
@Scope("prototype")
@RequestMapping("/springmvc")  //该注解起到限定范围的作用
public class MyController{
    @RequestMapping("/fileDowload")
    public ResponseEntity<byte[]> dowload() throws IOException{
        //指定下载文件
        File file = new File("d:/美女.png");
        InputStream is = new FileInputStream(file);
        //创建字节数组,并且设置数组大小为预估的文件字节数
        byte[] body = new byte[is.available()];
        //将输入流中字符存储到缓存数组中
        is.read(body);
        //获取下载显示的文件名,并解决中文乱码
        String name = file.getName();
        String downLoadFileName = new String(name.getBytes("UTF-8"),"ISO-8859-1");
        //设置Http响应头信息,并且通知浏览器以附件的形式进行下载
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Disposition", "attachment;filename="+downLoadFileName);
        //设置Http响应状态信息
        HttpStatus status = HttpStatus.OK;
        ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(body, httpHeaders, status);
        return responseEntity;

    }
}

异常处理

springMVC - 图11

package cn.itcast.exception;

/**
 * 自定义异常类
 */
public class SysException extends Exception{

    // 存储提示信息的
    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public SysException(String message) {
        this.message = message;
    }

}
package cn.itcast.exception;

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 异常处理器
 */
public class SysExceptionResolver implements HandlerExceptionResolver{

    /**
     * 处理异常业务逻辑
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @return
     */
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 获取到异常对象
        SysException e = null;
        if(ex instanceof SysException){
            e = (SysException)ex;
        }else{
            e = new SysException("系统正在维护....");
        }
        // 创建ModelAndView对象
        ModelAndView mv = new ModelAndView();
        mv.addObject("errorMsg",e.getMessage());
        mv.setViewName("error");
        return mv;
    }

}
package cn.itcast.controller;

import cn.itcast.exception.SysException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/user")
public class UserController {


    @RequestMapping("/testException")
    public String testException() throws SysException{
        System.out.println("testException执行了...");

        try {
            // 模拟异常
            int a = 10/0;
        } catch (Exception e) {
            // 打印异常信息
            e.printStackTrace();
            // 抛出自定义异常信息
            throw new SysException("查询所有用户出现错误了...");
        }



        return "success";
    }

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       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/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 开启注解扫描 -->
    <context:component-scan base-package="cn.itcast"/>

    <!-- 视图解析器对象 -->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--前端控制器,哪些静态资源不拦截-->
    <mvc:resources location="/css/" mapping="/css/**"/>
    <mvc:resources location="/images/" mapping="/images/**"/>
    <mvc:resources location="/js/" mapping="/js/**"/>

    <!--配置异常处理器-->
    <bean id="sysExceptionResolver" class="cn.itcast.exception.SysExceptionResolver"/>

    <!-- 开启SpringMVC框架注解的支持 -->
    <mvc:annotation-driven />

</beans>

拦截器

过滤器是 servlet 规范中的一部分,任何 java web 工程都可以使用。
拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。
拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦
截的。

springMVC - 图12

 <!-- 注册组件扫描器 -->
    <context:component-scan base-package="com.bjsxt.handlers"></context:component-scan>
    <!-- 注册注解驱动 -->
    <mvc:annotation-driven/>
    <!-- 注册视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <!-- 注册拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- <mvc:mapping path="/springmvc/hello"/> -->
            <mvc:mapping path="/**"/>
            <!-- <mvc:exclude-mapping path="/springmvc/hello2"/> -->
            <bean id="" class="com.bjsxt.interceptors.FirstInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

    <!-- 静态资源无法访问第二种解决方案 -->
    <!-- <mvc:default-servlet-handler/> -->
    <!-- 静态资源无法访问第三种解决方案 -->
    <mvc:resources location="/images/" mapping="/images/**"></mvc:resources>
    <mvc:resources location="/js/" mapping="/js/**"></mvc:resources>
//自定义拦截器
public class FirstInterceptor implements HandlerInterceptor {
    //该方法执行时机:处理器方法执行之前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("拦截器preHandle()执行!");
        //false就中断了,不进入处理器
        return true;
    }

    //该方法执行时机:处理器方法执行之后执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器postHandle()执行!");

    }

    //该方法执行时机:所有工作处理完成之后,响应给浏览器客户端之前执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("拦截器afterCompletion()执行!");

    }

}

多个拦截器

<!-- 注册拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean id="" class="com.bjsxt.interceptors.FirstInterceptor"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean id="" class="com.bjsxt.interceptors.SecondInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
//后端控制器
@Controller 
@Scope("prototype")
@RequestMapping("/springmvc")  
public class MyController{
    @RequestMapping("/hello2")
    public String  hello2(String username,int age,Model model,Map<String, Object> map,ModelMap modelMap){
        System.out.println(username + " 2222----------2222"+age);
        model.addAttribute("username", username);
        map.put("age", age);
        modelMap.addAttribute("gender", "female");
        return "welcome";
    }

}
//自定义拦截器
public class FirstInterceptor implements HandlerInterceptor {
    //该方法执行时机:处理器方法执行之前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("First拦截器preHandle()执行!");
        return true;
    }

    //该方法执行时机:处理器方法执行之后执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("First拦截器postHandle()执行!");

    }

    //该方法执行时机:所有工作处理完成之后,响应给浏览器客户端之前执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("First拦截器afterCompletion()执行!");

    }

}
public class SecondInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("Second的preHandle()执行!");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("Second的postHandle()执行!");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("Second的afterCompletion()执行!");

    }
}

springMVC - 图13

springMVC - 图14