SSM框架笔记13:Spring MVC基础

SSM框架笔记13:Spring MVC基础_第1张图片

vitalflux.com对2014-2015年度10佳Web框架排名,
没有Struts2的身影,前五名为:
1、Spring MVC
2、Grails
3、Play
4、Spring Boot
5、Vaadin

Spring MVC 是目前Java Web框架当之无愧的霸主(hegemon)。

一、Spring MVC概述
MVC:Model + View + Controller (数据模型+视图+控制器)
三层架构:Presentation Tier + Application Tier + Data Tier (展现层+应用层+数据访问层)

实际上MVC只存在于三层架构的展现层,M实际上是数据模型,是包含数据的对象,在Spring MVC里有一个专门的类交Model,用于和V之间的数据交互和传值;V指的是视图页面,包含JSP、FreeMarker、Velocity、Thymeleaf、Tile等;C当然就是控制器(Spring MVC的注解@Controller的类)。

三层架构是整个应用的架构,是由Spring框架负责管理的。一般项目结构中都有Service层、DAO层,这两个反馈在应用层和数据访问层。

SSM框架笔记13:Spring MVC基础_第2张图片




使用Spring MVC有两种方式:
(1)基于xml配置与注解的方式
(2)基于Java配置与注解的方式

下面我们通过案例学习基于xml配置与注解的方式来使用Spring MVC框架。

1、新建Maven项目SpringMVCDemo

SSM框架笔记13:Spring MVC基础_第3张图片

2、在pom.xml文件里添加必要的依赖


    4.0.0

    net.hw.spring
    SpringMVCDemo
    1.0-SNAPSHOT

    
        
        
            org.springframework
            spring-core
            4.3.6.RELEASE
        

        
        
            org.springframework
            spring-beans
            4.3.6.RELEASE
        

        
        
            org.springframework
            spring-context
            4.3.6.RELEASE
        

        
        
            org.springframework
            spring-web
            4.3.6.RELEASE
        

        
        
            org.springframework
            spring-webmvc
            4.3.6.RELEASE
        

        
        
            junit
            junit
            4.12
        

        
        
            log4j
            log4j
            1.2.17
        

        
        
            javax.servlet
            jstl
            1.2
        
    
3、将项目添加Web和Spring功能

SSM框架笔记13:Spring MVC基础_第4张图片

4、在WEB-INF里创建views目录,在里面创建登录页面、成功页面和失败页面

SSM框架笔记13:Spring MVC基础_第5张图片

三个页面的内容暂时不写,后面我们再来补充。

5、在main/java里创建包net.hw.spring.webmvc

SSM框架笔记13:Spring MVC基础_第6张图片

6、在resources里创建Spring配置文件spring-config.xml

SSM框架笔记13:Spring MVC基础_第7张图片

7、在resources里创建Spring MVC配置文件spring-mvc-config.xml

SSM框架笔记13:Spring MVC基础_第8张图片




    
    

    
    

    
    
        
        
        
    

8、在resources里创建日志属性文件log4j.properties

SSM框架笔记13:Spring MVC基础_第9张图片

9、编写web.xml文件,加载Spring配置文件以及Spring MVC配置文件

SSM框架笔记13:Spring MVC基础_第10张图片



    
    
        /WEB-INF/views/login.jsp
    
    
    
    
        org.springframework.web.context.ContextLoaderListener
    
    
    
    
        contextConfigLocation
        classpath:spring-config.xml
    
    
    
    
        DispatcherServlet
        org.springframework.web.servlet.DispatcherServlet
        
            contextConfigLocation
            classpath:spring-mvc-config.xml
        
        1
    

    
        DispatcherServlet
        /  
    
    
    
    
        Character Encoding
        org.springframework.web.filter.CharacterEncodingFilter
        
            encoding
            utf-8
        
    
    
        Character Encoding
        /*
    
    
10、 编写三个页面
(1)登录页面login.jsp

SSM框架笔记13:Spring MVC基础_第11张图片

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    用户登录
    


用户登录

账号
密码
(2)登陆成功页面success.jsp

SSM框架笔记13:Spring MVC基础_第12张图片

(3)登录失败页面failure.jsp

SSM框架笔记13:Spring MVC基础_第13张图片

11、在webmvc包里创建登录控制器LoginController

SSM框架笔记13:Spring MVC基础_第14张图片

package net.hw.spring.webmvc;

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

import javax.servlet.http.HttpSession;

/**
 * Created by howard on 2017/3/3.
 */
@Controller
public class LoginController {
    @RequestMapping("/login")
    public String login(@RequestParam("username") String username,
                        @RequestParam("password") String password,
                        HttpSession session) {        
        session.setAttribute("username", username);
        if (username.equals("admin") && password.equals("12345")) {
            return "success"; // 逻辑视图名
        } else {
            return "failure"; // 逻辑视图名
        }
    }
}
12、启动服务器,运行程序

SSM框架笔记13:Spring MVC基础_第15张图片

输入用户名和密码:admin和12345

SSM框架笔记13:Spring MVC基础_第16张图片

单击【登录】按钮:

SSM框架笔记13:Spring MVC基础_第17张图片

重新登录:

SSM框架笔记13:Spring MVC基础_第18张图片

单击【登录】按钮:

SSM框架笔记13:Spring MVC基础_第19张图片



任务:通过控制器给SpringMVCDemo项目设置首页文件index.jsp。 访问http://localhost:8080/ 显示内容Hello, Spring MVC。

1、修改web.xml文件
SSM框架笔记13:Spring MVC基础_第20张图片

2、在views目录里创建首页文件index.jsp
SSM框架笔记13:Spring MVC基础_第21张图片
3、修改LoginController

SSM框架笔记13:Spring MVC基础_第22张图片

4、启动服务器

SSM框架笔记13:Spring MVC基础_第23张图片

问题:怎么打开登录页面\WEB-INF\views\login.jsp?

在index.jsp页面添加一个跳转到登录页面的超链接。

1、修改index.jsp

SSM框架笔记13:Spring MVC基础_第24张图片

2、修改登录控制器LoginController

SSM框架笔记13:Spring MVC基础_第25张图片

3、启动服务器

SSM框架笔记13:Spring MVC基础_第26张图片

单击登录超链接:

输入用户名和密码,单击登录按钮:

SSM框架笔记13:Spring MVC基础_第27张图片

任务:利用Spring MVC配置文件实现快捷的页面跳转。

SSM框架笔记13:Spring MVC基础_第28张图片

1、修改登录控制器LoginController

SSM框架笔记13:Spring MVC基础_第29张图片

2、修改spring-mvc-config.xml


SSM框架笔记13:Spring MVC基础_第30张图片

3、启动服务器

SSM框架笔记13:Spring MVC基础_第31张图片

单击登录超链接:

SSM框架笔记13:Spring MVC基础_第32张图片

输入用户名和密码,单击登录按钮:

SSM框架笔记13:Spring MVC基础_第33张图片

任务:在WEB-INF目录里增加静态资源(图片、样式表、脚本),如何让Spring MVC能够正确地处理静态资源。

1、在WEB-INF下创建images目录,放点图片

SSM框架笔记13:Spring MVC基础_第34张图片

2、修改首页文件index.jsp,增加显示图片的元素

SSM框架笔记13:Spring MVC基础_第35张图片

3、启动服务器

SSM框架笔记13:Spring MVC基础_第36张图片

4、修改Spring MVC配置文件,单独处理静态资源

SSM框架笔记13:Spring MVC基础_第37张图片

5、启动服务器

SSM框架笔记13:Spring MVC基础_第38张图片

怎么回事呢?

原因:< img src= "/WEB-INF/images/product1.jpg" >
浏览器是无法直接访问放在/WEB-INF/目录里的资源,因此要修改这个路径,改成虚拟路径,比如< img src= "/images/product1.jpg" >

SSM框架笔记13:Spring MVC基础_第39张图片

但是这样就必须在Spring MVC配置文件里设置静态资源的路径映射。

SSM框架笔记13:Spring MVC基础_第40张图片

此时,再启动服务:

SSM框架笔记13:Spring MVC基础_第41张图片

知识点:客户端要求服务器端返回数据。

需要用到一个注解@ResponseBody

任务1、返回简单字符串

1、新建一个getStringController

SSM框架笔记13:Spring MVC基础_第42张图片

2、启动服务器,访问 http://localhost:8080/getString

SSM框架笔记13:Spring MVC基础_第43张图片

3、修改getStringController

SSM框架笔记13:Spring MVC基础_第44张图片

4、启动服务器,访问 http://localhost:8080/getString

SSM框架笔记13:Spring MVC基础_第45张图片

任务2、返回JSON数据
1、创建net.hw.spring.bean包,在里面创建User类

SSM框架笔记13:Spring MVC基础_第46张图片

package net.hw.spring.bean;

import java.util.Date;

/**
 * Created by howard on 2017/3/8.
 */
public class User {
    private int id;
    private String username;
    private String password;
    private String telephone;
    private Date registerTime;
    private int popedom;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public Date getRegisterTime() {
        return registerTime;
    }

    public void setRegisterTime(Date registerTime) {
        this.registerTime = registerTime;
    }

    public int getPopedom() {
        return popedom;
    }

    public void setPopedom(int popedom) {
        this.popedom = popedom;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", telephone='" + telephone + '\'' +
                ", registerTime=" + registerTime +
                ", popedom=" + popedom +
                '}';
    }
}

2、在net.hw.spring.webmvc包里创建GetJsonController

SSM框架笔记13:Spring MVC基础_第47张图片

package net.hw.spring.webmvc;

import net.hw.spring.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by howard on 2017/3/8.
 */
@Controller
public class GetJsonController {
    @RequestMapping(value = "/getJson", produces = "application/json; charset=utf-8")
    public @ResponseBody
    User getJson() {
        User user = new User();
        user.setId(1);
        user.setUsername("萌萌哒");
        user.setPassword("12345");
        user.setTelephone("15889895678");
        user.setRegisterTime(new Date());
        user.setPopedom(1);
        return user;
    }

    @RequestMapping(value = "/getJsonArray", produces = "application/json; charset=utf-8")
    public @ResponseBody
    List getJsonArray() {
        List users = new ArrayList();

        User user = new User();
        user.setId(1);
        user.setUsername("萌萌哒");
        user.setPassword("12345");
        user.setTelephone("15889895678");
        user.setRegisterTime(new Date());
        user.setPopedom(1);
        users.add(user);

        user = new User();
        user.setId(2);
        user.setUsername("李文霞");
        user.setPassword("45678");
        user.setTelephone("13978783456");
        user.setRegisterTime(new Date());
        user.setPopedom(1);
        users.add(user);

        user = new User();
        user.setId(3);
        user.setUsername("郑智化");
        user.setPassword("88888");
        user.setTelephone("15890903456");
        user.setRegisterTime(new Date());
        user.setPopedom(1);
        users.add(user);

        return users;
    }
}
3、在pom.xml文件里添加对json和xml格式的支持


    com.fasterxml.jackson.dataformat
    jackson-dataformat-xml
    2.5.3
4、启动服务器,访问 http://localhost:808/getJson

SSM框架笔记13:Spring MVC基础_第48张图片

5、访问 http://localhost:808/getJsonArray

SSM框架笔记13:Spring MVC基础_第49张图片

任务3、返回XML格式数据
1、在net.hw.spring.webmvc包里创建GetXmlController

SSM框架笔记13:Spring MVC基础_第50张图片

package net.hw.spring.webmvc;

import net.hw.spring.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by howard on 2017/3/8.
 */
@Controller
public class GetXmlController {
    @RequestMapping(value = "/getXml", produces = "application/xml; charset=utf-8")
    public @ResponseBody
    List getXml() {
        List users = new ArrayList();

        User user = new User();
        user.setId(1);
        user.setUsername("萌萌哒");
        user.setPassword("12345");
        user.setTelephone("15889895678");
        user.setRegisterTime(new Date());
        user.setPopedom(1);
        users.add(user);

        user = new User();
        user.setId(2);
        user.setUsername("李文霞");
        user.setPassword("45678");
        user.setTelephone("13978783456");
        user.setRegisterTime(new Date());
        user.setPopedom(1);
        users.add(user);

        user = new User();
        user.setId(3);
        user.setUsername("郑智化");
        user.setPassword("88888");
        user.setTelephone("15890903456");
        user.setRegisterTime(new Date());
        user.setPopedom(1);
        users.add(user);

        return users;
    }
}
2、启动服务器,访问 http://localhost:808/getXml

SSM框架笔记13:Spring MVC基础_第51张图片



Spring MVC 使我们可以简单地开发灵活且松耦合的Web项目。我们来学习基于基于注解和Java配置的零配置(无xml配置)的Spring MVC开发。

二、Spring MVC项目快速搭建
(一)点睛
Spring MVC提供一个DispatcherServlet来开发Web应用。

在Servlet2.5及以下的时候,只要在web.xml下配置元素即可。


    DispatcherServlet
    org.springframework.web.servlet.DispatcherServlet
    
        contextConfigLocation
        classpath:spring-mvc-config.xml
    
    1



    DispatcherServlet
    /
本节我们将使用Servlet3.0+无web.xml的配置方式,在Spring MVC里实现WebApplication接口便可实现等同于web.xml的配置。

(二)示例
1、构建Maven项目SpringMVC4Demo

SSM框架笔记13:Spring MVC基础_第52张图片

2、在pom.xml文件里添加依赖



    4.0.0

    net.hw.spring
    SpringMVC4Demo
    1.0-SNAPSHOT

    
        
        
            javax
            javaee-web-api
            7.0
            provided
        

        
        
            javax.servlet
            jstl
            1.2
        

        
        
            javax.servlet
            javax.servlet-api
            3.1.0
        

        
        
            javax.servlet.jsp
            jsp-api
            2.2.1-b03
        

        
        
            org.springframework
            spring-webmvc
            4.3.6.RELEASE
        

        
        
            org.springframework
            spring-tx
            4.3.6.RELEASE
        

        
        
            org.slf4j
            slf4j-api
            1.7.5
        

        
            org.slf4j
            jcl-over-slf4j
            1.7.5
        

        
            log4j
            log4j
            1.2.17
        

        
            ch.qos.logback
            logback-classic
            1.0.13
        

        
            ch.qos.logback
            logback-core
            1.0.13
        

        
            ch.qos.logback
            logback-access
            1.0.13
        

        
        
            junit
            junit
            4.12
        

        
        
            com.fasterxml.jackson.dataformat
            jackson-dataformat-xml
            2.5.3
        

        
        
            commons-fileupload
            commons-fileupload
            1.3.1
        

        
        
            commons-io
            commons-io
            2.2
        

    

3、创建日志配置文件logback.xml

SSM框架笔记13:Spring MVC基础_第53张图片



    
        true
    

    

    
        
            logback: %d{HH:mm:ss.SSS} %logger{36} - %msg%n
        
    

    

    
        
    
4、演示页面
在resources下创建views目录,并在此目录下新建index.jsp:

SSM框架笔记13:Spring MVC基础_第54张图片

为什么页面不放在Maven标准的web/WEB-INF下,此处这样做的主要目的是让大家书写Spring Boot的页面习惯的放置方式,Spring Boot的页面就是放置在src/main/resources下。

5、Spring MVC配置

SSM框架笔记13:Spring MVC基础_第55张图片

package net.hw.springmvc4;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

/**
 * Created by howard on 2017/2/25.
 */
@Configuration
@EnableWebMvc
@ComponentScan("net.hw.springmvc4")
public class MyMVCConfig {
    @Bean
    public InternalResourceViewResolver viewResolver () {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/classes/views");
        viewResolver.setSuffix(".jsp");
        viewResolver.setViewClass(JstlView.class);
        return viewResolver;
    }
}
6、Web应用初始化配置

SSM框架笔记13:Spring MVC基础_第56张图片

package net.hw.springmvc4;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;

/**
 * Created by howard on 2017/2/25.
 * WebApplicaitonInitializer是Spring用来配置Servlet3.0+配置的接口,
 * 从而实现了替代web.xml配置文件的作用。实现此接口将会自动被
 * SpringServletContainerInitializer(用来启动Servlet3.0容器)获取到。
 */
public class WebInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        // 创建Web应用容器
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        // 注册配置类(配置类对应以前的spring-mvc-config.xml文件)
        context.register(MyMVCConfig.class);
        // 与当前ServletContext关联
        context.setServletContext(servletContext);
        // 注册Spring MVC的前端控制器(DispatcherServlet)
       Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
       // 过滤一切资源请求
       servlet.addMapping("/");
       // 设置启动加载顺序
       servlet.setLoadOnStartup(1);
    }
}
6、简单控制器

SSM框架笔记13:Spring MVC基础_第57张图片

7、启动Tomcat服务器,查看结果

SSM框架笔记13:Spring MVC基础_第58张图片

三、Spring MVC常用注解
(一)点睛
1、@Controller,声明控制器Bean,注解在类上,表明这个类是Spring MVC里的Controller。Dispatcher Servlet会自动扫描添加了此注解的类。
2、@RequestMapping,注解在类或方法上,注解在方法上的路径会继承注解在类上的路径
3、@ResponseBody 支持将返回值放在response内,而不是返回一个页面。
4、@RequestBody 允许request的参数在request体内,而不是在直接链接在地址后面。此注解放置在参数前。
5、@Path Variable 用来接收路径参数,如/news/001,可接受001作为参数,此注解放置在参数前。
6、@RestController 是一个组合注解,组合@Controller和@ResponseBody,意味着当你只开发一个和页面交互数据的控制器时,需要使用此注解。若没有此注解,要想实现上述功能,则需要自己在代码中加@Controller和@ResponseBody两个注解。

(二)案例1(演示前五种注解)
1、创建domain子包,在里面创建Person类

SSM框架笔记13:Spring MVC基础_第59张图片

package net.hw.springmvc4.domain;

/**
 * Created by howard on 2017/2/25.
 */
public class Person {
    private Long id;
    private String name;

    public Person() {
    }

    public Person(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
2、在webmvc子包里创建DemoAnnoController

SSM框架笔记13:Spring MVC基础_第60张图片

package net.hw.springmvc4.webmvc;

import net.hw.springmvc4.domain.Person;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

/**
 * Created by howard on 2017/2/25.
 */
@Controller
@RequestMapping("/anno")
public class DemoAnnoController {
    @RequestMapping(produces = "text/plain;charset=utf-8")
    public @ResponseBody
    String index(HttpServletRequest request) {
        return "网址[" + request.getRequestURL() + "]可访问";
    }

    @RequestMapping(value = "/pathvar/{str}", produces = "text/plain;charset=utf-8")
    public @ResponseBody
    String demoPathVar(@PathVariable String str, HttpServletRequest request) {
        return "网址[" + request.getRequestURL() + "]可访问,路径参数:" + str;
    }

    @RequestMapping(value = "/requestParam", produces = "text/plain;charset=utf-8")
    public @ResponseBody
    String passRequestParam(Long id, HttpServletRequest request) {
        return "网址[" + request.getRequestURL() + "]可访问,id: " + id;
    }

    @RequestMapping(value = "/person", produces = "application/json;charset=utf-8")
    public @ResponseBody
    String passPerson(Person person, HttpServletRequest request) {
        return "网址[" + request.getRequestURL() + "]可访问, person对象的id: " + person.getId()
                + ", person对象的name: " + person.getName();
    }

    @RequestMapping(value = {"/luzhou", "/nanjing"}, produces = "text/plain;charset=utf-8")
    public @ResponseBody
    String remove(HttpServletRequest request) {
        return "网址[" + request.getRequestURL() + "]可访问,不同路径映射到同一个方法";
    }
}
3、启动服务器,测试控制器里的方法
(1)地址栏里输入 http://localhost:8080/anno
SSM框架笔记13:Spring MVC基础_第61张图片
(2)地址栏里输入 http://localhost:8080/anno/pathvar/test
SSM框架笔记13:Spring MVC基础_第62张图片
(3)地址栏里输入 http://localhost:8080/anno/requestParam?id=100
SSM框架笔记13:Spring MVC基础_第63张图片
(4)地址栏里输入 http://localhost:8080/anno/person?id=1&name=howard
SSM框架笔记13:Spring MVC基础_第64张图片
(5)地址栏里输入 http://localhost:8080/anno/luzhou
SSM框架笔记13:Spring MVC基础_第65张图片
(6)地址栏里输入 http://localhost:8080/anno/nanjing
SSM框架笔记13:Spring MVC基础_第66张图片
(三)案例2:演示@RestController注解
1、在webmvc子包里创建DemoRestController

SSM框架笔记13:Spring MVC基础_第67张图片

package net.hw.springmvc4.webmvc;

import net.hw.springmvc4.domain.Person;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by howard on 2017/2/25.
 */
@RestController // 返回数据时不需要@ResponseBody
@RequestMapping("/rest")
public class DemoRestController {
    @RequestMapping(value = "/getjson", produces = "application/json;charset=utf-8")
    public Person getjson(Person person) {
        return new Person(person.getId() + 1, person.getName() + "先生");
    }

    @RequestMapping(value = "/getxml", produces = "application/xml;charset=utf-8")
    public Person getxml(Person person) {
        return new Person(person.getId() + 1, person.getName() + "女士");
    }
}
2、启动服务器,查看结果
(1)在地址栏里输入 http://localhost:8080/rest/getjson?id=0&name=张三丰

SSM框架笔记13:Spring MVC基础_第68张图片

(2)在地址栏里输入 http://localhost:8080/rest/getxml?id=0&name=李红玉

SSM框架笔记13:Spring MVC基础_第69张图片

四、Spring MVC基本配置
(一)静态资源映射
1、点睛
程序的静态文件(js、css、图片)等需要直接访问,可通过在MVC配置里重写addResourceHandlers方法来实现。
2、示例
(1)在resources下创建static目录,在里面创建css、images与js目录,在三个目录里存放响应类型的文件

SSM框架笔记13:Spring MVC基础_第70张图片

(2)修改MyMVCConfig类

SSM框架笔记13:Spring MVC基础_第71张图片

package net.hw.springmvc4;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

/**
 * Created by howard on 2017/2/25.
 */
@Configuration
@EnableWebMvc
@ComponentScan("net.hw.springmvc4")
public class MyMVCConfig extends WebMvcConfigurerAdapter {
    /**
     * 声明视图解析器Bean,用来映射路径和实际页面的位置
     */
    @Bean
    public InternalResourceViewResolver viewResolver () {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/classes/views/");
        viewResolver.setSuffix(".jsp");
        viewResolver.setViewClass(JstlView.class);
        return viewResolver;
    }

    /**
     * 功能:静态资源映射
     * addResourceLocations指的是文件放置的目录
     * addResourceHandler指的是对外暴露的访问路径
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").
                addResourceLocations("classpath:/static/");
    }
}
(3)修改index.jsp

SSM框架笔记13:Spring MVC基础_第72张图片

启动服务器,查看结果,确实访问到了静态资源中的图片。

SSM框架笔记13:Spring MVC基础_第73张图片

(二)拦截器配置
1、点睛
拦截器实现对每一个请求处理前后进行相关的业务处理,类似于Servlet的Filter。普通的Bean继承HandlerInterceptorAdapter类来实现自定义拦截器。然后在MVC配置里通过addInterceptors方法注册自定义拦截器。
2、示例
(1)创建自定义拦截器DemoInterceptor

SSM框架笔记13:Spring MVC基础_第74张图片

package net.hw.springmvc4.interceptor;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

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

/**
 * Created by howard on 2017/2/25.
 * 或者实现HandlerInterceptor接口
 */
public class DemoInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        long startTime = (Long) request.getAttribute("startTime");
        request.removeAttribute("startTime");
        long endTime = System.currentTimeMillis();
        System.out.println("本次请求处理时间:" + (endTime - startTime) + "ms");
        request.setAttribute("handlingTime", endTime - startTime);
    }
}
(2)在MyMVCConfig文件里注册自定义拦截器

SSM框架笔记13:Spring MVC基础_第75张图片

package net.hw.springmvc4;

import net.hw.springmvc4.interceptor.DemoInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

/**
 * Created by howard on 2017/2/25.
 */
@Configuration
@EnableWebMvc
@ComponentScan("net.hw.springmvc4")
public class MyMVCConfig extends WebMvcConfigurerAdapter {
    /**
     * 配置拦截器Bean
     */
    @Bean
    public DemoInterceptor demoInterceptor() {
        return new DemoInterceptor();
    }

    /**
     * 注册拦截器
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(demoInterceptor());
    }

    /**
     * 声明视图解析器Bean,用来映射路径和实际页面的位置
     */
    @Bean
    public InternalResourceViewResolver viewResolver () {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/classes/views/");
        viewResolver.setSuffix(".jsp");
        viewResolver.setViewClass(JstlView.class);
        return viewResolver;
    }

    /**
     * 功能:静态资源映射
     * addResourceLocations指的是文件放置的目录
     * addResourceHandler指的是对外暴露的访问路径
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").
                addResourceLocations("classpath:/static/");
    }
}
启动服务器,在控制台查看结果:

SSM框架笔记13:Spring MVC基础_第76张图片

(三)@ControllerAdvice
1、点睛
通过@ControllerAdvice,我们可以将对于控制器的全局配置放置在同一个位置,注解了@Controller的方法可使用@ExceptionHandler、@InitBinder、@ModelAtrribute注解到方法上,这对所有注解了@RequestMapping的控制器内的方法有效。
(1)@ExceptionHandler:用于全局处理控制器里的异常。
(2)@InitBinder:用来设置WebDataBinder,WebDataBinder用来自动绑定前台请求到参数Model中。
(3)@ModelAttribute:原本作用是绑定键值对到Model里,此处是让全局的@RequestMapping都能获得在此处设置的键值对。
2、示例
(1)创建异常处理器通知类ExceptionHandlerAdvice

SSM框架笔记13:Spring MVC基础_第77张图片

package net.hw.springmvc4.advice;

import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;

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

/**
 * Created by howard on 2017/2/25.
 */
@ControllerAdvice // 声明控制器通知
public class ExceptionHandlerAdvice {
    @ExceptionHandler (value = Exception.class)
    public ModelAndView exception(Exception exception, WebRequest request) {
        ModelAndView modelAndView = new ModelAndView("error");
        modelAndView.addObject("errorMessage", exception.getMessage());
        return modelAndView;
    }

    @ModelAttribute // 所有注解了@RequestMapping的方法可获得此键值对
    public void addAttribute(Model model) {
        model.addAttribute("msg", "请求参数id被忽略~");
    }

    @InitBinder
    public void initBinder(WebDataBinder webDataBinder) {
        // 忽略request参数的id
        webDataBinder.setDisallowedFields("id");
        // 注册自定义日期编辑器
        webDataBinder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
    }
}
(2)创建通知控制器AdviceController

SSM框架笔记13:Spring MVC基础_第78张图片

package net.hw.springmvc4.webmvc;

import net.hw.springmvc4.domain.Person;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Created by howard on 2017/2/25.
 */
@Controller
public class AdviceController {
    @RequestMapping("/advice")
    public String getSomething(@ModelAttribute("msg") String msg, Person person) {
        throw new IllegalArgumentException("非常抱歉,参数有误!" + "
来自@ModelAttribute的msg: " + msg + "
request参数person的信息:" + person.getId() + ", " + person.getName()); } }
(3)创建异常展示页面error.jsp
SSM框架笔记13:Spring MVC基础_第79张图片
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


    Welcome


    ${errorMessage}
(4)启动服务器,访问http://localhost:8080/advice?id=1&name=howard,查看页面效果

SSM框架笔记13:Spring MVC基础_第80张图片

(四)其他配置
1、快捷的ViewController
我们曾用HelloController实现简单的页面跳转:
@Controller
public class HelloController {
    @RequestMapping("/")
    public String hello() {
        return "index";
    }
}
该控制器没有业务处理,只是简单的页面跳转,实际开发中,只需在配置MyMVCConfig里重写addViewControllers来简化配置:
@Override
public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/").setViewName("index");
}
也可以修改 addViewController的urlPath参数值:

这样实现的代码更简洁,管理更集中。
启动服务器,访问 http://localhost:8080/index

SSM框架笔记13:Spring MVC基础_第81张图片

2、路径匹配参数配置
在Spring MVC中,路径参数如果带“.”,那么“.”后面的值将被忽略。

SSM框架笔记13:Spring MVC基础_第82张图片

在MVC配置里通过重写configurePathMatch方法可以不忽略“.”后的参数值。
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
    // 不会忽略路径参数中“.”之后的值
    configurer.setUseSuffixPatternMatch(false);
}
此时,重启服务器,再次访问 http://localhost:8080/anno/pathvar/luzhou.howard ,结果如下:

SSM框架笔记13:Spring MVC基础_第83张图片

3、更多配置
更多配置请查看WebMvcConfigurerAdapter类的API,它是WebMvcConfigurer接口的实现,因此WebMvcConfigurerAdapter类的API方法可以用来配置MVC。


4、WebMvcConfigurerAdapter源代码
package org.springframework.web.servlet.config.annotation;

import java.util.List;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;

public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
    public WebMvcConfigurerAdapter() {
    }

    public void configurePathMatch(PathMatchConfigurer configurer) {
    }

    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    }

    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
    }

    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    }

    public void addFormatters(FormatterRegistry registry) {
    }

    public void addInterceptors(InterceptorRegistry registry) {
    }

    public void addResourceHandlers(ResourceHandlerRegistry registry) {
    }

    public void addCorsMappings(CorsRegistry registry) {
    }

    public void addViewControllers(ViewControllerRegistry registry) {
    }

    public void configureViewResolvers(ViewResolverRegistry registry) {
    }

    public void addArgumentResolvers(List argumentResolvers) {
    }

    public void addReturnValueHandlers(List returnValueHandlers) {
    }

    public void configureMessageConverters(List> converters) {
    }

    public void extendMessageConverters(List> converters) {
    }

    public void configureHandlerExceptionResolvers(List exceptionResolvers) {
    }

    public void extendHandlerExceptionResolvers(List exceptionResolvers) {
    }

    public Validator getValidator() {
        return null;
    }

    public MessageCodesResolver getMessageCodesResolver() {
        return null;
    }
}
5、WebMvcConfigurer源代码
package org.springframework.web.servlet.config.annotation;

import java.util.List;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;

public interface WebMvcConfigurer {
    void configurePathMatch(PathMatchConfigurer var1);

    void configureContentNegotiation(ContentNegotiationConfigurer var1);

    void configureAsyncSupport(AsyncSupportConfigurer var1);

    void configureDefaultServletHandling(DefaultServletHandlerConfigurer var1);

    void addFormatters(FormatterRegistry var1);

    void addInterceptors(InterceptorRegistry var1);

    void addResourceHandlers(ResourceHandlerRegistry var1);

    void addCorsMappings(CorsRegistry var1);

    void addViewControllers(ViewControllerRegistry var1);

    void configureViewResolvers(ViewResolverRegistry var1);

    void addArgumentResolvers(List var1);

    void addReturnValueHandlers(List var1);

    void configureMessageConverters(List> var1);

    void extendMessageConverters(List> var1);

    void configureHandlerExceptionResolvers(List var1);

    void extendHandlerExceptionResolvers(List var1);

    Validator getValidator();

    MessageCodesResolver getMessageCodesResolver();
}
五、Spring MVC高级配置
(一)文件上传配置
1、点睛
文件上传是一个项目里常用的功能,Spring MVC通过配置一个MultipartResolver来上传文件。
在Spring的控制器中,通过MultipartFile file来接收文件,通过MultipartFile[] files接收多个上传文件。
2、示例
(1)在pom.xml文件里添加文件上传依赖


    commons-fileupload
    commons-fileupload
    1.3.1
(2)创建上传页面upload.jsp
SSM框架笔记13:Spring MVC基础_第84张图片
<%@ page contentType="text/html;charset=UTF-8" language="java" %>



    上传文件
    


    

(3)在MVC配置里添加跳转到upload页面的ViewController
@Override
public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/index").setViewName("index");
    registry.addViewController("/toUpload").setViewName("upload");
}
(4)在MVC配置里设置MultipartResolver
@Bean
public MultipartResolver multipartResolver() {
    CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
    multipartResolver.setMaxUploadSize(1000000);
    // 避免中文文件名出现乱码
    multipartResolver.setDefaultEncoding("utf-8");
    return multipartResolver;
}
(5)创建上传控制器UploadController
SSM框架笔记13:Spring MVC基础_第85张图片
package net.hw.springmvc4.webmvc;

import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

/**
 * Created by howard on 2017/2/25.
 */
@Controller
public class UploadController {
    @RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "text/plain;charset=utf-8")
    public
    @ResponseBody
    String upload(MultipartFile file) {
        try {
            File uploadFile = new File("c:/upload/" + file.getOriginalFilename());
            FileUtils.writeByteArrayToFile(uploadFile, file.getBytes());
            return "文件上传成功!位置:" + uploadFile.getAbsolutePath();
        } catch (IOException e) {
            e.printStackTrace();
            return "文件上传失败!";
        }
    }
}
(6)启动服务器,访问 http://localhost:8080/toUpload
SSM框架笔记13:Spring MVC基础_第86张图片
选择上传文件:
SSM框架笔记13:Spring MVC基础_第87张图片
单击【上传】按钮:
SSM框架笔记13:Spring MVC基础_第88张图片
查看c:\upload文件夹:
SSM框架笔记13:Spring MVC基础_第89张图片
(二)自定义HttpMessageConverter
1、点睛
HttpMessageConverter用来处理request和response里的数据。Spring为我们内置了大量的HttpMessageConverter,比如MappingJackson2HttpMessageConverter、StringHttpMessageConverter等。
本节演示自定义的HttpMessageConverter,并在MVC配置里注册它。
2、示例
(1)创建MyMessageConverter
SSM框架笔记13:Spring MVC基础_第90张图片
package net.hw.springmvc4.converter;

import net.hw.springmvc4.domain.Person;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.nio.charset.Charset;

/**
 * Created by howard on 2017/2/25.
 */
public class MyMessageConverter extends AbstractHttpMessageConverter {
    
    public MyMessageConverter() {
        // 新建自定义媒体类型application/x-hw
        super(new MediaType("application", "x-hw", Charset.forName("utf-8")));
    }

    @Override
    protected boolean supports(Class clazz) {
        // 表明本HttpMessageConverter只处理Person这个类
        return Person.class.isAssignableFrom(clazz);
    }

    @Override
    protected Person readInternal(Class clazz, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
        String temp = StreamUtils.copyToString(httpInputMessage.getBody(), Charset.forName("utf-8"));
        String[] tempArr = temp.split("-");
        return new Person(new Long(tempArr[0]), tempArr[1]);
    }

    @Override
    protected void writeInternal(Person person, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {
        String out = "Hello, " + person.getId() + "-" + person.getName();
        httpOutputMessage.getBody().write(out.getBytes());
    }
}
(2)创建演示页面converter.jsp
SSM框架笔记13:Spring MVC基础_第91张图片
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    
    HttpMessageConverter


(3)在MVC里配置添加视图控制器,映射到converter.jsp页面
@Override
public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/index").setViewName("index");
    registry.addViewController("/toUpload").setViewName("upload");
    registry.addViewController("/converter").setViewName("converter");
}
(4)在MVC里注册HttpMessageConverter
有两种注册HttpMessageConverter的方法:
  • configureMessageConverters:重载会覆盖掉Spring MVC默认注册的多个HttpMessageConverter。
  • extendMessageConverters:仅添加一个自定义的HttpMessageConverter,不会覆盖默认注册的HttpMessageConverter。

本例中我们采用第二种方法:

@Bean
public HttpMessageConverter converter() {
    return new MyMessageConverter();
}
@Override
public void extendMessageConverters(List> converters) {
    converters.add(converter());
}
(5)创建控制器ConverterController
SSM框架笔记13:Spring MVC基础_第92张图片
package net.hw.springmvc4.webmvc;

import net.hw.springmvc4.domain.Person;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * Created by howard on 2017/2/25.
 */
@Controller
public class ConverterController {
    @RequestMapping(value = "/convert", produces = "application/x-hw")
    public @ResponseBody
    Person convert(@RequestBody Person person) {
        return person;
    }
}
(6)启动服务器,访问 http://localhost:8080/converter

SSM框架笔记13:Spring MVC基础_第93张图片

单击【请求】按钮:
SSM框架笔记13:Spring MVC基础_第94张图片


请求类型如下图所示:

SSM框架笔记13:Spring MVC基础_第95张图片

(三)服务器端推送技术
本节提供基于SSE(Server Send Event 服务端发送事件)的服务器端推送和基于Servlet3.0+的异步方法特性,其中第一种方式需要新式浏览器的支持,第二种方式是跨浏览器的。
1、SSE方式
(1)创建控制器SseController
SSM框架笔记13:Spring MVC基础_第96张图片
package net.hw.springmvc4.webmvc;

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

import java.util.Random;

/**
 * Created by howard on 2017/2/26.
 */
@Controller
public class SseController {
    @RequestMapping(value = "/push", produces = "text/event-stream")
    public @ResponseBody String push() {
        Random r = new Random();
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "data: Testing 1, 2, 3 " + r.nextInt() + "\n\n";
    }
}
(2)在resources/views目录里创建sse.jsp页面
SSM框架笔记13:Spring MVC基础_第97张图片
<%@ page contentType="text/html;charset=utf-8" language="java" %>


    SSE Demo
    


    

演示SSE技术

(3)在MyMvcConfig类里添加跳转sse.jsp页面的映射

SSM框架笔记13:Spring MVC基础_第98张图片

(4)启动服务器,在 360浏览器里 访问 http://localhost:8080/sse
SSM框架笔记13:Spring MVC基础_第99张图片
换个浏览器(Firefox),再访问 http://localhost:8080/sse
SSM框架笔记13:Spring MVC基础_第100张图片
2、Servlet3.0+异步方法处理
(1)开启异步方法支持

SSM框架笔记13:Spring MVC基础_第101张图片

(2)定时任务(推送服务PushService)

SSM框架笔记13:Spring MVC基础_第102张图片

package net.hw.springmvc4.service;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.async.DeferredResult;

import java.text.SimpleDateFormat;

/**
 * Created by howard on 2017/2/26.
 */
@Service
public class PushService {
    /**
     * 声明延迟结果
     */
    private DeferredResult deferredResult;

    /**
     * 获取异步更新
     */
    public DeferredResult getAysncUpdate() {
        deferredResult = new DeferredResult();
        return deferredResult;
    }

    @Scheduled(fixedDelay = 1000)
    public void refresh() {
        if (deferredResult != null) {
            deferredResult.setResult(new SimpleDateFormat("hh:mm:ss").format(System.currentTimeMillis()));
        }
    }
}
(3)创建控制器AsyncController

SSM框架笔记13:Spring MVC基础_第103张图片

package net.hw.springmvc4.webmvc;

import net.hw.springmvc4.service.PushService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.async.DeferredResult;

/**
 * Created by howard on 2017/2/26.
 */
@Controller
public class AsyncController {
    @Autowired
    private PushService pushService;

    @RequestMapping("/defer")
    public @ResponseBody DeferredResult deferredCall() {
        return pushService.getAysncUpdate();
    }
}
(4)演示页面(resources/views/async.jsp)

SSM框架笔记13:Spring MVC基础_第104张图片

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Servlet Async Support
    


演示Servlet3.0+异步处理方法

(5)在MyMvcConfig上启动计划任务的支持

SSM框架笔记13:Spring MVC基础_第105张图片

(6)在配置里添加视图控制器跳转到async.jsp页面

SSM框架笔记13:Spring MVC基础_第106张图片

(7)启动服务器,访问 http://localhost:8080/async
SSM框架笔记13:Spring MVC基础_第107张图片

你可能感兴趣的:(Java,Web框架)