Хороший! Наконец кто-то объяснил SpringMVC

задняя часть Spring MVC
Хороший! Наконец кто-то объяснил SpringMVC

Это 4-й день моего участия в августовском испытании обновлений.Подробности о событии:Испытание августовского обновления

1. Введение в SpringMVC

1.1, введение в SpringMVC

Чтобы сделать Spring подключаемой архитектурой MVC, SpringFrameWork разрабатывает среду SpringMVC на основе Spring, так что вы можете использовать Spring для веб-разработки.Фреймворк Spring SpringMVC как фреймворк контроллера для веб-разработки.

1.2, преимущества SpringMVC

SpringMVC — этоТипичный легкий фреймворк MVC, действует как инфраструктура контроллера во всей архитектуре MVC по сравнению с предыдущей инфраструктурой struts2,SpringMVC работает быстрее, а его разработка аннотаций более эффективна и гибка..

image-20210303203718690

  1. Его можно легко интегрировать с фреймворком Spring.
  2. Операционная эффективность намного выше, чем у struts2 framework.
  3. Аннотированная разработка более эффективна.

2. Начало работы со SpringMVC

2.1. Строительство окружающей среды

2.1.1. Введение зависимостей

Зависимости игнорируются, и я помещаю их в область комментариев!

2.1.2, записать файл конфигурации

<?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.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

<!--  1. 开启注解扫描-->
  <context:component-scan base-package="com.lin.controller"/>
<!--  2. 配置处理器映射器-->
<!--  <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />-->
<!--  3. 开启处理器适配器-->
<!--  <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />-->
<!--  上面两段配置被下面的一句话所替代(封装)-->
  <mvc:annotation-driven />
  <!--  4. 开启视图解析器-->
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/"/>
    <property name="suffix" value=".jsp"/>
  </bean>
</beans>

2.1.3, настроить 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>
  <display-name>Archetype Created Web Application</display-name>

<!--  配置springmvc的核心servlet-->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
<!--      告诉springmvc配置文件的位置-->
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
<!--    拦截所有请求-->
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

2.1.4, контроллер записи

package com.lin.controller;

import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author XiaoLin
 * @date 2021/2/17 17:09
 */
@Controller
public class HellowController {

  /**
      * @Description:第一个springmvc测试类
      * @author XiaoLin
      * @date 2021/2/17
      * @Param: [username, password]
      * @return java.lang.String
      */
     /*
      RequestMapping的修饰范围:可以用在类上和方法上,他的作用如下:
      1. 用在方法上可以给当前方法加入指定的请求路径
      2. 用在类上可以给类中的所有方法都加入一个统一的请求路径,在这个方法访问之前都必须加上
      */
  @RequestMapping("/hello")
  public String hello(String username,String password){
    System.out.println("hello");
    return "index";
  }
}

2.2 Подробное объяснение аннотаций

2.2.1,@Controller

Эта аннотация используется для идентификации класса, что это класс компонента контроллера, и создания экземпляра этого класса, чтобы сообщить Spring, что я контроллер.

2.2.2,@RequestMapping

Эту аннотацию можно использовать в методах или классах для указания пути запроса.

2.3, метод перехода SpringMVC

Есть два традиционных способа ускорить разработку сервлетов:

  1. вперед: переход вперед — это переход внутри сервера, поэтому это запрос, а адресная строка остается неизменной. При прыжке можно нести данные на передачу (используя область запроса на передачу).
  2. перенаправление: переход перенаправления является переходом на стороне клиента, поэтому это несколько запросов, адресная строка изменится, и данные не могут быть переданы во время перехода.

2.3.1, Контроллер ——> Главная страница

2.3.1.1, вперед

В ходе тестирования мы можем обнаружить, что SpringMVC по умолчанию использует метод переадресации запросов для перехода на главную страницу;

@Controller
@RequestMapping("forwoartAndRedirect")
public class TestForwoartAndRedirect {

  @RequestMapping("test")
  public String test(){
    System.out.println("test");
    return"index";
  }
}

2.3.1.2, перенаправление

Если мы хотим использовать перенаправление для перехода, нам нужно использовать ключевые слова, предоставленные нам SpringMVC——redirect:Что нужно сделать.

грамматика:return "redirect:/视图全路径名";

**Примечание:**redirect:За страницей следует не логическое имя, а полный путь. Поскольку переходы перенаправления не проходят через преобразователь представления.

2.3.1 Контроллер ——> Контроллер

2.3.1.1, вперед

Если мы хотим использовать переадресацию запросов для перехода к разным методам одного и того же (другого) контроллера, нам также необходимо использовать ключевые слова, предоставляемые SpringMVC:forward:.

грамматика:return:"forward: /需要跳转的类上的@RequestMapping的值/需要跳转的方法上的@RequestMapping的值;"

2.3.1.2, перенаправление

Если мы хотим использовать перенаправление, чтобы перейти к разным способам того же (разного) контроллера, нам также нужно использовать ключевые слова, предоставленные SpringMVC:redirect:.

грамматика:return:"redirect: /需要跳转的类上的@RequestMapping的值/需要跳转的方法上的@RequestMapping的值;"

2.4, прием параметра SpringMVC

2.4.1 Как сервлет получает параметры

В традиционной разработке сервлетов мы обычно используем этот метод для получения параметров запроса.

// 接收名字为name的参数
request.getParameter(name)

У него есть несколько замечаний:

  1. Обязательным параметром является атрибут имени поля формы.
  2. Метод getParameter используется для получения одного значения, а возвращаемый тип — String.
  3. Метод getParameterValues ​​используется для получения набора данных, а возвращаемый результат — String[].
  4. Есть много избыточных кодов, которые неудобно использовать, и типы должны быть преобразованы сами по себе.

2.4.2, прием параметра SpringMVC

SpringMVC использует список параметров метода в контроллере для получения параметров запроса клиента, которые могут выполнять автоматическое преобразование типов,Требуется, чтобы ключ передаваемого параметра совпадал с именем переменной формального параметра соответствующего метода, прежде чем можно будет выполнить автоматическое назначение.. Его преимущества очевидны:

  1. Упростить форму получения параметров (не нужно вызывать какой-либо метод, какие параметры нужны, просто указать какие параметры в методе контроллера).
  2. Тип параметра не нужно преобразовывать самостоятельно. Дата и время (по умолчанию — гггг/мм/дд), вам необходимо использовать аннотацию @DateTimeFormat, чтобы объявить формат, которому следует следовать при преобразовании даты, иначе будет выдано исключение 400.

2.4.2.1, основные типы данных

    Требуется, чтобы ключ передаваемого параметра совпадал с именем переменной формального параметра соответствующего метода для завершения автоматического присвоения.

2.4.2.2 Тип объекта

Если нам нужно получить тип объекта, мы можем напрямую объявить объект, который будет получен, как параметр метода контроллера. SpringMVC автоматически инкапсулирует объект.Если переданный ключ параметра совпадает с именем свойства в объекте, он будет автоматически инкапсулирован в объект.

2.4.2.3, тип массива

Если нам нужно получить тип массива, нам нужно только напрямую объявить тип массива, который будет получен, как формальный параметр метода.

2.4.2.4 Тип коллекции

SpringMVC не может напрямую получать параметры типа коллекции через список формальных параметров.Если вам нужно получить параметры типа коллекции, вы должны поместить коллекцию в объект и предоставить метод get/set. Рекомендуется инкапсулировать его в объект VO, а затем использовать тип объекта для его получения.

2.5, SpringMVC получает параметр китайской искаженной проблемы

2.5.1. ПОЛУЧИТЬ запрос

Искаженный код в методе запроса GET необходимо обсудить по версии Tomcat:

  1. Перед версией Tomcat8.x: используйте значение по умолчанию в server.xml.URIEncoding="ISO-8859-1"вместо кодировки "UTF-8", и появятся искаженные китайские символы.
  2. После версии Tomcat8.x: используйте значение по умолчанию в server.xml.URIEncoding="UTF-8", так что не будет проблемы с китайским искажением.

2.5.2, POST-запрос

SpringMVC не выполняет никакой обработки кодирования запросов POST по умолчанию, поэтому независимо от того, какая версия напрямую получает запросы POST, будут отображаться искаженные китайские символы.

2.5.2.1 Пользовательский фильтр для устранения искаженного запроса POST

На этапе сервлета мы изучили фильтры и можем настроить фильтры для фильтрации кода.

package com.filter;

import javax.servlet.*;
import java.io.IOException;

//自定义编码filter
public class CharacterEncodingFilter  implements Filter {

    private String encoding;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.encoding = filterConfig.getInitParameter("encoding");
        System.out.println(encoding);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding(encoding);
        response.setCharacterEncoding(encoding);
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}
 <!--配置post请求方式中文乱码的Filter-->
  <filter>
    <filter-name>charset</filter-name>
    <filter-class>com.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>

  <filter-mapping>
    <filter-name>charset</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

2.5.2.2 Используйте CharacterEncodingFilter для устранения искаженных запросов POST


  <!--配置post请求方式中文乱码的Filter-->
  <filter>
    <filter-name>charset</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>charset</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
package com.filter;

import javax.servlet.*;
import java.io.IOException;

//自定义编码filter
public class CharacterEncodingFilter  implements Filter {

    private String encoding;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.encoding = filterConfig.getInitParameter("encoding");
        System.out.println(encoding);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding(encoding);
        response.setCharacterEncoding(encoding);
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}

2.6 Механизм передачи данных в SpringMVC

2.6.1, каков механизм передачи данных

Механизм передачи данных в основном включает в себя три проблемы:

  1. Как хранятся данные?
  2. Как получить данные на странице?
  3. Как должны отображаться данные, полученные на странице?

2.6.2, Механизм передачи данных сервлета

В предыдущей разработке сервлета мы обычно помещали данные в область (запрос, сеанс, приложение). Если данные представляют собой единый фрагмент данных, его можно отобразить непосредственно во внешнем интерфейсе с помощью выражений EL. Если это набор или массив, можно использовать выражения EL.➕Теги JSTL просматриваются и отображаются во внешнем интерфейсе.

3. Интерфейсный контроллер

3.1 Что такое интерфейсный контроллер

В среде MVC есть интерфейсный контроллер, а входной контроллер (контроллер) установлен на интерфейсе (фронт) веб-приложения для обеспечения централизованного механизма обработки запросов, и все запросы отправляются на контроллер для единый процесс, а затем отправляют запрос соответствующим обработчикам. Обычно используется для выполнения общих процессов, таких как проверка разрешений, авторизация, ведение журнала и т. д. Возможность повторного использования и масштабируемость улучшаются благодаря возможности интерфейсных элементов управления централизованно обрабатывать запросы.

Вот как мы передаем и обрабатываем запросы без фронт-контроллера.

image-20210303204840516

С фронт-контроллером мы стали такими.

image-20210303205548577

3.2, реализация кода

Spring MVC уже предоставляет класс DispatcherServlet в качестве переднего контроллера, поэтому для использования Spring MVC вы должны настроить передний контроллер в файле web.xml.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0">
  <!-- Spring MVC 前端控制器-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-
      class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 指定 Spring 容器启动加载的配置文件-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:mvc.xml</param-value>
    </init-param>
    <!-- Tomcat 启动初始化 -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

3.3 Внимание

    load-on-startupЭлемент является необязательным: если значение равно 0 или больше 0, это означает, что контейнер строит сервлет при старте приложения и вызывает свой метод init для инициализации (чем меньше неотрицательное значение, тем выше приоритет запуска сервлета). сервлет); Если значение отрицательное или не указано, сервлет будет загружен при первом запросе. Если это настроено, работа по инициализации SpringMVC может быть завершена при запуске контейнера, а не оставлена ​​на выполнение по запросу пользователя, что повышает удобство доступа пользователя.

3.4, сопоставление пути

Путь сопоставления для настройки фронт-контроллера обычно имеет следующие три формы:

  1. Конфигурация, такая как .do, .htm, является наиболее традиционным способом доступа к статическим файлам (изображениям, JS, CSS и т. д.), но не поддерживает стиль RESTful.
  2. Настроенный как /, он может поддерживать популярные стили RESTful, но статические файлы (изображения, JS, CSS и т. д.) будут заблокированы и недоступны.
  3. Это неправильный способ настроить его как /*, его можно запросить у контроллера, но он будет перехвачен при переходе к JSP, и представление JSP не может быть отрисовано, что также приведет к недоступным статическим ресурсам.

3.4.1 Причины перехвата доступа к статическим ресурсам и JSP

    Tomcat 容器处理静态资源是交由内置 DefaultServlet 来处理的(拦截路径是 /),处理 JSP 资源是交由内置的 JspServlet 处理的(拦截路径是*.jsp | *.jspx)。
    启动项目时,先加载容器的 web.xml,而后加载项目中的 web.xml。当拦截路径在两者文件中配置的一样,后面会覆盖掉前者。
    所以前端控制器配置拦截路径是 / 的所有静态资源都会交由前端控制器处理,而拦截路径配置 /*,所有静态资源和 JSP 都会交由前端控制器处理。

3.4.2, как решить

3.4.2.1 Метод 1

Измените файл web.xml и измените путь сопоставления интерфейсного контроллера на*.do,Но обратите внимание, что при доступе к методу обработчика в контроллере путь запроса должен содержать .do.

<servlet-mapping>
	<servlet-name>dispatcherServlet</servlet-name>
	<url-pattern>*.do</url-pattern>
</servlet-mapping>	

3.4.2.2 Метод 2

Добавьте раздел конфигурации в mvc.xml, который будет создавать и хранить конфигурацию в контексте Spring MVC.DefaultServletHttpRequestHandlerфасоль, будет входитьDispatcherServletЗапрос проверяется, и если это не сопоставленный запрос, запрос передается сервлету контейнера по умолчанию для обработки.

<mvc:default-servlet-handler/>

3,5,@ModelAttributeаннотация

объект в параметре (Должен быть пользовательский тип), SpringMVC по умолчанию сохранит его вModel, имя — это первая буква имени класса параметра в нижнем регистре, иногда этот класс будет очень длинным, но у нас есть такое требование, например: эхо условий запроса. Мы просто добавляем перед пользовательским классом@ModelAttribute, который может написать имя ключа, который нам нужно изменить.

package cn.wolfcode.web.controller;
	@Controller
	public class RequestController {
		@RequestMapping("/req7")
			public String resp7(@ModelAttribute("u") User user) {
			return "m";
		}
}

В-четвертых, обработка ответа

Роль SpringMVC заключается в запросе и обработке ответа.Обработка ответа относится к тому, как написать метод обработки в контроллере, чтобы принять запрос в качестве ответа, найти файл представления и сохранить данные в области видимости. Для обработки метода ответа общий метод обработки возвращает тип ModelAndView и String.

4.1. Вернуться к ModelAndView

Метод возвращает объект ModelAndView, в котором задаются данные модели и указывается представление. Внешний интерфейс по-прежнему использует JSTL+CgLib для получения значения. У него есть два распространенных метода:

  1. addObject(String key, Object value): Установите ключ и значение общих данных.
  2. addObject(Object value): Установите значение общих данных, ключ — это первая буква типа значения в нижнем регистре.
package cn.linstudy.web.controller;

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

@Controller
public class ResponseController {
  // 提供方法处理请求,localhost/resp1
  @RequestMapping("/resp1")
  public ModelAndView resp1() {
// 通过创建这个类对象,告诉 Spring MVC 找什么视图文件, 往作用域或者说往模型中存入什么数据
    ModelAndView mv = new ModelAndView();
// 往作用域或者模型中存入数据
    mv.addObject("msg", "方法返回类型是 ModelAndView");
// 找视图
    mv.setViewName("/WEB-INF/views/resp.jsp");
    return mv;
  }

4.2, вернуть строку

Возвращает тип String (широко используемый). В настоящее время, если нам нужно обмениваться данными, нам нужно использовать объект HttpServlet. Spring помогает нам инкапсулировать объект: Model . Используется в сочетании для хранения данных в области видимости или модели.

package cn.instudy.web.controller;

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

@Controller
public class ResponseController {
  // 提供方法处理请求,localhost/resp2
  @RequestMapping("/resp2")
  public String resp2(Model model) {
// 往作用域或者模型中存入数据
    model.addAttribute("msg", "方法返回类型是 String");
// 返回视图名
    return "/WEB-INF/views/resp.jsp";
  }
}

4.3 Улучшение

Мы обнаружим, что если нам нужно написать интерфейс возврата, нам нужно постоянно писать префикс и суффикс. В настоящее время нам нужно исключить префикс и суффикс представления. Нам нужно только настроить парсер представления в Spring.

<!--
配置视图解析器 配置这个Spring MVC 找视图的路径就是:前缀 + 逻辑视图名(处理方法设置或返回视图名)+ 后缀名
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<!-- 视图前缀 -->
	<property name="prefix" value="/WEB-INF/views/"/>
	<!-- 视图后缀 -->
	<property name="suffix" value=".jsp"/>
</bean>

5. Запрос на переадресацию и перенаправление

5.1 Разница между переадресацией запроса и перенаправлением

несколько запросов Адресная строка Ресурсы в WEB-INF поделиться данными запроса Повторно ли отправлена ​​форма
запрос на переадресацию 1 раз не меняется может получить доступ можно поделиться имеют
перенаправить неоднократно Изменять не доступный нельзя поделиться никто

5.2. Переадресация запроса

Добавьте ключевое слово forward, чтобы указать, что запрос переадресован, что эквивалентноrequest.getRequestDispatcher().forward(request,response), адресная строка браузера остается неизменной после переадресации, а данные в предыдущем запросе используются совместно.После добавления ключевого слова настроенный преобразователь представления не работает. Если возвращаемое представление должно писать полный путь

package cn.linstudy.web.controller;
@Controller
public class ResponseController {

	@RequestMapping("/TestForward")
	public String forward() {
		return "forward:/WEB-INF/views/welcome.jsp";
	}
}

5.3. Перенаправление

Добавьте ключевое слово перенаправления, чтобы указать перенаправление, что эквивалентноresponse.sendRedirect(), после перенаправления адресная строка браузера становится адресом перенаправления и не передает ранее запрошенные данные.

package cn.linstudy.web.controller;
@Controller
public class ResponseController {
	// localhost/r
	@RequestMapping("/TestRedirect")
	public String redirect() {
		return "redirect:/static/demo.html";
	}
}

5.4, ​​путь запроса

При запросе переадресации и перенаправления у нас обычно есть два способа записи пути запроса:

  1. добавлять/: используется абсолютный путь (рекомендуется), который находится в корневом пути проекта. (/response/test6 ---> "redirect:/hello.html" ---> localhost:/hello.html)
  2. не добавлять/: Использование — это относительный путь, который относится к предыдущему уровню предыдущего пути контекста доступа. (/response/test6 ---> "redirect:hello.html" ---> localhost:/response/hello.html)

6. Обработка параметров

6.1 Обработка простых типов параметров запроса

Как получить параметры параметра простого типа данных в запросе в контроллере? Простые типы данных включают базовые типы данных и их классы-оболочки, которые принимают формальные параметры, такие как String и BigDecimal.

6.1.1 Имя параметра запроса и формальный параметр списка параметров метода контроллера имеют одно и то же имя.

Если имя параметра, переданное от стойки регистрации, совпадает с формальным именем параметра списка параметров в методе контроллера, ничего делать не нужно, и SpringMVC автоматически назначит его нам.

 // 请求路径为:/req1?username=zs&age=18
package cn.linstudy.web.controller;
	@Controller
	public class RequestController {
		@RequestMapping("/req1")
		public ModelAndView resp1(String username, int age) {
			System.out.println(username);
			System.out.println(age);
			return null;
		}
}

6.1.2 Имя параметра запроса и параметр списка параметров метода контроллера имеют разные имена

Если имя параметра, переданное от стойки регистрации, отличается от формального имени параметра параметра списка параметров в методе контроллера, нам нужно использовать аннотацию.@RequestParam("前台携带的参数名")Чтобы сообщить SpringMVC о любом назначении данных.

 // 请求路径为:/req1?username=zs&age=18
package cn.linstudy.web.controller;
	@Controller
	public class RequestController {
		@RequestMapping("/req1")
		public ModelAndView resp1(@RequestParam("username") String username1, @RequestParam("age") int age1) {
			System.out.println(username);
			System.out.println(age);
			return null;
		}
}

6.2 Обработка сложных типов параметров запроса

6.2.1 Тип массива

Для параметров типа массива нам нужно только определить тип массива с тем же именем в списке формальных параметров параметра метода, который нужно получить.

// 请求路径 /req3?ids=1&ids=2&ids=3
package cn.linstudy.web.controller;
	@Controller
	public class RequestController {
		@RequestMapping("/req3")
		public ModelAndView resp3(Long[] ids) {
			System.out.println(Arrays.toString(ids));
			return null;
		}
}

6.2.2 Пользовательский тип

Во многих случаях нам нужно получить объект пользовательского типа. Например, когда мы сохраняем пользователей, нам нужно инкапсулировать данные, передаваемые внешним интерфейсом, в настраиваемый тип пользователя.На данный момент нам нужно только убедиться, что поля в пользовательском типе совпадают с полями, передаваемыми внешний интерфейс (Обратите внимание, что имя переданного параметра совпадает с именем свойства инкапсулированного объекта.), SpringMVC может автоматически инкапсулировать его.

// /req4?username=hehe&password=666
package cn.linstudy.web.controller;	
	@Controller
	public class RequestController {
		@RequestMapping("/req4")
		public ModelAndView resp4(User user) {
			System.out.println(user);
			return null
		}
}

Базовый Spring MVC вызывает метод обработки в соответствии с адресом запроса. При вызове метода он обнаруживает, что необходимо передать фактический параметр типа User. Spring MVC создаст объект User путем отражения, а затем найдет соответствующий атрибут через имя параметра запроса и установить соответствующее значение параметра для атрибута объекта.

6.3. Обработка параметров запроса типа даты

6.3.1, дата указана в параметре запроса

Если дата стоит в параметре запроса, то ее нужно вставить в формальный параметр типа Дата метода обработки@DateTimeFormatаннотация.

package cn.linstudy.controller;
	@Controller
	public class RequestController {
		@RequestMapping("/req5")
		// 注意形参的类型为 java.util.Date
		public ModelAndView resp5(@DateTimeFormat(pattern="yyyy-MM-dd")Date date) {
			System.out.println(date.toLocaleString());
			return null;
		}
}

6.3.2 На инкапсулированном объекте

Если дата находится в поле инкапсулируемого объекта, то нам нужно вставить ее в поле@DateTimeFormatаннотация.

package cn.linstudy.domain;
	public class User {
	private Long id;
	private String Username;
	private String password;
	// 增加下面这个字段,并贴注解
	@DateTimeFormat(pattern="yyyy-MM-dd")
	private Date date;
	// 省略 setter getter toString
}
	package cn.linstudy.controller;
	@Controller
	public class RequestController {
		@RequestMapping("/req6")
		public ModelAndView resp6(User user) {
			System.out.println(user);
			return null;
		}
}

7. Загрузка и скачивание файлов

7.1 Загрузка файла

Просмотрите предыдущее использование Servlet3.0 для решения проблемы загрузки файлов, написания форм загрузки (POST, multipart/form-data) и написания кода для разбора загруженных файлов в методе обработки doPost. Но в SpringMVC это может помочь нам упростить шаги и код загрузки файлов.

7.1.1 Написание формы

Обратите внимание, что тип данных запроса должен быть: multipart/form-data, а метод запроса — POST.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<body>
	<form action="/upload" method="POST" enctype="multipart/form-data">
		文件:<input type="file" name="pic"><br>
		<input type="submit" value="提交"/>
	</form>
</body>
</html>

7.1.2. Изменение web.xml

Мы можем указать размер загружаемого файла в web.xml.

<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:mvc.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
	<multipart-config>
		<max-file-size>52428800</max-file-size>
		<max-request-size>52428800</max-request-size>
	</multipart-config>
</servlet>
<servlet-mapping>
	<servlet-name>dispatcherServlet</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>

7.1.3, настроить парсер загрузки

Настройте парсер загрузки в mvc.xml,Использование SpringMVCmultipartfileЧтобы получить файл, загруженный клиентом, должен быть настроен парсер загрузки файлов, а идентификатор парсинга должен бытьmultipartResolver

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  <!--控制文件上传大小单位字节 默认没有大小限制 这里是2-->
  <property name="maxUploadSize" value="2097152"/>
</bean>

7.1.4, настроить контроллер загрузки

package cn.linstudy.controller;
	@Controller
	public class UploadController {
	// Spring 容器存在 ServletContext 类型的对象,所以定义好 ServletContext 类型字段贴@Autowired 注解即可获取到
	@Autowired
	private ServletContext servletContext;
	@RequestMapping("/upload")
	public ModelAndView upload(Part pic) throws Exception {
		System.out.println(pic.getContentType()); // 文件类型
		System.out.println(pic.getName()); // 文件参数名
		System.out.println(pic.getSize()); // 文件大小
		System.out.println(pic.getInputStream()); // 文件输入流
		// FileCopyUtils.copy(in, out),一个 Spring 提供的拷贝方法
		// 获取项目 webapp 目录下 uploadDir 目录的绝对路径
		System.out.println(servletContext.getRealPath("/uploadDir"));
		return null;
	}
}

7.2, загрузка файла

Загрузка файла:将服务器上的文件下载到当前用户访问的计算机的过程称之为文件下载

7.2.1 Контроллер разработки

При загрузке информация заголовка ответа должна быть установлена, чтобы указать, как файл сохраняется.Кроме того, контроллер для загрузки файла не может иметь возвращаемого значения, что означает, что ответ используется только для загрузки информации о файле`

	/**
     * 测试文件下载
     * @param fileName 要下载文件名
     * @return
     */
    @RequestMapping("download")
    public String download(String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException {
        //获取下载服务器上文件的绝对路径
        String realPath = request.getSession().getServletContext().getRealPath("/down");
        //根据文件名获取服务上指定文件
        FileInputStream is = new FileInputStream(new File(realPath, fileName));
        //获取响应对象设置响应头信息
        response.setHeader("content-disposition","attachment;fileName="+ URLEncoder.encode(fileName,"UTF-8"));
        ServletOutputStream os = response.getOutputStream();
        IOUtils.copy(is,os);
        IOUtils.closeQuietly(is);
        IOUtils.closeQuietly(os);
        return null;
    }