Spring4MVC(二)视图解析器,国际化,类型转换,数据格式化,静态资源,表单标签,ResponseEntity文件下载

1、视图和视图解析器

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

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

       对于最终究竟采取何种视图对象对模型数据进行渲染,处理器并不关心,处理器工作重点聚焦在生产模型数据的工作上,从而实现 MVC 的充分解耦。

1.1 视图

视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户。

为了实现视图模型和具体实现技术的解耦,Spring 在org.springframework.web.servlet 包中定义了一个高度抽象的 View接口:

视图对象由视图解析器负责实例化;由于视图是无状态的,所以他们不会有线程安全的问题

常用的视图实现类
大类视图类型说明
URL资源视图InternalResourceView将JSP或其他资源封装成一个视图,是InternalResourceViewResolver默认使用的视图实现类
JstlView如果jsp文件中使用了JSTL国际化标签的功能,则需要使用该视图类
文档视图AbstractExcelViewExcel文档视图的抽象类,该视图基于POI构造Excel文档
AbstractPdfViewPDF文档视图的抽象类,该视图基于iText构造PDF文档
报表视图ConfigurableJsperReportsView几个使用JsperReports报表技术的视图
JsperReportsCsvView
JsperReportsMultiFormatView
JsperReportsHtmlView
JsperReportsPdfView
JsperReportsXlsView
JSON视图MappingJacksonJsonView将模型数据通过JackSon开源框架的ObjectMapper以Json方式输出

1.2 视图解析器

       SpringMVC 为逻辑视图名的解析提供了不同的策略,可以在 Spring WEB 上下文中配置一种或多种解析策略,并
指定他们之间的先后顺序。每一种映射策略对应一个具体的视图解析器实现类。

       视图解析器的作用比较单一:将逻辑视图解析为一个具体的视图对象。

       所有的视图解析器都必须实现 ViewResolver 接口:

常用的视图解析器实现类
大类视图类型说明
解析为Bean的名字BeanNameViewResolver将逻辑视图名解析为一个Bean,Bean的id等于逻辑视图名
解析为URL文件InternalResourceViewResolver将视图名解析为一个URL文件,一般用该解析器将视图名映射为一个保存在WEB-INF目录下的程序文件(如JSP)
JsperReportsViewResolverJsperReports是一个基于Java的开源报表工具,该解析器将视图名解析为报表文件对应的URL
模板文件视图FreeMarkerViewResolver解析为FreeMarker模板技术的模板文件
VelocityViewResolver解析为Velocity模板技术的模板文件
VelocityLayoutViewResolver

       可以选择一种视图解析器或混用多种视图解析器,每个视图解析器都实现了 Ordered 接口并开放出一个 order 属性,可以通过 order 属性指定解析器的优先顺序,order 越小优先级越高

       SpringMVC 会按视图解析器顺序的优先顺序对逻辑视图名进行解析,直到解析成功并返回视图对象,否则将抛出ServletException 异常。

1.2.1 InternalResourceViewResolver

     JSP 是最常见的视图技术,可以使用InternalResourceViewResolver 作为视图解析器,他的配置如下:

 <!-- 配置视图解析器: 如何把 handler 方法返回值解析为实际的物理视图 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

1.2.2 JSTL的使用

       若项目中使用了 JSTL,则 SpringMVC 会自动把视图由InternalResourceView 转为 JstlView(需要导入 jstl.jar和standard.jar)
       若使用 JSTL 的 fmt 标签则需要在 SpringMVC 的配置文件中配置国际化资源文件

1、导入jar包

2、在src下面创建三个国际化文件

i18n.properties:

i18n.username=Username
i18n.password=Password

i18n_zh_CN.properties:

i18n.username=用户名
i18n.password=密码

i18n_en_US.properties:

i18n.username=Username
i18n.password=Password

3、在springmvc.xml中配置国际化资源文件

<!--配置国际化资源文件-->
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename" value="i18n"/>
    </bean>

4、jsp页面使用fmt标签

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--导入fmt国际化标签--%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
  <head>
    <title>成功页面</title>
  </head>
  <body>
  <br/>
  <fmt:message key="i18n.username"/>
  <br/>
  <fmt:message key="i18n.password"/>
</html>

1.2.3 mvc:view-controller

       上面从index.jsp跳转到success.jsp页面,都是经过了Handler进行转发的(因为success.jsp页面在WEB-INF下面,无法直接访问的),若希望直接响应通过 SpringMVC 渲染的页面,可以使用 <mvc:view-controller> 标签实现:

<!--直接响应页面的配置,而无需再经过Handler的方法-->
    <mvc:view-controller path="success" view-name="success"/>

此时,就可以在浏览器直接访问success路径,也会跳转到success.jsp页面。

上面的配置会有一个问题:此时之前的那个<a>标签的href跳转都会报404错误了,要想解决这个问题,需要配置

<mvc:annotation-driven>:
<mvc:annotation-driven></mvc:annotation-driven>

1.3 Excel 视图

       若希望使用Excel 展示数据列表,仅需要扩展 SpringMVC 提供的 AbstractExcelView AbstractJExcelView 即可。实现 buildExcelDocument() 方法,在方法中使用模型数据对象构建 Excel 文档就可以了。

       AbstractExcelView 基于 POI API,而AbstractJExcelView 是基于 JExcelAPI 的。

       视图对象需要配置 IOC 容器中的一个 Bean,使用BeanNameViewResolver 作为视图解析器即可。

       若希望直接在浏览器中直接下载Excel文档,则可以设置响应头 Content-Disposition 的值为attachment;filename=xxx.xls

1.4 自定义根据名字解析的解析器

1.4.1 自定义视图

package com.springmvc;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.View;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.Map;

@Component("helloView")//把该视图实现类交给spring管理
public class HelloView implements View {
    @Override
    public String getContentType() {
        return "text/html";
    }

    @Override
    public void render(Map<String, ?> map, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        httpServletResponse.getWriter().println("hello view , time:"+new Date());
    }
}

1.4.2 配置根据视图名称解析的解析器

<!--配置一个根据视图名字解析视图的解析器,
        order属性值越小越优先执行,
        InternalResourceViewResolver默认是order是Integer的最大值-->
    <bean id="beanNameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver">
        <property name="order" value="100"/>
    </bean>

1.4.3 测试:

@RequestMapping("testHelloView")
    public String testHelloView(){
        System.out.println("testHelloView...");
        return "helloView";
    }
<br/><br/>
  <a href="springmvc/testHelloView">testHelloView</a>

 

2、重定向

       一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理;如果返回的字符串中带 forward: redirect: 前缀
时,SpringMVC 会对他们进行特殊处理:将 forward:redirect: 当成指示符,其后的字符串作为 URL 来处理。
       redirect:success.jsp:会完成一个到 success.jsp 的重定向的操作
       forward:success.jsp:会完成一个到 success.jsp 的转发操作

3、Spring 的表单标签

       通过 SpringMVC 的表单标签可以实现将模型数据中的属性和 HTML 表单元素相绑定,以实现表单数据更便捷编辑和表单值的回显。

使用SpringMVC的表单标签,需要引入:

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

3.1 form 标签

       一般情况下,通过 GET 请求获取表单页面,而通过POST 请求提交表单页面,因此获取表单页面和提交表单
页面的 URL 是相同的。只要满足该最佳条件的契约,<form:form> 标签就无需通过 action 属性指定表单提交的 URL

       可以通过 modelAttribute 属性指定绑定的模型属性,若没有指定该属性,则默认从 request 域对象中读取command 的表单 bean,如果该属性值也不存在,则会发生错误。

3.2 其他表单标签

SpringMVC提供了多个表单组件标签;

1、<form:input/>、<form:select/> 等,用以绑定表单字段的属性值,它们的共有属性如下:
       path:表单字段,对应 html 元素的 name 属性,支持级联属性
       htmlEscape:是否对表单值的 HTML 特殊字符进行转换,默认值 为 true
       cssClass:表单组件对应的 CSS – 样式类名
       cssErrorClass:表单组件的数据存在错误时,采取的 CSS – 样式

2、form:input、form:password、form:hidden、form:textarea :对应 HTML 表单的 text、password、hidden、textarea
标签

3、form:radiobutton:单选框组件标签,当表单 bean 对应的属性值和 value 值相等时,单选框被选中。

4、form:radiobuttons:单选框组标签,用于构造多个单选框,属性如下:
       items:可以是一个 List、String[] 或 Map
       itemValue:指定 radio 的 value 值。可以是集合中 bean 的一个属性值
       itemLabel:指定 radio 的 label值
       delimiter:多个单选框可以通过 delimiter 指定分隔符

5、form:checkbox:•复选框组件。用于构造单个复选框

6、form:checkboxs:用于构造多个复选框。使用方式同form:radiobuttons 标签

7、form:select:用于构造下拉框组件。使用方式同form:radiobuttons 标签

8、form:option:下拉框选项组件标签。使用方式同form:radiobuttons 标签

9、form:errors:显示表单组件或数据校验所对应的错误
       <form:errors path= “ *” /> :显示表单所有的错误 –
       <form:errors path= “ user*” /> :显示所有以 user 为前缀的属性对应的错误
       <form:errors path= “ username” /> :显示特定表单对象属性的错误

 

4、处理静态资源

优雅的 REST 风格的资源URL 不希望带 .html 或 .do 等后缀;

若将 DispatcherServlet 请求映射配置为 /,则 Spring MVC 将捕获WEB 容器的所有请求,包括静态资源的请求, SpringMVC 会将他们当成一个普通请求处理,因找不到对应处理器将导致错误。

可以在 SpringMVC 的配置文件中配置 <mvc:default-servlet-handler/> 的方式解决静态资源的问题:

       <mvc:default-servlet-handler/> 将在 SpringMVC 上下文中定义一个DefaultServletHttpRequestHandler,它会对进入 DispatcherServlet 的请求进行筛查,如果发现是没有经过映射的请求,就将该请求交由 WEB 应用服务器默认的 Servlet 处理,如果不是静态资源的请求,才由DispatcherServlet 继续处理。

       一般 WEB 应用服务器默认的 Servlet 的名称都是 default。若所使用的WEB 服务器的默认 Servlet 名称不是 default,则需要通过 default-servlet-name 属性显式指定。

<!--处理静态资源-->
    <mvc:default-servlet-handler default-servlet-name="default"></mvc:default-servlet-handler>

5、数据绑定流程

       1. Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创建 DataBinder 实例对象

       2. DataBinder 调用装配在 Spring MVC 上下文中的ConversionService 组件进行数据类型转换、数据格式化工作。将 Servlet 中的请求信息填充到入参对象中

       3. 调用 Validator 组件对已经绑定了请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果BindingData 对象

       4. Spring MVC 抽取 BindingResult 中的入参对象和校验错误对象,将它们赋给处理方法的响应入参。

Spring MVC 通过反射机制对目标处理方法进行解析,将请求消息绑定到处理方法的入参中。数据绑定的核心部件是DataBinder,运行机制如下:

6、数据转换

Spring MVC 上下文中内建了很多转换器,可完成大多数 Java 类型的转换工作。

ConversionService converters =
java.lang.Boolean -> java.lang.String : –
org.springframework.core.convert.support.ObjectToStringConverter@f874ca
java.lang.Character -> java.lang.Number : CharacterToNumberFactory@f004c9 –
java.lang.Character -> java.lang.String : ObjectToStringConverter@68a961 –
java.lang.Enum -> java.lang.String : EnumToStringConverter@12f060a –
java.lang.Number -> java.lang.Character : NumberToCharacterConverter@1482ac5 –
java.lang.Number -> java.lang.Number : NumberToNumberConverterFactory@126c6f –
java.lang.Number -> java.lang.String : ObjectToStringConverter@14888e8 –
java.lang.String -> java.lang.Boolean : StringToBooleanConverter@1ca6626 –
java.lang.String -> java.lang.Character : StringToCharacterConverter@1143800 –
java.lang.String -> java.lang.Enum : StringToEnumConverterFactory@1bba86e –
java.lang.String -> java.lang.Number : StringToNumberConverterFactory@18d2c12 –
java.lang.String -> java.util.Locale : StringToLocaleConverter@3598e1 –
java.lang.String -> java.util.Properties : StringToPropertiesConverter@c90828 –
java.lang.String -> java.util.UUID : StringToUUIDConverter@a42f23 –
java.util.Locale -> java.lang.String : ObjectToStringConverter@c7e20a –
java.util.Properties -> java.lang.String : PropertiesToStringConverter@367a7f –
java.util.UUID -> java.lang.String : ObjectToStringConverter@112b07f

6.1 自定义类型转换器

       ConversionService 是 Spring 类型转换体系的核心接口。

       可以利用 ConversionServiceFactoryBean 在 Spring 的 IOC容器中定义一个 ConversionService, Spring 将自动识别出IOC 容器中的 ConversionService,并在 Bean 属性配置及Spring MVC 处理方法入参绑定等场合使用它进行数据的转换

       可通过 ConversionServiceFactoryBeanconverters 属性注册自定义的类型转换器

       Spring 定义了 3 种类型的转换器接口,实现任意一个转换 器接口都可以作为自定义转换器注册到ConversionServiceFactroyBean 中:
       1、Converter<S,T>:将 S 类型对象转为 T 类型对象

       2、ConverterFactory:将相同系列多个 “同质” Converter 封装在一起。如果希望将一种类型的对象转换为另一种类型及其子类的对象(例如将 String 转换为 Number 及 Number 子类(Integer、Long、Double 等)对象)可使用该转换器工厂类

       3、GenericConverter:会根据源类对象及目标类对象所在的宿主类中的上下文信息进行类型转换

6.1.1 自定义类型转换器类

需求:自定义个类型转换器,把类似于:101-lisi-23这样的字符串,转成一个User对象。

package com.springmvc;

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

@Component//交给Spring管理
public class UserConverter implements Converter<String, User> {
    @Override
    public User convert(String source) {
        if(!StringUtils.isEmpty(source)){
            String[] values = source.split("-");
            if(values.length>0){
                Integer id = Integer.parseInt(values[0]);
                String name = values[1];
                Integer age = Integer.parseInt(values[2]);

                User user = new User();
                user.setId(id);
                user.setName(name);
                user.setAge(age);
                System.out.println("User:"+user);
                return user;
            }
        }
        return null;
    }
}

6.1.2 配置自定义类型转换器

<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <list>
                <!--自定义的类型转换器-->
                <bean class="com.springmvc.UserConverter"/>
            </list>
        </property>
    </bean>

<mvc:annotation-driven conversion-service= “conversionService”/> 会将自定义的 ConversionService 注册到Spring MVC 的上下文中

6.1.3 测试

1、页面通过form表单提交一串字符串

<form action="springmvc/testConvert" method="post">
    <input type="text" name="user"/>
    <input type="submit" value="submit">
  </form>

2、后台方法接收

@RequestMapping("testConvert")
    public String testConvert(@RequestParam("user") User user){
        System.out.println("接受的User:"+user);
        return "helloView";
    }

3、测试

启动,在输入框输入:1001-lisi-33,点击submit提交,后台打印如下:

User:User{id=1001, name='lisi', age='33', department=null}
接受的User:User{id=1001, name='lisi', age='33', department=null}

7、<mvc:annotation-driven/>详解

<mvc:annotation-driven /> 会自动注册RequestMappingHandlerMappingRequestMappingHandlerAdapterExceptionHandlerExceptionResolver 三个bean
还将提供以下支持:
       支持使用 ConversionService 实例对表单参数进行类型转换 
       支持使用 @NumberFormat 注解、@DateTimeFormat 注解完成数据类型的格式化
       支持使用 @Valid 注解对 JavaBean 实例进行 JSR 303 验证 
       支持使用 @RequestBody @ResponseBody 注解

8、@InitBinder

       由 @InitBinder 标识的方法,可以对 WebDataBinder 对象进行初始化。WebDataBinder 是 DataBinder 的子类,用
于完成由表单字段到 JavaBean 属性的绑定

       @InitBinder方法不能有返回值,它必须声明为void。

       @InitBinder方法的参数通常是是 WebDataBinder

9、数据格式化

       对属性对象的输入/输出进行格式化,从其本质上讲依然属于 “类型转换” 的范畴。

       Spring 在格式化模块中定义了一个实现ConversionService 接口的FormattingConversionService 实现类,该实现类扩展了 GenericConversionService,因此它既具有类型转换的功能,又具有格式化的功能。

       FormattingConversionService 拥有一个FormattingConversionServiceFactroyBean 工厂类,后者用于在 Spring 上下文中构造前者

       FormattingConversionServiceFactroyBean 内部已经注册了:

              1、NumberFormatAnnotationFormatterFactroy:支持对数字类型的属性使用 @NumberFormat 注解

              2、JodaDateTimeFormatAnnotationFormatterFactroy:支持对日期类型的属性使用 @DateTimeFormat 注解

       装配了 FormattingConversionServiceFactroyBean 后,就可以在 Spring MVC 入参绑定及模型数据输出时使用注解驱动
了。<mvc:annotation-driven/> 默认创建的ConversionService 实例为FormattingConversionServiceFactroyBean。

所以使用步骤:1、配置文件添加配置:<mvc:annotation-driven/>  2、在属性上使用注解:@NumberFormat等。

9.1 日期格式化@DateTimeFormat

@DateTimeFormat 注解可对java.util.Date、java.util.Calendar、java.long.Long 时间类型的属性字段进行标注:

       pattern 属性:类型为字符串。指定解析/格式化字段数据的模式, 如:”yyyy-MM-dd hh:mm:ss”
       iso 属性:类型为 DateTimeFormat.ISO。指定解析/格式化字段数据 的ISO模式,包括四种:ISO.NONE(不使用) -- 默
认、ISO.DATE(yyyy-MM-dd) 、ISO.TIME(hh:mm:ss.SSSZ)、ISO.DATE_TIME(yyyy-MM-dd hh:mm:ss.SSSZ)
       style 属性:字符串类型。通过样式指定日期时间的格式,由两位字符组成,第一位表示日期的格式,第二位表示时间的格式:S:短日期/时间格式、M:中日期/时间格式、L:长日期/时间格式、F:完整日期/时间格式、- 忽略日期或时间格式

9.2 数值格式化@NumberFormat

@NumberFormat 可对类似数字类型的属性进行标注,它拥有两个互斥的属性:
       style:类型为 NumberFormat.Style。用于指定样式类型,包括三种:Style.NUMBER(正常数字类型)、Style.CURRENCY(货币类型)、 Style.PERCENT(百分数类型)
       pattern:类型为 String,自定义样式,如patter="#,###";

10、处理JSON

10.1 返回和接收JSON

1、加入jackson的三个jar包:jackson-annotations-2.1.5.jar    jackson-core-2.1.5.jar   jackson-databind-2.1.5.jar

2、编写目标方法,使其返回 JSON 对应的对象或集合

3、如果是返回,就在方法上添加 @ResponseBody 注解,如果是接收json,就在方法入参前面加上@RequestBody。

10.2 处理JSON的原理:HttpMessageConverter<T>

       HttpMessageConverter<T> 是 Spring3.0 新添加的一个接口,负责将请求信息转换为一个对象(类型为 T),将对象(
类型为 T)输出为响应信息。

       HttpMessageConverter<T>接口定义的方法:

              Boolean canRead(Class<?> clazz,MediaType  mediaType):指定转换器可以读取的对象类型,即转换器是否可将请求信息转换为 clazz 类型的对象,同时指定支持 MIME 类型(text/html,applaiction/json等)

              Boolean canWrite(Class<?> clazz,MediaType mediaType):指定转换器是否可将 clazz 类型的对象写到响应流中,响应流支持的媒体类型在MediaType 中定义。

              LIst<MediaType> getSupportMediaTypes():该转换器支持的媒体类型。

              T read(Class<? extends T> clazz,HttpInputMessage inputMessage– ):将请求信息流转换为 T 类型的对象。

              void write(T t,MediaType contnetType,HttpOutputMessgae outputMessage):将T类型的对象写到响应流中,同时指定相应的媒体类型为 contentType。

HttpMessageConverter<T> 的实现类:

       DispatcherServlet 默认装配RequestMappingHandlerAdapter ,而RequestMappingHandlerAdapter 默认装配如下HttpMessageConverter:

       加入 jackson jar 包后, RequestMappingHandlerAdapter 装配的 HttpMessageConverter 如下:

10.3 HttpMessageConverter<T> 是使用

       使用 HttpMessageConverter<T> 将请求信息转化并绑定到处理方法的入参中或将响应结果转为对应类型的响应信息,Spring 提供了两种途径:
              —使用 @RequestBody / @ResponseBody – 对处理方法进行标注

              —使用 HttpEntity<T> / ResponseEntity<T> 作为处理方法的入参或返回值

       当控制器处理方法使用到 @RequestBody/@ResponseBody 或 HttpEntity<T>/ResponseEntity<T> 时, Spring 首先根据请求头或响应头的Accept 属性选择匹配的 HttpMessageConverter,进而根据参数类型或泛型类型的过滤得到匹配的 HttpMessageConverter,若找不到可用的HttpMessageConverter 将报错。

       @RequestBody 和 @ResponseBody 不需要成对出现

10.4 HttpEntity、ResponseEntity 示例

10.4.1 HttpEntity示例

使用HttpEntity参数获取请求头和请求体

<!-- post请求,默认的请求参数都会以name=value&name=value的形式进行拼接,然后发送给服务器。 -->
  <form action="${pageContext.request.contextPath }/springmvc/testHttpEntity" method="post">
    用户名:<input type="text" name="username" /><br/>
    密码:<input type="password" name="password" /><br/>
    <input type="submit" />
  </form>

控制器方法:

@RequestMapping("testHttpEntity")
    public String testHttpEntity(HttpEntity<String> httpEntity){
        System.out.println("请求头:" + httpEntity.getHeaders());
        System.out.println("请求体:" + httpEntity.getBody());
        return SUCCESS;
    }

打印效果:

请求头:{host=[localhost:8080], connection=[keep-alive], content-length=[25], cache-control=[max-age=0], origin=[http://localhost:8080], upgrade-insecure-requests=[1], content-type=[application/x-www-form-urlencoded], user-agent=[Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36], accept=[text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8], referer=[http://localhost:8080/Spring4MVC_01_war_exploded/], accept-encoding=[gzip, deflate, br], accept-language=[zh-CN,zh;q=0.9], cookie=[JSESSIONID=6BDC934074C10324ADF0E0682F52800B]}
请求体:username=aaa&password=111

 

10.4.2 ResponseEntity 示例

//测试下载文件的效果
    @RequestMapping("testResponseEntity")
    public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
        ServletContext servletContext = session.getServletContext();
        InputStream inputStream = servletContext.getResourceAsStream("/file/aaa.txt");
        byte[] body = new byte[inputStream.available()];
        inputStream.read(body);//把数据读取到body中

        //获取需要下载的文件的数据类型
	String mimeType = servletContext .getMimeType("/file/aaa.txt");
        HttpHeaders headers = new HttpHeaders();
        // 添加响应头,告诉客户端我回去的数据类型是什么
	httpHeaders.add("Content-Type", mimeType);
        headers.add("Content-Disposition", "attachment;filename=abc.txt");

        HttpStatus statusCode = HttpStatus.OK;
        // 第一个参数是你要返回的数据--我们要实现文件下载,就需要把下载的文件字节内容都放body中
	// 第二个参数是 响应头
	// 第三个参数是你要返回的响应状态码和响应 状态描述 符
        ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(body, headers, statusCode);
        return responseEntity;
    }
<a href="springmvc/testResponseEntity">testResponseEntity</a>

11、国际化

关于国际化的需求和对应的基本解决方案:

1、在页面上能够根据浏览器的语言设置的情况对文本(不是指内容),时间和数值进行本地化处理;

       解决办法:使用JSTL的fmt标签

2、可以在Bean(控制器controller)中获取国际化资源文件 Locale 对应的消息

       解决办法:在Bean(控制器controller)中注入 ResourceBundleMessageSource 的实例,使用其对应的 getMessage 方法即可

3、可以通过超链接切换 Locale,而不再依赖于浏览器的语言设置

       解决办法:配置 LocalResolver 和LocaleChangeInterceptor

11.1 在页面上能够根据浏览器的语言设置的情况对文本(不是指内容),时间和数值进行本地化处理

11.1.1 创建国家化文件

       若项目中使用了 JSTL,则 SpringMVC 会自动把视图由InternalResourceView 转为 JstlView(需要导入 jstl.jar和standard.jar)
       若使用 JSTL 的 fmt 标签则需要在 SpringMVC 的配置文件中配置国际化资源文件

1、导入jar包

2、在src下面创建三个国际化文件

i18n.properties:

i18n.username=Username
i18n.password=Password

i18n_zh_CN.properties:

i18n.username=用户名
i18n.password=密码

i18n_en_US.properties:

i18n.username=Username
i18n.password=Password

3、jsp页面使用fmt标签

i18n.jsp:该页面展示用户名,可以不经过控制器,直接跳转到i18n2.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--导入fmt国际化标签--%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
  <head>
    <title>i18n</title>
  </head>
  <body>
    <br/>
    <fmt:message key="i18n.username"/>
    <br/>
    <a href="i18n2">I18N2 PAGE</a>
  </body>
</html>

i18n2.jsp:该页面展示密码,可以不经过控制器,直接跳转到i18n.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--导入fmt国际化标签--%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
  <head>
    <title>i18n</title>
  </head>
  <body>
    <br/>
    <fmt:message key="i18n.password"/>
    <br/>
    <a href="i18n">I18N PAGE</a>
  </body>
</html>

4、在springmvc.xml中配置国际化资源文件

<!--配置国际化资源文件-->
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename" value="i18n"/>
    </bean>

<!--直接响应页面的配置,而无需再经过Handler的方法-->
    <mvc:view-controller path="i18n" view-name="i18n"/>
    <mvc:view-controller path="i18n2" view-name="i18n2"/>

启动工程,可以直接浏览器访问:http://localhost:8080/Spring4MVC_01_war_exploded/i18n,切换浏览器语言可以看到效果

11.2 在Bean(控制器controller)中获取国际化资源文件 Locale 对应的消息

11.2.1 国家化文件还是上面的

11.2.2 配置如下

<!--配置国际化资源文件-->
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename" value="i18n"/>
    </bean>

    <!--直接响应页面的配置,而无需再经过Handler的方法-->
    <!--<mvc:view-controller path="i18n" view-name="i18n"/>-->
    <!--<mvc:view-controller path="i18n2" view-name="i18n2"/>-->

11.2.3 修改i18n.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--导入fmt国际化标签--%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
  <head>
    <title>i18n</title>
  </head>
  <body>
    <br/>
    <fmt:message key="i18n.username"/>
    <fmt:message key="i18n.password"/>
    <br/>
  </body>
</html>

11.2.4 首页添加超链接

<a href="springmvc/i18n">I18n Page</a>

11.2.5 处理器方法

需要注入:ResourceBundleMessageSource 

@Autowired
    private ResourceBundleMessageSource messageSource;

    @RequestMapping("i18n")
    public String testI18n(Locale locale){
        String username = messageSource.getMessage("i18n.username", null, locale);
        System.out.println("username:"+username);
        String password = messageSource.getMessage("i18n.password", null, locale);
        System.out.println("password:"+password);
        return "i18n";
    }

测试控制台能根据浏览器的语言设置显示对应的语言信息。

11.3 通过超链接切换 Locale,而不再依赖于浏览器的语言设置

       SpringMVC 还允许装配一个动态更改本地化类型的拦截器,这样通过指定一个请求参数就可以控制单个请求的本地化类型。

11.3.1 本地化解析器和本地化拦截器

       AcceptHeaderLocaleResolver:根据 HTTP 请求头的Accept-Language 参数确定本地化类型,如果没有显式定义本地化解析器, SpringMVC 使用该解析器。

       CookieLocaleResolver:根据指定的 Cookie 值确定本地化类型

       SessionLocaleResolver:根据 Session 中特定的属性确定本地化类型

       LocaleChangeInterceptor:从请求参数中获取本次请求对应的本地化类型。

SessionLocaleResolver & LocaleChangeInterceptor 工作原理:

 

11.3.2 配置

<!-- 配置 SessionLocalResolver -->
    <bean id="localeResolver"
          class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>

    <mvc:interceptors>
        <!-- 配置 LocaleChanceInterceptor -->
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
    </mvc:interceptors>

11.3.3 首页添加超链接添加Locale

<br/><br/>
  <a href="springmvc/i18n?locale=zh_CH">点击切换为中文</a>
  <br/><br/>
  <a href="springmvc/i18n?locale=en_US">点击切换为英文</a>

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值