SpringMVC详解

spring-web提供了核心http功能集成
spring-webmvc基于spring-web。如果你依赖了spring-webmvc就不需要显式依赖spring-web。

spring-web 提供了核心 HTTP 集成,包括一些便捷的 servlet 过滤器, Spring HTTP 调用,用于集成其它 web 框架的基础结构以及技术(Hessian,Burlap)。

spring-webmvc 是 Spring MVC 的一个实现。spriing-webmvc 依赖于 spring-web,这样包含它就会间接地添加 spring-web。不必显示添加 spring-web。

如果你不使用 Spring MVC ,但想要借助其它 Spring 支持的 web 相关技术的优势,那么你只需依赖 spring-web 。

一、Spring与Web环境集成概述

ApplicationContext:应用上下文对象,通过new ClasspathXmlApplicationContext(spring配置文件) 方式获取

ServletContextListener:Web项目中

1、使用ServletContextListener监听Web应用的启动

2、在Web应用启动时,就加 载Spring的配置文件,创建应用上下文对象ApplicationContext

3、在将其存储到最大的域servletContext域 中,这样就可以在任意位置从域中获得应用上下文ApplicationContext对象

ContextLoaderListener:Spring提供的监听器,对上述功能的封装

1、监听器内部加载Spring配置文件

2、创建应用上下文对象ApplicationContext,存储到最大的域servletContext

3、并提供了客户端工具WebApplicationContextUtils供使用者在获得上下文对象

(1)导入spring-web坐标

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>

(2)配置ContextLoaderListener监听器

<!--全局参数-->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>

<!--Spring的监听器-->
<listener>
    <listener-class>
    	org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

(3)获取上下文对象

ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
Object obj = applicationContext.getBean("id");

二、SpringMVC快速入门

(1)导入 Spring、SpringMVC、Servlet,Jsp 的坐标

<!--Spring坐标-->
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>
<!--SpringMVC坐标-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>

<!--Servlet坐标-->
    <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
</dependency>
<!--Jsp坐标-->
<dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.0</version>
</dependency>

(2)web.xml配置SpringMVC的核心控制器

<servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

(3)创建Controller、业务方法、视图页面index.jsp配置注解

@Controller
public class QuickController {
    @RequestMapping("/quick")
    public String quickMethod(){
        System.out.println("quickMethod running.....");
        return "index";
	}
}


视图index:
<html>
<body>
	<h2>Hello SpringMVC!</h2>
</body>
</html>

(4)创建spring-mvc.xml

<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="com.itheima"/>
</beans>

(5)测试访问地址

http://localhost:8080/itheima_springmvc1/quick 

三、SpringMVC组件

(1)组件

1、DispatcherServlet(前端控制器):用户请求到达前端控制器,它就相当于MVC 模式中的C,DispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,DispatcherServlet的存在降低了组件之间的耦合性。

2、HandlerMapping(处理器映射器): HandlerMapping负责根据用户请求找到Handler 即处理器,SpringMVC提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

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

4、Handler(处理器):它就是我们开发中要编写的具体业务控制器。由DispatcherServlet把用户请求转发到Handler。由 Handler 对具体的用户请求进行处理。

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

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

7、Model:”模型“的意思,是MVC架构中的”M“部分,是用来传输数据的

8、ModelAndView:模型和视图“,可以理解成MVC架构中的”M“和”V“,其中包含”Model“和”view“两部分,表示处理程序返回的模型和视图,由 DispatcherServlet 通过 ViewResolver 解析。 该模型是一个Map,允许使用多个按名称键控的对象。视图可以采用String视图名的形式,需要通过ViewResolver对象解析; 或者,可以直接指定一个View对象。 ModeAndView主要功能:设置转向地址、将底层获取的数据进行存储(或者封装)、最后将数据传递给View。

(2)SpringMVC执行流程

1、用户发送请求至前端控制器DispatcherServlet。

2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。

3、处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。

4、DispatcherServlet调用HandlerAdapter处理器适配器。

5、HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。

6、Controller执行完成返回ModelAndView。

7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。

8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器。

9、ViewReslover解析后返回具体View。

10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。DispatcherServlet响应用户。

四、注解与XML配置

(1)注解**@RequestMapping:**

  • 作用:用于建立URL请求和处理请求方法之间的对应关系
  • 在类上,请求URL的第一级访问目录,不写的话,相当于根目录
  • 在方法上,请求URL的第二级访问目录,与类上的@RequestMapping标注的以及目录一起组成访问虚拟路径
  • value:用于指定请求的URL。与path属性的作用相同
  • method:用于指定请求方式
  • params:用于指定限制请求参数条件
  • params = {“accountName”}:请求参数必须有accountName
  • params={“moneny!=100”}:请求参数money不能是100

(2)XML配置

1、mvc命名空间
命名空间:xmlns:context="http://www.springframework.org/schema/context"
		 xmlns:mvc="http://www.springframework.org/schema/mvc"
约束地址: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


2、组件扫描
将Controller存储到Spring容器中,用@Controller注解标注,需要使用
<context:component-scan base-package="com.itheima.controller"/>进行组件扫描。


3、视图解析器
SpringMVC有默认组件配置,默认组件都是DispatcherServlet.properties配置文件中配置的

该配置文件地址org/springframework/web/servlet/DispatcherServlet.properties

该文件中配置了默认的视图解析器org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

解析器默认设置:
REDIRECT_URL_PREFIX = "redirect:" --重定向前缀
FORWARD_URL_PREFIX = "forward:" --转发前缀(默认值)
prefix = ""; --视图名称前缀
suffix = ""; --视图名称后缀


通过注入的方式修改视图的前后缀
<!--配置内部资源视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"></property>
    <property name="suffix" value=".jsp"></property>
</bean>

五、视图详解

(1)Model与ModelAndView区别:

1、Model只是用来传输数据的,并不会进行业务的寻址。ModelAndView 却是可以进行业务寻址的,就是设置对应的要请求的静态文件,这里的静态文件指的是类似jsp的文件。Model是每次请求中都存在的默认参数,利用其addAttribute()方法即可将服务器的值传递到jsp页面中;ModelAndView包含model和view两部分,使用时需要自己实例化,利用ModelMap来传值,也可以设置view的名称。

2、Model是每一次请求可以自动创建,但是ModelAndView 是需要我们自己去new的。

(2)Model常用方法

public interface Model {
 
    Model addAttribute(String attributeName, @Nullable Object attributeValue);
 
    Model addAttribute(Object attributeValue);
 
    Model addAllAttributes(Collection<?> attributeValues);
 
    Model addAllAttributes(Map<String, ?> attributes);
 
}
/*
 * controller 负责提供访问应用程序的行为,通常通过接口定义或者注解定义两种方法实现。
 * 控制器负责解析用户的请求并将其转换为一个模型。
 * */
@Controller  //代表这个类会被spring接管,被这个注解的类中所有方法,如果返回值是string,并且有具体的页面可以跳转,那么就会被视图解析器解析
public class IndexController {
     
    @RequestMapping("/hello")   //意为请求 localhost:8080/hello 
    public String hello(Model model){
        //封装数据(向模型中添加数据,可以jsp页面直接取出并渲染)
        model.addAttribute("name","张三");
        model.addAttribute("sex","男");
        model.addAttribute("age",23);
        System.out.println(model);
        //会被视图解析器处理
        return "hello";   //返回到哪个页面     
    }
    
    @RequestMapping("/hello2")
    public String hello2(Model model){
        Person person =new Person();
        person.name="张三";
        person.age=16;
        person.sex="男";
        System.out.println(person);
        model.addAttribute("person",person);
        return "hello";
    }
}

(3)ModelAndView常用方法

ModelAndView(String viewName, String modelName, Object modelObject) //构造方法
ModelAndView  addAllObjects(Map modelMap)  //添加包含在所提供的地图模型中的所有条目。
ModelAndView  addObject(Object modelObject)  //添加对象使用的参数名称生成模型。
ModelAndView  addObject(String modelName,ObjectmodelObject)  //对象添加到模型中。
//ModelAndView():这个构造方法构造出来的ModelAndView不能直接使用,没有指定view,也没有绑定model对象,当然,model对象不是必须的,但是view确实必须的。用这个构造方法构造的实例主要用来在以后往其中加view设置和model对象
@Controller
@RequestMapping
public class IndexController {
	/**
     * 利用ModelAndView来转发数据,给前端视图
     * @return
     */
    @RequestMapping("/m06")
    public ModelAndView m06() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("m06");
        modelAndView.addObject("message", "Hello World, Hello Kitty");
        return modelAndView;
    }
    
    /**
     * 利用ModelAndView来转发数据,给前端视图
     * @return
     */
    @RequestMapping("/m07")
    public ModelAndView m07() {
        return new ModelAndView("m07", "message", "Hello World");
    }
    
    /**
     * ModelAndView默认转发
     * ModelAndView还是可以设置重定向
     * 1. 重定向另一个控制器
     * 2. 重定向具体的jsp页面
     * @param name
     * @return
     */
    @RequestMapping("/{name}/m07")
    public ModelAndView m07(@PathVariable String name) {
        if (!"admin".equals(name)) {
            return new ModelAndView("redirect:/m07.jsp");
        }
        return new ModelAndView("m07");
    }

    
}

(4)ModelAndView具体实例

@RequestMapping("mvc")
@Controller
public class TestRequestMMapping {
	
	@RequestMapping(value="/testModelAndView")
	public ModelAndView testModelAndView(){
		ModelAndView mav = new ModelAndView();
		mav.setViewName("hello");//跳转新的页面名称
		mav.addObject("address", "中国广东省广州市");//传入request作用域参数
		return mav;
	}
}

跳转jsp页面以及request作用于取值

<title>New Page</title>
</head>
<body>
	<h1>ModelAndView 跳转</h1>
	
	<br>
	
	${requestScope.address}   
	
	<br>
	
	${address }    
 
	<br>	
	
</body>

六、视图解析器详解

当一个请求被HandlerMapping处理完后,会返回一个ModelAndView对象,springmvc借助视图解析器(ViewResolver)得到最终将逻辑视图解析为视图对象(View),最终的视图可以是jsp、html,也可能是Excel等,转换成对应的View对象后渲染给用户,即返回浏览器,在这个渲染过程中,发挥作用的就是ViewResolver和View两个接口

对于最终采取哪种视图对象对模型数据进行渲染,处理器并不关心,处理器工作重点在生产模型数据上,从而实现mvc的充分解耦,视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户端,主要就是完成转发或重定向操作

(1)ViewResolver接口

//ViewResolver接口
public interface ViewResolver {
    /**
     * 只有这一个方法,用于把逻辑视图名称解析为真正视图View
     /
   @Nullable
   View resolveViewName(String viewName, Locale locale) throws Exception;
}

ViewResolver接口继承链中的实现类:

1)UrlBasedViewResolver(URL资源视图):

主要就是提供的一种拼接URL的方式来解析视图,他可以指定前缀和后缀,然后拼接到返回的逻辑视图名称,就是指定的视图URL了

2)InternalResourceViewResolver(UrlBasedViewResolver子类):

将视图名解析为一个URL文件,一般使用该解析器将视图名映射为一个保存在WEB-INF下的程序文件如jsp,jsp是常见的视图技术,可以使用InternalResourceViewResolver作为视图解析器

@Controller
public class LoginController {
    @RequestMapping(value = "login")
    public String login() {
        return "login";
    }
}

//在springmvc中没有配置视图解析器的情况下,访问/login会报错,错误的大概意思就是没有正确设置转发(或包含)到请求调度程序路径
//意思就是把逻辑视图解析后的URL路径还是/login,因为默认情况下该视图解析器解析视图是没有配置前缀和后缀的

//InternalResourceViewResolver中有一个静态方法 prepareForRendering判断url路径是否匹配
protected String prepareForRendering(HttpServletRequest request, HttpServletResponse response)

(2)View接口

View接口有很多实现类,接口中有一个重要方法render(),用于渲染给定模型的视图

View接口继承链中的实现类

InternalResourceView视图:

将jsp或者其他资源封装成一个视图,是InternalResourceViewResolver默认使用的视图实现类

文档视图:

AbstractExcelView: Excel文档视图的抽象类,该视图类基于POI构造excel文档

JSON视图:

MappingJacksonJsonView:将数据模型通过Jackson开源框架的ObjectMapper以JSON方式输出

(3)请求转发与视图解析器

请求转发: 返回逻辑视图名包含forward:前缀,解析后是InternalResourceView

重定向: 返回逻辑视图名包含redirect:前缀,解析后是RedirectView

默认的: 返回视图名不带任何前缀,默认视图解析器为InternalResourceViewResolver,解析后是InternalResourceView

重定向与请求转发,解析后的视图类型不一样

在AbstractCachingViewResolver(ViewResolver接口的实现类)中的resolveViewName()方法中调用createView()

之后进入loadView()(loadView()这是个抽象方法,在UrlBasedViewResolver中实现),

再进入buildView()(在URLBasedViewResolver类中,在InternalResourceViewResolver中重写了此方法)返回一个view

view视图在返回之前就根据请求转发和重定向的不同固定了视图类型

@Override
protected View createView(String viewName, Locale locale) throws Exception {
 
   /**
	* 判断一下当前视图解析器能不能处理给定视图,如果不能处理的话,就返回null,交给下一个视图解析器处理
	*/
   if (!canHandle(viewName, locale)) {
      return null;
   }
 
   /**
	* 检查视图名是否以 "redirect:" 开头
	*/
   if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
       /**
		* 去掉前缀,得到后面的重定向地址
		*/
      String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
       /**
		* 创建一个重定向视图
		*/
      RedirectView view = new RedirectView(redirectUrl,
            isRedirectContextRelative(), isRedirectHttp10Compatible());
      String[] hosts = getRedirectHosts();
      if (hosts != null) {
         view.setHosts(hosts);
      }
      return applyLifecycleMethods(REDIRECT_URL_PREFIX, view);
   }
 
    /**
	 * 检查视图名是否以 "forward:" 开头
	 */
   if (viewName.startsWith(FORWARD_URL_PREFIX)) {
      String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
        /**
	 	 * 创建请求转发InternalResourceView视图
	 	 */
      InternalResourceView view = new InternalResourceView(forwardUrl);
      return applyLifecycleMethods(FORWARD_URL_PREFIX, view);
   }
 
    /**
	 * 如果视图名不以"redirect:"或"forward:"为前缀,则通过父类中的实现创建视图
	 */
   return super.createView(viewName, locale);
}

七、SpringMVC数据响应

(1)页面跳转

1、返回字符串形式

@RequestMapping("/quick")
 public String quickMethod(){ 
 	return "index";
}

因为视图解析器配置如下:
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />

所以转发和重定向的地址不一样:
转发:forward:/WEB-INF/views/index.jsp
重定向:redirect:/index.jsp

2、返回ModelAndView对象

@RequestMapping("/quick2")
public ModelAndView quickMethod2(){
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("redirect:index.jsp");
    return modelAndView;
}
@RequestMapping("/quick3")
public ModelAndView quickMethod3(){
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("forward:/WEB-INF/views/index.jsp");
    return modelAndView;
}

3、向request域存储数据

//通过注入的request对象setAttribute()方法设置
@RequestMapping("/quick")
public String quickMethod(HttpServletRequest request){
    request.setAttribute("name","zhangsan");
    return "index";
}

//通过ModelAndView的addObject()方法设置
@RequestMapping("/quick3")
public ModelAndView quickMethod3(){
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("forward:/WEB-INF/views/index.jsp");
    modelAndView.addObject("name","lisi");
    return modelAndView;
}
(2)SpringMVC回写数据——直接返回字符串

1、通过注入的response对象,使用response.getWriter().print(“hello world”)

@RequestMapping("/quick4")
public void quickMethod4(HttpServletResponse response) throws IOException {
	response.getWriter().print("hello world");
}

2、直接返回字符串,通过@ResponseBody注解,方法返回的字符串在响应体中返回

@RequestMapping("/quick5")
@ResponseBody
public String quickMethod5() throws IOException {
	return "hello springMVC!!!";
}

3、手动拼接json字符串和json转换工具

//手动拼接
@RequestMapping("/quick6")
@ResponseBody
public String quickMethod6() throws IOException {
	return "{\"name\":\"zhangsan\",\"age\":18}";
}



//使用json转换工具(转换工具不止一种,但是如果使用其他工具,使用注解驱动就无法自动返回json格式)
<!--jackson-->
<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-databind</artifactId>
    <version>2.9.0</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.0</version>
</dependency>

@RequestMapping("/quick7")
@ResponseBody
public String quickMethod7() throws IOException {
    User user = new User();
    user.setUsername("zhangsan");
    user.setAge(18);
    ObjectMapper objectMapper = new ObjectMapper();
    String s = objectMapper.writeValueAsString(user);
    return s;
}
(3)SpringMVC回写数据——返回对象或集合
<!--mvc的注解驱动-->
 <mvc:annotation-driven/>

在SpringMVC的各个组件中,处理器映射器、处理器适配器、视图解析器称为SpringMVC的三大组件。 使用**<mvc:annotation-driven/>**自动加载 RequestMappingHandlerMapping(处理映射器)和 RequestMappingHandlerAdapter(处 理 适 配 器 ),可用在Spring-xml.xml配置文件中使用mvc注解驱动代替处理器和适配器的配置。同时使用默认底层就会集成jackson进行对象或集合的json格式字符串的转换。

八、SpringMVC获得请求数据

(1)获取基本类型参数

方法的参数名称与请求参数的name一致,参数值会自动映射匹配

//http://localhost:8080/quick9?username=zhangsan&age=12
@RequestMapping("/quick9")
@ResponseBody
public void quickMethod9(String username,int age) throws IOException {
    System.out.println(username);
    System.out.println(age);
}
(2)获得POJO类型参数

方法的POJO参数的属性名与请求参数的name一致,参数值会自动映射匹配

//http://localhost:8080/quick11?username=zhangsan&age=12
public class User {
    private String username;
    private int age;
    getter/setter…
}
@RequestMapping("/quick10")
@ResponseBody
public void quickMethod10(User user) throws IOException {
	System.out.println(user);
}
(3)获得数组类型参数

方法中数组名称与请求参数name一致,参数会自动映射匹配

//http://localhost:8080/quic11?strs=111&strs=222&str=333
@RequestMapping("/quick11")
@ResponseBody
public void quickMethod11(String[] strs) throws IOException {
	 System.out.println(Arrays.asList(strs));
}
(4)获得集合类型参数

获得集合参数时,要将集合参数包装到了POJO中才可以

public class VO {
    private List<User> userList;

    @Override
    public String toString() {
        return "VO{" +
                "userList=" + userList +
                '}';
    }

    public List<User> getUserList() {
        return userList;
    }

    public void setUserList(List<User> userList) {
        this.userList = userList;
    }
}
<form action="${pageContext.request.contextPath}/user/quick14" method="post">
    <%--      表明第几个User对象--%>
    <input type="text" name="userList[0].username"><br>
    <input type="text" name="userList[0].age"><br>
    <input type="text" name="userList[1].username"><br>
    <input type="text" name="userList[1].age"><br>
    <input type="submit" value="提交">
</form>
@RequestMapping(value="/quick14")
@ResponseBody
public void save14(VO vo) throws IOException {
	System.out.println(vo);
}

使用ajax提交,指定contentType为json,参数位置使用R@equestBody可以直接接收集合数据

<script>
    //模拟数据
    var userList = new Array();
        userList.push({username: "zhangsan",age: "20"});
        userList.push({username: "lisi",age: "20"});
        $.ajax({
        type: "POST",
            url: "/itheima_springmvc1/quick13",
            data: JSON.stringify(userList),
            contentType : 'application/json;charset=utf-8'
        });
</script>
@RequestMapping("/quick13")
@ResponseBody
public void quickMethod13(@RequestBody List<User> userList) throws 
IOException {
	System.out.println(userList);
}

SpringMVC的前端控制器DispatcherServlet的url-pattern配置是/,代表所有资源进行过滤,通过以下两种方式进行放行:

  • 在springp-mvc.xml配置文件指定放行资源

    <mvc:resources mapping=“/js/**” location=“/js/”/>

  • 使用<mvc:default-servlet-handler>标签

(5)请求数据乱码问题
<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>
(6)参数绑定注解@requestParm

当请求参数名称与业务方法参数名称不一致时,就需要通过@RequestParm注解显示的绑定

  • value:请求参数名称
  • required:指定请求参数是否必须包括,默认是true,提交时如果没有此参数则报错
  • defaultValue:当没有指定参数时,则使用指定的默认值赋值
<form action="${pageContext.request.contextPath}/quick14" method="post">
    <input type="text" name="name"><br>
    <input type="submit" value="提交"><br>
</form>
@RequestMapping("/quick14")
@ResponseBody
public void quickMethod14(@RequestParam("name") String username) throws 
IOException {
	System.out.println(username);
}

@RequestMapping("/quick14")
@ResponseBody
public void quickMethod14(@RequestParam(value="name",required =  false,defaultValue = "itcast") String username) throws IOException {
	System.out.println(username);
}
(7)获得Restful风格的参数
  • /user/1 GET : 得到id = 1 的 user
  • /user/1 DELETE: 删除 id = 1 的user
  • /user/1 PUT: 更新id = 1 的user
  • /user POST: 新增user
功能传统方式restful风格
查询http://127.0.0.1/item/selectUser?id=1GET http://127.0.0.1/item/selectUser/1
新增http://127.0.0.1/item/addUserPOST http://127.0.0.1/item/addUser
更新http://127.0.0.1/item/updateUserPUT http://127.0.0.1/item/updateUser
删除http://127.0.0.1/item/deleteUser?id=1DELETE http://127.0.0.1/item/deleteUser/1
@RequestMapping("/quick19/{name}")
@ResponseBody
public void quickMethod19(@PathVariable(value = "name",required = true) String username){
	System.out.println(username);
}
(8)自定义类型转换器(日器类型转换)

1、现转换器类实现Converter接口

public class DateConverter implements Converter<String,Date>{
    @Override
    public Date convert(String source) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date date = format.parse(source);
            return date;
        } catch (ParseException e) {
        	e.printStackTrace();
        }
        return null;
    }
}

2、在配置文件中声明转换器

<bean id="converterService"  
    class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <list>
        	<bean class="com.itheima.converter.DateConverter"/>
        </list>
    </property>
</bean>

3、在<annotation-driven>中引用转换器

<mvc:annotation-driven conversion-service="converterService"/>
(9)获得Servlet相关API

SpringMVC支持使用原始ServletAPI对象作为控制器方法的参数进行注入,常用的对象如

  • HttpServletRequest

  • HttpServletResponse

  • HttpSession

@RequestMapping("/quick16")
@ResponseBody
public void quickMethod16(HttpServletRequest request,HttpServletResponse response, HttpSession session){
    System.out.println(request);
    System.out.println(response);
    System.out.println(session);
}
(10)获得请求头

1、@RequestHeader

  • value:请求头的名称
  • required:是否携带此请求头
@RequestMapping(value="/quick20")
@ResponseBody
public void save20(@RequestHeader(value = "User-Agent",required = false) String headValue) throws IOException {
	System.out.println(headValue);
}

2、@CookieValue

  • value:指定cookie的名称
  • required:是否必须携带此cookie
@RequestMapping("/quick18")
@ResponseBody
public void quickMethod18(@CookieValue(value = "JSESSIONID",required = false) String jsessionid){
	System.out.println(jsessionid);
}

(11)文件上传

1、文件上传三要素

  • 表单项type=“file”
  • 表单的提交方式是post
  • 表单的enctype属性是多部分表单形式,及enctype=“multipart/form-data”
<form action="${pageContext.request.contextPath}/quick20" method="post" 
enctype="multipart/form-data">
    名称:<input type="text" name="name"><br>
    文件:<input type="file" name="file"><br>
     <input type="submit" value="提交"><br>
</form>

2、文件上传原理

  • 当form表单修改为多部分表单时,request.getParameter()将失效
  • enctype="application/x-www-form-urlencoded"时,form表单的正文内容格式是: key=value&key=value&key=value
  • 当form表单的enctype取值为Mutilpart/form-data时,请求正文内容就变成多部分形式

多部分表单是指一个表单可以分为多个部分填写。用户可以在每个部分填写好数据后,逐步填写完整个表单。在表单的每一步提交时,都只提交当前步骤的数据。

3、单文件上传

导入fileupload和io坐标

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.2.2</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

配置解析器

<bean id="multipartResolver" 
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--上传文件总大小-->
    <property name="maxUploadSize" value="5242800"/>
    <!--上传单个文件的大小-->
    <property name="maxUploadSizePerFile" value="5242800"/>
    <!--上传文件的编码类型-->
    <property name="defaultEncoding" value="UTF-8"/>
</bean>

编写上传代码

@RequestMapping("/quick20")
@ResponseBody
public void quickMethod20(String name,MultipartFile uploadFile) throws IOException {
    //获得文件名称
    String originalFilename = uploadFile.getOriginalFilename();
    //保存文件
    uploadFile.transferTo(new File("C:\\upload\\"+originalFilename));
}

4、多文件上传实现

页面修改

<h1>多文件上传测试</h1>
<form action="${pageContext.request.contextPath}/quick21" method="post" 
enctype="multipart/form-data">
    名称:<input type="text" name="name"><br>
    文件1:<input type="file" name="uploadFiles"><br>
    文件2:<input type="file" name="uploadFiles"><br>
    文件3:<input type="file" name="uploadFiles"><br>
	<input type="submit" value="提交"><br>
</form>

方法参数MutipartFile类型修改为MultipartFile[]

@RequestMapping("/quick21")
@ResponseBody
public void quickMethod21(String name,MultipartFile[] uploadFiles) throws IOException {
	for (MultipartFile uploadFile : uploadFiles){
        String originalFilename = uploadFile.getOriginalFilename();
        uploadFile.transferTo(new File("C:\\upload\\"+originalFilename));
    }
}

九、SpringMVC拦截器

(1)概述

1、Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。拦截器也是AOP思想的具体实现。

2、拦截器和过滤器区别

区别过滤器(Filter)拦截器(Interceptor)
使用范围servlet的一部分属于SpringMVC框架
拦截范围在url-pattern中配置了/*之后,可以对所有要访问的资源拦截<mvc:mappingpath=""/>中配置了/**之后,也可以对所有资源进行拦截,但是可以通过<mvc:exclude-mapping path=“”/>标签排除不需要拦截的资源

(2)拦截器实现

1、创建拦截器类实现HandleInterceptor接口

public class MyHandlerInterceptor1 implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse 
        response, Object handler) {
        System.out.println("preHandle running...");
        return true;
    }
    public void postHandle(HttpServletRequest request, HttpServletResponse 
        response, Object handler, ModelAndView modelAndView) {
        System.out.println("postHandle running...");
    }
    public void afterCompletion(HttpServletRequest request, HttpServletResponse 
        response, Object handler, Exception ex) {
        System.out.println("afterCompletion running...");
    }
}

2、配置拦截器

<--配置拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
    	<mvc:mapping path="/**"/>
    	<bean class="com.itheima.interceptor.MyHandlerInterceptor1"/>
    </mvc:interceptor>
</mvc:interceptors>

3、测试

@RequestMapping("/quick23")
@ResponseBody
public ModelAndView quickMethod23() throws IOException, ParseException {
    System.out.println("目标方法执行....");
    ModelAndView modelAndView= new ModelAndView();
    modelAndView.addObject("name","itcast");
    modelAndView.setViewName("index");
    return modelAndView;
}

(3)拦截器方法说明

方法名说明
preHandle方法将请求处理之前进行调用,该方法的返回值是布尔值Boolean类型的, 当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会 再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle方法
postHandle()该方法是在当前请求进行处理之后被调用,前提是preHandle方法的返回值为 true 时才能被调用,且它会在DispatcherServlet进行视图返回渲染之前被调 用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView对象 进行操作
afterCompletion()该方法将在整个请求结束之后,也就是在DispatcherServlet渲染了对应的视图 之后执行,前提是preHandle方法的返回值为true 时才能被调用

十、SpringMVC异常处理机制

(1)异常处理思路

系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后 者主要通过规范代码开发、测试等手段减少运行时异常的发生。

系统的Dao、Service、Controller出现都通过throws Exception向上抛出(Dao交给Service,Service交给Contoller,Controller交给前端控制器),最后由SpringMVC前端控制器交由异常处理器HandlerExceptionResovler进行异常处理

(2)简单异常处理器SimpleMappingExceptionResolver

<!--配置简单映射异常处理器-->
<bean 
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="defaultErrorView" value="error"/>   #默认错误视图
    <property name="exceptionMappings">
        <map>  #相应异常与视图的映射配置,特定异常类型对应特定错误视图,key为异常类型,value为错误视图
            <entry key="com.itheima.exception.MyException" value="error"/>
            <entry key="java.lang.ClassCastException" value="error"/>
        </map>
    </property>
</bean>

(3)自定义异常处理步骤(实现Spring的异常处理接口HandlerExceptionResolver)

1、创建异常处理类实现handlerExceptionResolver

public class MyExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, 
    HttpServletResponse response, Object handler, Exception ex) {
        //处理异常的代码实现
        //创建ModelAndView对象
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("exceptionPage");
        return modelAndView;
    }
}

2、配置异常处理器

<bean id="exceptionResolver" class="com.itheima.exception.MyExceptionResolver"/>

3、编写异常页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
	<title>Title</title>
</head>
<body>
	这是一个最终异常的显示页面
</body>
</html>

4、测试异常跳转

@RequestMapping("/quick22")
@ResponseBody
public void quickMethod22() throws IOException, ParseException {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
    simpleDateFormat.parse("abcde");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值