SpringMVC框架基本使用指南

SpringMVC框架基本使用指南

一  MVC的基本概念

SpringMVC是基于MVC模式设计的。MVC模式将应用的输入,处理,输出分离开来,形成模型层,控制层,视图层。M:代表数据模型,即根据业务逻辑处理的数据以及一些安全,日志模块。V:代表视图,即jsp页面,html页面等表现数据结果的界面。C:代表控制器,接受视图的请求,根据请求选择对应的数据模型进行处理。并将结果返回给对应的视图。

二  MVC的优点

  1. 可以有效的降低模块之间的耦合度,当视图发生改变时,模型层和控制层无需改动。
  2. 可以提高模型的复用性,多个视图可以共用同一套数据模型,无需重写一套模型。
  3. 简单易用。
  4. 方便后期的维护。

三  SpringMVC的工作流程

  1. 用户向DispatcherServlet发送请求。
  2. DispatcherServlet将请求交个HandlerMapping处理。
  3. HandlerMapping根据URL找到对应的Controller,并返回给DispatcherServlet。
  4. DispatcherServlet调用HandlerAdapter进行参数封装,数据格式转换,数据验证等操作,最后调用具体的Controller方法。
  5. Controller方法执行完后,返回ModelAndView对象给HandlerAdapter,HandlerAdapter再返回给DispatcherServlet。
  6. DispatcherServlet将ModelAndView对象交给ViewReslover视图解析器处理。
  7. ViewReslover视图解析器解析成视图,返回给DispatcherServlet。
  8. DispatcherServlet将数据填充到视图中。
  9. DispatcherServlet将渲染后的视图返回给用户。

四  搭建SpringMVC框架

自从Spring3以后,SpringMVC框架就支持xml和java两种配置方法,下面我们先看看如何使用xml配置SpringMVC框架.

1.xml配置SpringMVC框架

第一步:导入Maven依赖

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.7.RELEASE</version>
        </dependency>
       <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.1.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.1.7.RELEASE</version>
         </dependency>
          <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aop</artifactId>
                <version>5.1.7.RELEASE</version>
          </dependency>
           <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>5.1.7.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.1.7.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>1.2</version>
            </dependency>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.9.2</version>
            </dependency>

第二步:配置web.xml文件

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>

  <servlet>
    <servlet-name>SpringMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:config/SpringMVC_Config.xml</param-value>
    </init-param>
  </servlet>

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

</web-app>

servlet配置了DispatcherServlet,初始参数为config/SpringMVC_Config.xml,servlet-mapping里配置这个servlet会拦截所有的请求。如果没有指定初始化参数,SpringMVC默认会去找/WEB-INF/SpringMVC-servlet.xml。


第三步:配置SpringMVC_Config.xml文件

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

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

    <!-- 不拦截静态资源 -->
    <mvc:default-servlet-handler />

    <!--<mvc:resources mapping="images/," location="classpath:images/"></mvc:resources>-->

    <!-- 开启mvc注解支持-->
    <mvc:annotation-driven />

    <!-- 配置视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <!-- 后缀 -->
        <property name="suffix" value=".jsp" />
    </bean>

</beans>

上文中mvc:default-servlet-handler标签和mvc:resources标签都可以实现不拦截静态资源的效果,任选其一。

第四步:测试框架配置
视图 index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<body>
<h2>Hello World!</h2>
${key}
<h1><%  out.print(request.getAttribute("key"));%></h1>
</body>
</html>

控制器

package com.study.Controller;

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

@Controller
public class TestController {

    @RequestMapping("/hello")
    public ModelAndView print()
    {
        ModelAndView model=new ModelAndView();
        model.setViewName("hello");
        model.addObject("key","546565151231");
        return model;
    }

    @RequestMapping("/")
    public ModelAndView first()
    {
        ModelAndView model=new ModelAndView();
        model.setViewName("index");
        model.addObject("key","5465651");
        return model;
    }
}

@Controller注解:标注该类为一个Controller类。
@RequestMapping注解:用于配置方法的请求映射路径。
运行服务器,根据请求url http://localhost:8080 DispatcherServlet最终会调用first方法,first方法创建了一个ModelAndView 对象,调用setViewName方法设置视图名,调用addObject方法添加数据。最终将对象返回给DispatcherServlet。DispatcherServlet此时调用视图解析器解析视图,最终渲染到index视图中。
运行结果:

在这里插入图片描述

2.java配置SpringMVC框架

使用java配置SpringMVC框架,可以完全摆脱web.xml文件。只需添加几个配置类即可
第一步:配置MVC框架配置类

package com.study.Config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

/**
 * Created by forget on 2019/6/9.
 */
@EnableWebMvc
@Configuration
@ComponentScan(basePackages = "com.study.Controller")
public class SpringMVCConfig implements WebMvcConfigurer{

//    @Bean
//    public InternalResourceViewResolver internalResourceViewResolver(){
        配置视图解析器
//        InternalResourceViewResolver internalResourceViewResolver=new InternalResourceViewResolver();
//        internalResourceViewResolver.setPrefix("/WEB-INF/jsp/");
//        internalResourceViewResolver.setSuffix(".jsp");
//        return internalResourceViewResolver;
//    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry){
//        将本地文件路径映射为资源路径
        registry.addResourceHandler("/static/**").addResourceLocations("file:E:/ItemStatic/static/");
        registry.addResourceHandler("/upload/**").addResourceLocations("file:E:/ItemStatic/upload/");
    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry){
        InternalResourceViewResolver internalResourceViewResolver=new InternalResourceViewResolver();
        internalResourceViewResolver.setPrefix("/WEB-INF/jsp/");
        internalResourceViewResolver.setSuffix(".jsp");
        registry.viewResolver(internalResourceViewResolver);
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){
//        不拦截静态资源
        configurer.enable();
    }
}

@EnableWebMvc注解表示启用MVC框架的java配置,此注解必须配合@Configuration注解使用。
@ComponentScan注解表示开启注解扫描,相当于context:component-scan标签

WebMvcConfigurer接口是Spring5.0以后的MVC配置类,Spring5.0以前使用WebMvcConfigurerAdapter作为配置类,Spring5.0以后这个类就被废弃了。你通过实现该接口,重写接口中的默认方法,配置MVC 的一些功能,比如静态资源路径的映射,跨域等。

关于视图解析器配置有两种方式,第一种将视图解析器配置成一个bean,第二种重写configureViewResolvers方法,直接注册一个视图解析器。

第二步:配置父应用配置类

package com.study.Config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

/**
 * Created by forget on 2019/6/9.
 */
@Configuration
@ComponentScan(basePackages = "com.study")
public class RootConfig {
}

该类代表父应用上下文,子应用上下文可以访问父应用上下文,但父应用上下文不能访问子应用上下文。当存在多个DispatcherServlet时可以在多个DispatcherServlet的应用上下文之间共享bean,比如数据源之类的。你也可以不配置该类,只使用一个DispatcherServlet

第三步:加载配置类

package com.study.Config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

/**
 * Created by forget on 2019/6/9.
 */
public class ConfigDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
//        return new Class[]{RootConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMVCConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

该类用于代替web.xml,加载配置类。该类之所以可以不用web.xml就能完成配置类的自动加载,是因为在Servlet3.0环境下,Servlet 容器会在 classpath 下搜索实现了 javax.servlet .ServletContainerInitializer 接口,而Spring实现了这个接口,AbstractAnnotationConfigDispatcherServletInitializer类正是间接实现了这个接口,所以在Servlet3.0容器中,就可以通过继承该类来加载配置文件了。

getRootConfigClasses方法用于加载父应用配置类,当只有一个子应用上下文(即只有一个DispatcherServlet)时可以不配置。

getServletConfigClasses方法用于加载DispatcherServlet的配置文件,每个DispatcherServlet都有自己单独的配置类。

getServletMappings方法用于配置DispatcherServlet的映射路径。

到此为止java的配置就已经全部完成了,接下来测试一下配置结果,还是原来那个控制器和视图。

第四步:测试结果

在这里插入图片描述

五  配置拦截器

1.xml配置拦截器
    <mvc:interceptors>
     <bean id="myIntersrc" class="com.study.Interceptors.MyInterceptorsrc"></bean>
        <mvc:interceptor>
            <mvc:mapping path="/"/>
            <bean id="myInter" class="com.study.Interceptors.MyInterceptor"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/"/>
            <bean id="Int" class="com.study.Interceptors.ExtendInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

mvc:interceptor标签代表一个拦截器,mvc:mapping标签代表拦截器拦截的请求url,bean标签在这里代表拦截器。你也可以直接在mvc:interceptors标签下定义拦截器的bean,这样该拦截器会拦截所有请求。

2.java配置拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry){
//        注册拦截器
          registry.addInterceptor(new MyInterceptor()).addPathPatterns("/");
          registry.addInterceptor(new ExtendInterceptor());
    }

addInterceptors方法是WebMvcConfigurer接口的默认方法,你需要实现这个接口,然后重写方法,通过addInterceptor方法注册拦截器,再通过返回值调用addPathPatterns方法,设置拦截的请求URL,如果设置则会拦截所有请求。

PS:拦截器会将静态资源也一起拦截的,即使你使用了已经配置了不拦截静态资源。所以你应该使用mvc:exclude-mapping标签或excludePathPatterns方法将静态资源的路径排除。


在上面的配置中,MyInterceptor是HandlerInterceptor接口的实现类,ExtendInterceptor是抽象类HandlerInterceptorAdapter的子类,间接的实现了HandlerInterceptor接口。在SpringMVC中要定义拦截器必须实现这个接口。

HandlerInterceptor接口中有三个方法,方法参数中的handler是下一个拦截器

  1. preHandle方法:在控制器方法调用前执行,通过返回值控制是否放行到下一个方法。

  2. postHandle方法:在控制器方法调用后执行。

  3. afterCompletion方法:在视图渲染完成后调用。

当存在多个拦截器时,执行顺序如下

  • 拦截器1执行前方法

  • 拦截器2执行前方法

  • 拦截器2执行后方法

  • 拦截器1执行后方法

  • 拦截器1页面渲染后方法

  • 拦截器2页面渲染后方法

拦截器的执行顺序就是拦截器的定义顺序

六  异常处理

SpringMVC有三种统一处理异常的方式。

第一种
使用@ExceptionHandler注解

    @ExceptionHandler
    public ModelAndView Error(Exception e)
    {
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.setViewName("error");
        modelAndView.addObject("errMsg",e.getMessage());
        return modelAndView;
    }

@ExceptionHandler注解可以指定方法处理的异常类,如果未指定,则默认为方法的参数类型。你可以选择返回视图,也可以选择配合@ResponseBody注解返回json数据。这种方式是局部的,只能处理该方法所在的Controller类出现的异常。

第二种
从Spring3.2开始就有@ControllerAdvice注解,该注解用于控制器增强,它作用于所有被@RequestMapping,@GetMapping等映射注解过的方法 ,因此可以用做全局异常处理,全局数据处理等。

@ControllerAdvice
public class Excepy{

    @ExceptionHandler
    public ModelAndView Error(Exception e)
    {
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.setViewName("error");
        modelAndView.addObject("errMsg",e.getMessage());
        return modelAndView;
    }
}

PS:该类必须被Spring扫描到,才能处理全局异常。

第三种
实现HandlerExceptionResolver接口,这个接口用于请求过程中产生的异常。

@Order(-1000)
public class Excepy implements HandlerExceptionResolver{
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.setViewName("error");
        modelAndView.addObject("errMsg",e.getMessage());
        return modelAndView;
    }
}

@Order(-1000)注解是为了提高该异常处理器的优先级别,防止异常被Spring的异常处理器捕获。该异常处理器必须被Spring容器管理才能处理异常。

七  转发和重定向

SpringMVC中想进行转发和重定向操作可以参考以下代码

    @GetMapping("/red")
    public String test01(){
        return "redirect:/index";
    }

    @GetMapping("for")
    public String test00(){
        return "forward:index";
    }
    
    @GetMapping("redMode")
    public ModelAndView test03(){
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.setViewName("redirect:/index");
        return modelAndView;
    }

    @GetMapping("forMode")
    public ModelAndView test04(){
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.setViewName("forward:/index");
        return modelAndView;
    }
带参数的重定向

SpringMVC3.1版本之后出来了RedirectAttribute功能,专门用于重定向之后还能带参数跳转的.

    @GetMapping("redMode")
    public ModelAndView test03(RedirectAttributes redirectAttributes){
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.setViewName("redirect:/hello");
        redirectAttributes.addAttribute("key","231321");
        redirectAttributes.addFlashAttribute("key2","543231");
        return modelAndView;
    }

1、使用 RedirectAttributes 的 addAttribute()方法设置参数,则参数将直接拼接在转发url后面,然后可以在通过request.getParameter(“userName”)) 和 直接通过spring mvc配置参数映射接收到参数
2、使用 RedirectAttributes 的 addFlashAttribute()方法设置参数,则参数不会出现在转发url中,然后可以通过modelMap 取出参数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值