Spring框架学习笔记(3)——SpringMVC框架

2019-10-02 00:00:00 spring 框架 学习笔记

SpringMVC框架是基于Spring框架,可以让我们更为方便的进行Web的开发,实现前后端分离

思路和原理

我们之前仿照SpringMVC定义了一个自定义MVC框架,两者的思路其实都是一样的。

建议结合两篇文章进行学习

JSP学习笔记(6)—— 自定义MVC框架

首先,提供一个前置拦截器(DispatchServlet),拦截url请求,之后,根据url请求,跳转到Controller层,执行操作,之后再返回数据

入门

我的demo是使用了maven框架

1.创建maven项目

按照下图进行配置
《Spring框架学习笔记(3)——SpringMVC框架》

2.添加依赖

修改pom.xml,添加依赖

刚开始的时候,使用的是最新版本(5.x.x),然后发现有个奇怪的错误,折腾了许久找不到方法,于是便用了4.x.x版本的,果然没有出现问题了,果然是新版本都不好用。。

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.11</version>
  <scope>test</scope>
</dependency>
<!--日志-->

<dependency>
  <groupId>commons-logging</groupId>
  <artifactId>commons-logging</artifactId>
  <version>RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>4.3.9.release</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context-support</artifactId>
  <version>4.3.9.release</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>4.3.9.release</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>4.3.9.release</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-beans</artifactId>
  <version>4.3.9.release</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-expression</artifactId>
  <version>4.3.9.release</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-web</artifactId>
  <version>4.3.9.release</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>4.3.9.release</version>
</dependency>
<!--AOP-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>4.3.9.release</version>
</dependency>

<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>RELEASE</version>
</dependency>
<dependency>
  <groupId>aopalliance</groupId>
  <artifactId>aopalliance</artifactId>
  <version>RELEASE</version>
</dependency>
<!-- springmvc依赖的json库(如果使用@responsebody注解返回json数据) -->
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.7.3</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.7.3</version>
</dependency>
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
  <version>3.3.2</version>
</dependency>
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>4.0.1</version>
</dependency>
<!-- jstl 1.2.5 version libarary -->
<dependency>
  <groupId>org.apache.taglibs</groupId>
  <artifactId>taglibs-standard-spec</artifactId>
  <version>1.2.5</version>
</dependency>
<dependency>
  <groupId>org.apache.taglibs</groupId>
  <artifactId>taglibs-standard-impl</artifactId>
  <version>1.2.5</version>
</dependency>
<!-- oracle driver -->
<dependency>
  <groupId>com.github.noraui</groupId>
  <artifactId>ojdbc8</artifactId>
  <version>12.2.0.1</version>
</dependency>
<!-- mybatis orm框架 -->
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.5.2</version>
</dependency>
<!-- spring整合mybatis -->
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>2.0.2</version>
</dependency>
<!-- 文件上传与下载 -->
<!--
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>
-->

3.项目结构优化

由于是根据maven模板新建的项目,所以项目结构还需要添加一些文件夹

在main文件夹下新建java文件夹

《Spring框架学习笔记(3)——SpringMVC框架》

把java文件夹设置为source directory

《Spring框架学习笔记(3)——SpringMVC框架》

在java文件夹下新建自己的包名,然后新建一个controller文件夹和model文件夹,顺便也新建一个resources的文件夹,和上面同样的步骤,设置为resources directory

《Spring框架学习笔记(3)——SpringMVC框架》

除此之外,还需要在webapp文件夹下新建一个views文件夹

《Spring框架学习笔记(3)——SpringMVC框架》

4.设置Tomcat配置

我这里是设置好了,没有设置的话,是没有下拉菜单的,但是有个add configuration的选项

《Spring框架学习笔记(3)——SpringMVC框架》

选择tomcat的设置,选择local,如果没有Tomcat的选项,可以点击选项最下面的show more

《Spring框架学习笔记(3)——SpringMVC框架》

点击之后,添加构造物

《Spring框架学习笔记(3)——SpringMVC框架》

选择那个exploded的选项

《Spring框架学习笔记(3)——SpringMVC框架》

设置url

《Spring框架学习笔记(3)——SpringMVC框架》

之后开始运行Web程序,就可以通过访问http://localhost:8080/springmvcdemo来访问Web项目的首页

5.新建springmvc配置文件

springmvc配置文件和之前的spring文件一样,都是进行相关的bean的配置,这里由于是资源文件,所以按照规则我们放入resources文件夹中

springmvc-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 对web包中的所有类进行扫描,以完成Bean创建和自动依赖注入的功能-->
    <!-- 把标记了controller和requestmapping注解的类和方法进行保存,之后通过反射调用 -->
    <context:component-scan base-package="com.wan.controller"/>
    
    <!--支持spring3.0+ 新的mvc注解,不加有些注解功能不行,如json转换的@ResponseBody
         <context:annotation-config/>
          将隐式地向 Spring 容器注册
        1. AutowiredAnnotationBeanPostProcessor     解决数据或组件自动装配
        2. CommonAnnotationBeanPostProcessor        解决兼容JSR250规范的注解:@Resource,@PostConstruct,...
        3. PersistenceAnnotationBeanPostProcessor   解决持久化注解处理
        4. RequiredAnnotationBeanPostProcessor
            这 4 个 BeanPostProcessor。

     enable-matrix-variables="true": 开启矩阵变量获取数据的特性
-->
    <mvc:annotation-driven enable-matrix-variables="true">
        <mvc:async-support default-timeout="10"/><!--子元素可指定异步拦截器-->
    </mvc:annotation-driven>
    
    <!-- 配置*.js,*.css,*.jpg,*.html等的请不由DispatcherServlet处理,而直接交tomcat服务的默认Servlet来处理,
        不同的服务器其默认Servlet的名字是不同,但tomcat默认Servlet的名字叫“default”
    -->
    <mvc:default-servlet-handler/>

    <!--对模型视图名称的解析,即在模型视图名称添加前后缀
        UserController.login(){
            return "success"; //spring mvc 解析为一个对应的jsp(视图)/views/success.jsp
        }
    -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/views/" p:suffix=".jsp">
        <!-- /views/[login].jsp -->
        <!-- 与p:prefix, p:suffix 等价
        <property name="prefix" value="/views/" />
        <property name="suffix" value=".jsp" />
        -->
        <!-- 如果使用jstl的话,配置下面的属性 -->
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
    </bean>
</beans>

配置中有个bean类,是配置视图解析器(也就是最后的那个bean标签),我们使用的是InternalResourceViewResolver

此解析器会把请求处理类(controller类)处理方法的返回值按照“前缀+方法返回值+后缀”的格式进行加工,并把加工后的返回值作为路径进行跳转

除此之外,还有其他的解析器,下面会进行补充说明

6.配置web.xml文件

由于我们使用的maven的模板创建的web项目,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">
    <display-name>SpringMVC Demo</display-name>

    <!-- springmvc 核心控制器,将springMVC整合到项目里-->
    <servlet>
        <servlet-name>springmvc-DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!-- 配置spring mvc的组件:扫描controller, view resovle -->
            <param-value>classpath:springmvc-config.xml</param-value>
        </init-param>
        <!-- 服务器启动时加载顺序 -->
        <load-on-startup>1</load-on-startup>
        <!-- 异步请求处理支持 -->
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc-DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

7.测试

我们用一个简单的例子去了解springmvc的使用方式

我们编写一个controller类,用来模拟实现登录操作,登录成功,跳转到登录成功的页面success.jsp

UserController.java

package com.wan.controller;

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

/**
 * @author StarsOne
 * @date Create in  2019/9/28 0028 14:27
 * @description
 */
@Controller
public class UserController {
    @RequestMapping("/user/login")
    public String login() {
        //这里的返回,之后会加上前缀和后缀
        //相当于页面跳转到 views/success.jsp 页面
        return "success";
    }
}

success.jsp中,只有一个简单的“登录成功”文字

index.jsp中,有个链接,请求url为user/login

<a href="user/login">登录</a>

之后就是可以跳转到了页面

《Spring框架学习笔记(3)——SpringMVC框架》

PS:上面方法返回了一个success,,会被自动加入前缀和后缀,注意,这里是进行的请求转发

除此之外,我们还可以加上forwardredirect前缀来进行请求转发或重定向

但是,如果使用这两种前缀,之后视图解析器就不会自动添加前缀和后缀了。所以,我们得指定具体跳转的url地址。

@RequestMapping("/user/login")
public String login() {
    //请求转发
    return "forward:/views/success.jsp";
}

@RequestMapping("/user/login")
public String login() {
    //重定向
    return "redirect:/views/success.jsp";
}

RequestMapping注解

高级使用

springmvc框架中的RequestMapping注解不像我们之前自定义MVC框架的注解那样简单,它的还可以标注一个类

例如:

package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author StarsOne
 * @date Create in  2019/9/28 0028 14:27
 * @description
 */
@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public String login() {
        //这里的返回,相当于页面跳转到 views/success.jsp 页面
        return "success";
    }
}

我们链接上的url请求就是/user/login,而不能使用login

属性说明及使用

属性说明
value指定请求的实际url地址,是默认属性,如@RequestMapping(“/login”) 相当于@RequestMapping(value=”/login”
method指定请求的方法,post或get
params规定请求中的参数必须满足一定的条件
header规定请求中的请求头(header)必须满足一定的条件

1.method

package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author StarsOne
 * @date Create in  2019/9/28 0028 14:27
 * @description
 */
@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login",method="RequestMethod.POST")
    public String login() {
        //这里的返回,相当于页面跳转到 views/success.jsp 页面
        return "success";
    }
}

之后如果请求不是post方式,就会出现405错误

2.params

使用此属性可以对请求的参数进行约束

例子:

package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author StarsOne
 * @date Create in  2019/9/28 0028 14:27
 * @description
 */
@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login",params={"name","age!=23"})
    public String login() {
        //这里的返回,相当于页面跳转到 views/success.jsp 页面
        return "success";
    }
}

上面的例子约束的url的请求参数必须要包含有name和age,且age不能等于23,如果不满足条件,就会发生404错误

如:

<!-- 满足条件的url请求 -->
<a href="user/login?name=zhang&age=21">登录</a>

params中可以接收以下表达式

表达式说明
paramNameurl请求必须包含paramName此参数名
!paramNameurl请求不能包含paramName此参数名
paramName!=xxurl请求必须包含paramName此参数名,且此参数数值不等于xx

header比较少用,这里就不补充了

获得请求url参数值

获得url请求的参数值,我们可以使用RequestParam注解

使用此注解,可以把url请求参数的数值赋值给方法参数

下面是@RequestParam注解的常用属性说明

属性说明
value请求携带参数的参数名
required标识请求url参数是必须存在某个具体的参数,true(默认):必须存在,不存在则会发生异常;false:不存在
defaultValue给方法参数赋一个默认值,如果请求url不存在此参数,则使用默认值
package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author StarsOne
 * @date Create in  2019/9/28 0028 14:27
 * @description
 */
@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public String login(@RequestParam(value="username") String name) {
        //这里的返回,相当于页面跳转到 views/success.jsp 页面
        return "success";
    }
}

请求url为user/login?username=zhang,之后便会把此请求参数赋值给方法参数name

和我们自定义mvc框架一样,springmvc框架中,我们也可以直接使用实体类、session、request、response作为方法的参数

@RequestMapping("/user/login")
public login(Student student){
    ...
}

@RequestMapping("/user/login")
public login(HttpServletRequest request,HttpServletResponse response,HttpSession session){
    ...
}

RequestParam类似的还有这两个RequestHeaderCookieValue

这两个注解我现在没怎么用到,暂时了解一下,不作补充

  • RequestHeader注解,主要是用来获得请求头的数据
  • CookieValee注解,主要是用来获得一个cookieValue

返回json数据

我们使用@ResponseBody,方法返回实体类或者集合的时候,springmvc就会自动帮我们转为json数据

使用之前需要导入这两个jar,jackson-core.jarjackson-databind.jar,之前的依赖已经包含下面这两个jar了

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

UserController.java

package com.wan.controller;


import com.wan.model.Teacher;

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

/**
 * @author StarsOne
 * @date Create in  2019/9/28 0028 14:27
 * @description
 */
@Controller
@RequestMapping("/user")
public class UserController {
    @ResponseBody
    @RequestMapping("/login")
    public Teacher login() {
        return new Teacher("001", "张三");
    }
}

之后在jsp页面中使用ajax异步请求

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<html>
<head>
    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
    <script type='text/javascript'>

        function getData() {
            $.getJSON("user/login", function(json){
                console.log(json);
            });
        }
    </script>
</head>
<body>
<button onclick="getData()">登录</button>
</body>
</html>

就可以在控制台看到打印出来的json数据

《Spring框架学习笔记(3)——SpringMVC框架》

处理Model数据

SpringMVC中,M其实就是代表着Model(模型),也就是相当于数据

假设我们要从数据查询数据:先从页面(View)发送url请求,然后控制器(Controller)通过Service/Dao从数据库中获得了数据(Model),并把数据进行处理,使得数据能够传回页面(View)并显示。

如果是异步请求的话,我们可以返回一个json数据到页面,如果不是的话,我们就得把数据存放在request或session的作用域里,之后由页面(View)从作用域中取出数据并显示

SpringMVC提供了四种方法来处理那些需要从作用域中取出数据显示的视图

  • ModelAndView
  • Map、ModelMap和Model
  • @SessionAttributes
  • @ModelAttribute

1.ModelAndView

此类一般用来作方法的返回值来实现返回一个带数据的页面(View)

UserController.java

package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author StarsOne
 * @date Create in  2019/9/28 0028 14:27
 * @description
 */
@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public ModelAndView login() {
        String view = "success";
        ModelAndView mav = new ModelAndView(view);
        Teacher teacher = new Teacher("001","张三");
        //相当于request.addAttribute("teacher",teacher)
        mav.addObject("teacher",teacher);
        return mav;
    }
}

success.jsp中取出数据并显示

<body>
${requestScope.student.tno}
</body>

上面的例子和之前一样,还是会加上前缀和后缀,得到views/success.jsp

2.Map、ModelMap和Model

Map、ModelMap和Model一般使用作为方法的参数,之后,通过put方法往里面存入数据

package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author StarsOne
 * @date Create in  2019/9/28 0028 14:27
 * @description
 */
@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public String login(Map<String,Object> map) {
        String view = "success";
        Teacher teacher = new Teacher("001","张三");
        //相当于request.addAttribute("teacher",teacher)
        map.put("teacher",teacher);
        return "success";
    }
}

ModelMap和Map的使用方法一样

还可以使用Model

@RequestMapping("/login")
    public String login(Model model) {
        String view = "success";
        Teacher teacher = new Teacher("001","张三");
        //相当于request.addAttribute("teacher",teacher)
        model.addAttribute("teacher",teacher);
        return "success";
    }

Model类还可以使用添加一个map数据,addAllAttribute(Map<String,?> map)

3.@SessionAttributes

前面的两个方法,都是放入到request的作用域里,如果我们想放入session作用域,可以使用@SessionAttributes注解,一般标注在类上

@SessionAttributes可以将指定的对象加入到session范围,也可以将某个类型的对象加入到session中

下面的例子,指定了key为teacher的对象,添加到了session作用域

package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author StarsOne
 * @date Create in  2019/9/28 0028 14:27
 * @description
 */
@Controller
@RequestMapping("/user")
@SessionAttributes(value="teacher")
public class UserController {
    @RequestMapping("/login")
    public String login(Map<String,Object> map) {
        String view = "success";
        Teacher teacher = new Teacher("001","张三");
        //在添加到request作用域,同时也添加了session作用域
        map.put("teacher",teacher);
        return "success";
    }
}

把Teacher类型的对象添加到session作用域中

package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author StarsOne
 * @date Create in  2019/9/28 0028 14:27
 * @description
 */
@Controller
@RequestMapping("/user")
@SessionAttributes(type=Teacher.class)
public class UserController {
    @RequestMapping("/login")
    public String login(Map<String,Object> map) {
        String view = "success";
        Teacher teacher = new Teacher("001","张三");
        //在添加到request作用域,同时也添加了session作用域
        map.put("teacher",teacher);
        return "success";
    }
}

4.@ModelAttribute

使用情况:
我们需要对数据进行更新,但我们只能更新数据的某个属性。

我们点击编辑之后,只有一个输入框让我们输入,用来更改那个属性,我们输入更改后的属性值,更新的时候会发现,controller里面的数据,传入的对象除了更改的那个属性值,其他的属性值都是为null,我们不希望这种情况,所以,使用此注解

此注解用来修饰controller里的某个方法,然后就会在执行controller中@RequestMapping的方法之前执行,把传入的对象中的数据更新,之后执行修改操作的话,只会把对象需要修改的属性值更改,其他的属性值不变(不为null了)

我个人觉得这样好像比较麻烦,上面的情况有个更好的解决办法,就是不要使用唯一的输入框,而是使用多个输入框,把不能更改的那几项输入框设置disable,之后提交表单也能成功传入其他的属性值

视图解析器

工作流程

springmvc框架中,请求处理方法(Controller中的方法)执行完成后,最终返回一个ModelAndView 对象。

Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是JSP ,也可能是Excel、JFreeChart 等各种表现形式的视图

对于最终究竟采取何种视图对象对模型数据进行渲染(也就是我们常说的把数据从request等作用域取出来显示到页面上),处理器并不关心,处理器工作重点聚焦在生产模型数据的工作上,从而实现MVC 的充分解耦

对于那些返回String,View 或ModeMap 等类型的处理方法,Spring MVC 也会在内部将它们装配成一个ModelAndView 对象,它包含了逻辑名和模型对象的视图;

如下图:

《Spring框架学习笔记(3)——SpringMVC框架》

View

springmvc中的View其实是个接口,下面是常见的View接口的实现类

视图类型实现类说明
URL视图类型InternalResourceView将JSP或其他资源封装成一个视图。被视图解析器InternalResourceViewResolver默认使用。
URL视图类型JstlViewInternalResourceView的子类。如果JSP中使用了JSTL的国际化标签,就需要使用该视图类
文档视图AbstractExcelViewExcel文档视图的抽象类
文档视图AbstractPdfViewPDF文档视图的抽象类
报表视图ConfigurableJasperReportsView
报表视图JasperReportsHtmlView
报表视图JasperReportsPdfView
报表视图JasperReportsXlsView
JSON视图MappingJackson2JsonView将数据通过Jackson框架的ObjectMapper对象,以JSON方式输出

ViewResolver以及子类

ViewResolver和View一样,也是个接口

视图解析器类型类名说明
解析为映射文件UrlBasedViewResolver它简单实现了ViewResolver接口, 不用任何映射就能通过逻辑视图名称访问资源
解析为映射文件InternalResourceViewResolver将逻辑视图名解析为一个路径
解析为beanBeanNameViewResolver将逻辑视图名解析为bean的name属性,从而根据name属性去找对应的bean
解析为beanResourceBundleResolver和BeanNameViewResolver一样,只不过定义的view-bean都在一个properties文件中,用这个类进行加载这个properties文件
解析为beanXmlViewResolver和ResourceBundleResolver一样,只不过定义的view-bean在一个xml文件中,用这个类来加载xml文件
解析为模版文件VelocityViewResolver对Velocity模版引擎的支持
解析为模版文件FreeMarkerViewResolver对FreeMarker模版引擎的支持

这里,我只介绍以下前两种,也就是我们用过的类型。更多请参考我们下面给出的链接

AbstractCachingViewResolver,这个类为抽象类,实现了ViewResolver接口,抽象类只能被继承,无法创建实例。

UrlBasedViewResolver就是继承于AbstractCachingViewResolver这个类,从而扩展了功能。

AbstractCachingViewResolver介绍:

这种视图解析器会把它曾经解析过的视图保存起来,然后每次要解析视图的时候先从缓存里面找。

如果找到了对应的视图就直接返回,如果没有就创建一个新的视图对象,然后把它放到一个用于缓存的map中,接着再把新建的视图返回。

使用这种视图缓存的方式可以把解析视图的性能问题降到最低。

UrlBasedViewResolver介绍:

继承了AbstractCachingViewResolver,主要就是提供的一种拼接URL的方式来解析视图,它可以让我们通过prefix属性指定一个指定的前缀,通过suffix属性指定一个指定的后缀,然后把返回的逻辑视图名称加上指定的前缀和后缀就是指定的视图URL了。

InternalResourceViewResolver介绍:

这个类是继承于UrlBasedViewResolver,UrlBasedViewResolver具有的功能它都有,而且还有它自己的特性。从字面翻译,InternalResourceViewResolver就是内部资源解析器。

InternalResourceViewResolver会把返回的视图名称都解析为InternalResourceView对象,InternalResourceView会把Controller处理器方法返回的模型属性都存放到对应的request属性中,然后通过RequestDispatcher在服务器端把请求forword重定向到目标URL。

参考链接:Spring MVC-从零开始-view-ViewResolver

静态资源访问

情景

如果我们想要通过一个url去访问我们项目中的一个图片、js文件、视频等静态资源,会发现报404错误

原因是我们定义一个前置Servlet,处理了所有的url请求,但是,由于未能找到RequestMapping注解上的相匹配的url,所以就会出现404错误

解决方法

在springmvc配置文件中添<mvc:default-servlet-handler/><mvc:annotation-driven></mvc:annotation-driven>即可解决问题

之前给出的springmvc配置文件中,其实已经添加了这两个标签,在这里稍微介绍一下作用

<mvc:default-servlet-handler/>作用:在SpringMVC上下文中,定义了一个DefaultServletHttpRequestHandler,它会对鄋DispatcherServlet处理的请求进行检查,如果发现某个请求没有对应的@RequestMapping进行处理,就会将该请求交个Web服务器默认的Servlet进行处理,二默认的Servlet就会直接根据url去访问该资源

<mvc:annotation-driven></mvc:annotation-driven>作用:访问静态资源的同时,眼能够正常的访问其他非静态资源

两个标签都要添加

中文乱码方法(补充)

1. 设置页面编码

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>

2.配置过滤器

在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">
    <display-name>SpringMVC Demo</display-name>

    <!-- 中文转码必须加到核心控制器前面 -->
    <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>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/</url-pattern>
    </filter-mapping>
    
    <!-- springmvc 核心控制器,将springMVC整合到项目里-->
    <servlet>
        <servlet-name>springmvc-DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!-- 配置spring mvc的组件:扫描controller, view resovle -->
            <param-value>classpath:springmvc-config.xml</param-value>
        </init-param>
        <!-- 服务器启动时加载顺序 -->
        <load-on-startup>1</load-on-startup>
        <!-- 异步请求处理支持 -->
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc-DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

更多方法,请查看参考链接

参考链接:彻底解决springMVC中文乱码

    原文作者:Stars-one
    原文地址: https://www.cnblogs.com/kexing/p/11615562.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。

相关文章