springmvc <mvc:annotation-driven/><mvc:default-servlet-handler/>区别 ssm整合

2023-11-11

文章目录


推荐学习在C语言中文网上springmvc

概述:

简单理解mvc就是做网站开发,前后端交互

概念和核心

- 概念:SpringMVC是Spring框架中的一个分支,是基于Java实现MVC的轻量级Web框架
- 核心:Spring的web框架围绕DispatcherServlet [ 调度Servlet ] 设计的。

什么是MVC

- Model:数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和 服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。
- View:负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。
- Controller(调度员): 接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作。
- 最常用的MVC:(Model)Bean +(view) Jsp +(Controller) Servlet

MVC 设计不仅限于 Java Web 应用,还包括许多应用,比如前端、PHP、.NET 等语言。之所以那么做的根本原因在于解耦各个模块。

MVC 是 Model、View 和 Controller 的缩写,分别代表 Web 应用程序中的 3 种职责。

  • 模型:用于存储数据以及处理用户请求的业务逻辑。
  • 视图:向控制器提交数据,显示模型中的数据。
  • 控制器:根据视图提出的请求判断将请求和数据交给哪个模型处理,将处理后的有关结果交给哪个视图更新显示。

基于 Servlet 的 MVC 模式的具体实现如下。

  • 模型:一个或多个 JavaBean 对象,用于存储数据(实体模型,由 JavaBean 类创建)和处理业务逻辑(业务模型,由一般的 Java 类创建)。
  • 视图:一个或多个 JSP 页面,向控制器提交数据和为模型提供数据显示,JSP 页面主要使用 HTML 标记和 JavaBean 标记来显示数据。
  • 控制器:一个或多个 Servlet 对象,根据视图提交的请求进行控制,即将请求转发给处理业务逻辑的 JavaBean,并将处理结果存放到实体模型 JavaBean 中,输出给视图显示。

基于 Servlet 的 MVC 模式的流程如图 1 所示。

JSP中的MVC模式

springmvc第一个程序搭建

先到依赖

dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

idea搭建项目

先创建maven项目

右击点击红箭头

在这里插入图片描述

里面就有想要的web引用

在这里插入图片描述

eclipse搭建

创建maven时候直接修改

在这里插入图片描述

在spirngmvc.xml配置文件写上这个

<context:component-scan base-package="com.xiong.controller"/>

web.xml写上servlet配置

<!-- 配置 DispatcherServlet:springmvc核心-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <!-- 关联一个springmvc一个reoures配置文件-->
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!--设置执行级别-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--拦截的规则 -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!--匹配的规则 -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

注意:拦截规则

url参与匹配的是哪部分?

答:匹配的时候并不是用完整的url进行匹配,而是用完整的url减去当前应用对应上下文之后的部分来 进行匹配。比如,访问localhost:8080/webdemo/login,应用上下文是localhost:8080/webdemo,参 与匹配的是/login

有四种匹配规则

  • 精确匹配

    中配置的项与url相应部分完全一致才能匹配上

    例如

在这里插入图片描述

当在浏览器中输入如下几种url时,都会被匹配到该servlet

在这里插入图片描述

  • 路劲匹配/*

    • 全部拦截,包括jsp,图片,css等,不建议用
    • 请求可以走到action中,但转到jsp会被再次拦截,不能访问到jsp

    以/字符开头,并以/*结尾的字段串用于路劲匹配。

    例如

在这里插入图片描述

路劲以/user/开始,后面的路劲可以任意。比如下面的url都会被匹配:

在这里插入图片描述

在这里插入图片描述

它涵盖的范围最大,它可以匹配所有的request请求。

  • 扩展名匹配 *.xx

    • 拦截特定结尾的请求

      以*.开头的字符串被用于扩展名匹配。

      在这里插入图片描述

      则任何扩展名为jsp或action的url请求都会匹配,比如下面的url都会被匹配

    在这里插入图片描述

  • 缺省匹配 /

    拦截所有,但不包括jsp和css等静态文件,即对静态资源放行

    缺省匹配的写法是唯一的,就是<url-pattern>/</url-pattern>

    当其他方式都匹配不到时候,就会使用默认的servlet。

匹配优先级

精确匹配>路劲匹配>扩展匹配>缺省匹配

路劲匹配和扩展名匹配不能同时使用

流程和原理

执行流程

在这里插入图片描述

1、 用户发送请求至前端控制器DispatcherServlet

2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。

3、 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并 返回给DispatcherServlet。

4、 DispatcherServlet通过HandlerAdapter处理器适配器调用处理器

5、 执行处理器(Controller,也叫后端控制器)。

6、 Controller执行完成返回ModelAndView

7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet

8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器

9、 ViewReslover解析后返回具体View

10、 DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。

11、 DispatcherServlet响应用户

组件说明

DispatcherServlet:前端控制器

用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由 它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。

HandlerMapping:处理器映射器

HandlerMapping负责根据用户请求url找到Handler即处理器,springmvc提供了不同的映射器实现不 同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

Handler:处理器

Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。

由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。

HandlAdapter:处理器适配器

通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的 处理器进行执行。

你有一个类接口,但是这个接口不太符合你的预期,如果要用他就需要在他的源码上进行一些修 改,这时你可以做一个适配器,在不修改原来这个接口源码的情况下,在适配器上对这个接口进 行运用,使得适配器符合你的规范。

适配器模式(Adapter Pattern),把一个类的接口变换成客户端所期待的另一种接口, Adapter模式使原本因接口不匹配(或者不兼容)而无法在一起工作的两个类能够在一起工作。 又称为转换器模式、变压器模式、包装(Wrapper)器模式(把已有的一些类包装起来,使之能 有满足需要的接口)。

例如内存卡-读卡器-笔记本,内存卡就是这个类接口,读卡器就是适配器,笔记本是系统,笔记本 通过读卡器使用内存卡。

springmvc的handler(Controller,HttpRequestHandler,Servlet等)有多种实现方式,例如 继承Controller的,基于注解控制器方式的,HttpRequestHandler方式的。由于实现方式不一 样,调用方式就不确定了。

如果正常编写调用,就需要使用多个if else判断instance of,再添加实现方式,就需要修改源 码,不符合对扩展开放,对修改关闭原则。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LuCIGzgh-1604658526488)(E:\保存\QQ截图20201105145503.jpg)]

ViewResolver:视图解析器

View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即 具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。

View:视图

springmvc框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、pdfView等。 我们最常用的视图就是jsp。

说明:在springmvc的各个组件中,处理器映射器、处理器适配器、视图解析器称为springmvc的三大 组件

需要用户开发的组件有handler、view

演变过程

继承controller接口,注册bean到容器。相当于原始servlet的写法

在这里插入图片描述

按理说,三大组件都需要我们配置,但是前端控制器给我们提供了默认的,所以可以不配在上面的基础上,配置处理器适配器和处理器映射器

在这里插入图片描述

注解开发

在这里插入图片描述

<bean id="dao" class="xiongxiong.dao.UserDaoMysql"></bean><!--扫描单个包进行托管容器-->

手动配置处理器映射器和处理器适配器很麻烦,可以用一个标签代替

<mvc:annotation-driven/>

访问静态资源

css,js,图片等

<mvc:default-servlet-handler/> 访问全部静态资源
<mvc:resources />
<mvc:resources mapping="resources/**/"   location="/resources/"/>  这个指定的默认静态资源路径

一般静态资源会在tomat默认的servlet中加载
在这里插入图片描述

在这里插入图片描述

四个重要标签的作用和区别

<context:annotation-config/>
<context:component-scan/>
两个区别

源码:

Activates various annotations to be detected in bean classes: Spring's @Required and
@Autowired, as well as JSR 250's @PostConstruct, @PreDestroy and @Resource (if available),
JAX-WS's @WebServiceRef (if available), EJB 3's @EJB (if available), and JPA's
@PersistenceContext and @PersistenceUnit (if available). Alternatively, you may
choose to activate the individual BeanPostProcessors for those annotations.

Note: This tag does not activate processing of Spring's @Transactional or EJB 3's
@TransactionAttribute annotation. Consider the use of the <tx:annotation-driven>
tag for that purpose.

See javadoc for org.springframework.context.annotation.AnnotationConfigApplicationContext
for information on code-based alternatives to bootstrapping annotation-driven support.

翻译:

激活要在bean类中检测到的各种注释:Spring的@Required和
@Autowired,以及JSR 250的@PostConstruct, @PreDestroy和@Resource(如果有的话),
JAX-WS的@WebServiceRef(如果可用)、EJB 3的@EJB(如果可用)和JPA的
@PersistenceContext和@PersistenceUnit(如果可用)。或者,你可能
选择为这些注释激活单独的beanpostprocessor。
注意:此标记不激活Spring的@Transactional或EJB 3的处理
@TransactionAttribute注释。请考虑<tx:注释驱动的>的使用
标签的目的。
参见javadoc获得org.springframework.context. context. annotationconfigapplicationcontext
有关引导注释驱动支持的基于代码的替代方案的信息。

源码:

Scans the classpath for annotated components that will be auto-registered as
	Spring beans. By default, the Spring-provided @Component, @Repository, @Service,
	@Controller, @RestController, @ControllerAdvice, and @Configuration stereotypes
	will be detected.

	Note: This tag implies the effects of the 'annotation-config' tag, activating @Required,
	@Autowired, @PostConstruct, @PreDestroy, @Resource, @PersistenceContext and @PersistenceUnit
	annotations in the component classes, which is usually desired for autodetected components
	(without external configuration). Turn off the 'annotation-config' attribute to deactivate
	this default behavior, for example in order to use custom BeanPostProcessor definitions
	for handling those annotations.

	Note: You may use placeholders in package paths, but only resolved against system
	properties (analogous to resource paths). A component scan results in new bean definitions
	being registered; Spring's PropertySourcesPlaceholderConfigurer will apply to those bean
	definitions just like to regular bean definitions, but it won't apply to the component
	scan settings themselves.

	See javadoc for org.springframework.context.annotation.ComponentScan for information
	on code-based alternatives to bootstrapping component-scanning.

翻译:

扫描类路径,寻找将被自动注册为的带注释的组件
Spring bean。默认情况下,spring提供的@Component、@Repository、@Service、
@Controller、@RestController、@ControllerAdvice和@Configuration构造型
将被检测到。
注意:此标记暗示了“注释-config”标记的效果,即激活@Required,
@Autowired, @PostConstruct, @PreDestroy, @Resource, @PersistenceContext和@PersistenceUnit
组件类中的注释,这通常是自动检测组件所需要的
(没有外部配置)。关闭“注释-配置”属性以禁用
此默认行为,例如为了使用自定义BeanPostProcessor定义
来处理这些注释。
注意:您可以在包路径中使用占位符,但只能针对system进行解析
属性(类似于资源路径)。组件扫描会产生新的bean定义
被注册;Spring的PropertySourcesPlaceholderConfigurer将应用于这些bean
定义就像常规的bean定义一样,但它不适用于组件
扫描设置。
有关org.springframework.context.annotation,请参阅javadoc。ComponentScan信息
基于代码的组件扫描引导方法。

context:component-scan/ 使用只要打一个context:component-scan/就可以 因为context:component-scan/已经包含在里面啦

<mvc:annotation-driven/>
开启两个处理器相关。。本质是servlet
<mvc:default-servlet-handler/>
走默认的servlet,也就是服务器提供的servlet。本质是servlet

springmvc 是5以上的

源码:

在这里插入图片描述

在这里插入图片描述

自己大概网上查了一下

自己用大白话说一下:

<mvc:default-servlet-handler/> <mvc:annotation-driven/>都没有

我自己看了源码 然后我仔细看了一下 都没有话就会随机找一个进行运行

<mvc:default-servlet-handler/>有它 <mvc:annotation-driven/>没有它

一个有一个没有时所注册的三个bean都不能处理@RequestMapping注解,因此无法找到相应的Controller,进而无法进行访问路径的映射

<mvc:default-servlet-handler/> <mvc:annotation-driven/>两个都有

两个都有的话 他们会找会注册一个RequestMappingHandlerAdapter的bean容器里面进行处理

所以一般使用的话都是两个一起使用

转发和重定向

转发:客户浏览器发送 http 请求,Web 服务器接受此请求,调用内部的一个方法在容器内部完成 请求处理和转发动作,将目标资源发送给客户;在这里转发的路径必须是同一个 Web 容器下的 URL,其不能转向到其他的 Web 路径上,中间传递的是自己的容器内的 request。

在客户浏览器的地址栏中显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了 转发的。转发行为是浏览器只做了一次访问请求。

注意:看到的是一次的路径;request可以带过去

forward:/xxx

重定向:客户浏览器发送 http 请求,Web 服务器接受后发送 302 状态码响应及对应新的 location 给客户浏览器,客户浏览器发现是 302 响应,则自动再发送一个新的 http 请求,请求 URL 是新 的 location 地址,服务器根据此请求寻找资源并发送给客户。

在这里 location 可以重定向到任意 URL,既然是浏览器重新发出了请求,那么就没有什么 request 传递的概念了。在客户浏览器的地址栏中显示的是其重定向的路径,客户可以观察到地址 的变化。重定向行为是浏览器做了至少两次的访问请求。

注意:浏览器看到两次地址,request带不过去

redirect:/xxx
或者
redirect:/ip: 是可以访问其他项目的
@RequestMapping("/index")
public class IndexController {
    @RequestMapping("/login")
    public String login() {
        //转发到一个请求方法(同一个控制器类可以省略/index/)
        return "forward:/index/isLogin";
    }
    @RequestMapping("/isLogin")
    public String isLogin() {
        //重定向到一个请求方法
        return "redirect:/index/isRegister";
    }
    @RequestMapping("/isRegister")
    public String isRegister() {
        //转发到一个视图
        return "register";
    }
}
request.getAttribute()和request.getParameter()的区别

1,getAttribute表示从request范围取得设置的属性,必须要先setAttribute设置属性,才能通过getAttribute来取得,设置与取得的为Object对象类型

2,getParameter表示接收参数,参数为页面提交的参数,包括:表单提交的参数、URL重写(就是xxx?id=1中的id)传的参数等,因此这个并没有设置参数的方法(没有setParameter),而且接收参数返回的不是Object,而是String类型

注解

restful风格(了解)表述性状态转移

一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

xx/xx/xx

如:https://api.example.com/v1/zoos

GET(SELECT):从服务器取出资源(一项或多项)。

POST(CREATE):在服务器新建一个资源。

PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。

PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。

DELETE(DELETE):从服务器删除资源。

之前在java写法是

在这里插入图片描述

但是为了简写是

在这里插入图片描述

RequestMapping注解包括

在这里插入图片描述

@PutMapping等于@RequestMapping 两个用法是一样的 但是在restful风格这样写比较简单不用写很长的代码

前端要是和后端代码匹配的话写这样的代码

因为浏览器form表单只支持GET与POST请求,而DELETE、PUT等method并不支持,spring3.0添加了一个过滤器,可以将这些请求转换为标准的http方法,使得支持GET、POST、PUT与DELETE请求。

<!-- 浏览器不支持put,delete等method,由该filter将/xxx?_method=delete转换为标准的http delete方法 -->
    <!--配置成浏览器可以识别的格式-->
    <!-- 配置HiddenHttpMethodFilter-->
    <filter>
        <filter-name>httpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>

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

然后在页面写这个代码

<input type="hidden" name="_method" value="delect"/>
这里的value也可以写成GET或者POST只要是RequestMapping注解里面的

要是使用restful风格
这里我用springboot演示

先配置yml文件
在这里插入图片描述
要是删除就是写成delete要是修改写成put
在这里插入图片描述
就可以使用了

前端传值的话

<a th:href="@{/book/toUpdateBook/} + ${book.bookID}">修改</a> 差不多就是这样写的
<tr th:each="p: ${page}">
					<td th:text="${p.id}"></td>
					<td th:text="${p.name}"></td>
					<td><a th:href="@{/categories/{id}(id=${p.id})}">编辑</a></td>
					<td><a class="delete" th:href="@{/categories/{id}(id=${p.id})}">删除</a></td>
				</tr>

@RequestMapping

  • 可以加在类上,也可以加在方法上
  • 可以使用路径符号
    • * 表示任何路径
    • ?表示单个字符的占位
    • ** 表示不管中间有几层目录
  • 占位符 {xxx} xxx代表你输入的id或者是name 比如在配合restful风格使用

@PathVariable

spring3.0的一个新功能:接收请求路径中占位符的值

@RequestParam

  • name或者value 前后端名字不匹配 作为是前后端名字匹配
  • defaultValue 作用是给默认值 一般会在分页中使用
  • required 等于true false 默认是 false 要是改成true 必须要前端传值不然会报错

绑定单个请求参数值

请求方法中可以出现的参数类型

javax.servlet.ServletRequest或javax.servlet.http.HttpServletRequest

javax.servlet.ServletResponse或java.servlet.http.HttpServletResponse

javax.servlet.http.HttpSession

org.springframework.web.context.request.WebRequest或

org.springframework.web.context.request.NativeWebRequest

java.util.Locale

java.io.InputStream或java.io.Reader

java.io.OutputStream或java.io.Writer

java.security.Principal

HttpEntity<?>

java.util.Map org.springframework.ui.Model

org.springframework.ui.ModelMap

org.springframework.web.servlet.mvc.support.RedirectAttributes

org.springframework.validation.Errors

org.springframework.validation.BindingResult

org.springframework.web.bind.support.SessionStatus

org.springframework.web.util.UriComponentsBuilder

@PathVariable、@MatrixVariable注解

@RequestParam、@RequestHeader、@RequestBody、@RequestPart注解

如果需要在方法中用到以上对象,可以将其写在参数列表中,spring会创建对象并传递给方法

SpringMVC请求处理方法可返回的类型

org.springframework.web.portlet.ModelAndView

org.springframework.ui.Model

java.util.Map

org.springframework.web.servlet.View

java.lang.String

HttpEntity或ResponseEntity

java.util.concurrent.Callable

org.springframework.web.context.request.async.DeferredResult

void

返回值类型

.ModelAndView

String

void

Object

上传下载

  1. 导包:commons-fileupload

  2. 页面:post,enctype=“multipart/form-data”

    <form method="post" action="test" enctype="multipart/form-data"><%--enctype="multipart/form-data"是把文件装换成二级制流闯进去的--%>
      <input type="file" name="file">
      <%--file 一个文件只能选择上传一个--%>
      <input type="submit" value="tijiao">
    
      </form>
    
  3. spring.xml中配置文件上传的那个类

<!-- 配置MultipartResolver,用于上传文件,使用spring的CommonsMultipartResolver-->
    <bean id="multipartResolver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="10000000" />
        <property name="defaultEncoding" value="UTF-8" />
    </bean>
  1. MultipartFile

  2. 假如我们上传的名字一样的话就会把前面一样所以我们一般会创建一个随机名字加原本的名字但是随机名字也有冲突我们一般都有UUID创建随机数

    具体使用可以看:https://blog.csdn.net/wuzhangxiong123/article/details/109532412

@RequestMapping("test")
    public String test1(MultipartFile file, HttpServletRequest request) throws IOException {
        String oldname=file.getOriginalFilename();
        String newname= UUID.randomUUID().toString()+oldname;
        String path="d:/aaaaaaa";
        File director=new File(path);
        if (!director.exists()) {
            director.mkdirs();
        }
        File target=new File(path,newname);
        file.transferTo(target);
        //        System.out.println(file.getOriginalFilename());//getOriginalFilename获取文件名字
        return "login";
    }

多文件上传

有两种

1.是多创建几个同样的方法 但是名字不一样

2.把他写成一个数组接收起来 但是名字一定要一样

public String test1(MultipartFile[] file, HttpServletRequest request) throws IOException {
        for (MultipartFile multipartFile : file) {
            System.out.println(multipartFile.getOriginalFilename());
            //在里面写和上面一样的代码
        }
 

文件下载

id name lujing
1 期中考试题.doc d:/aaa/78979879.doc

实现文件下载有以下两种方法:

  • 通过超链接实现下载。

  • 利用程序编码实现下载。

    通过超链接实现下载固然简单,但暴露了下载文件的真实位置,并且只能下载存放在 Web 应用程序所在的目录下的文件。

    利用程序编码实现下载可以增加安全访问控制,还可以从任意位置提供下载的数据,可以将文件存放到 Web 应用程序以外的目录中,也可以将文件保存到数据库中。

代码如下:

编写控制器类

@Controller
public class FileDownController {
    // 得到一个用来记录日志的对象,在打印时标记打印的是哪个类的信息
    private static final Log logger = LogFactory
            .getLog(FileDownController.class);
    /**
     * 显示要下载的文件
     */
    @RequestMapping("showDownFiles")
    public String show(HttpServletRequest request, Model model) {
        // 从 workspace\.metadata\.plugins\org.eclipse.wst.server.core\
        // tmp0\wtpwebapps\springMVCDemo11\下载
        String realpath = request.getServletContext()
                .getRealPath("uploadfiles");
        File dir = new File(realpath);
        File files[] = dir.listFiles();
        // 获取该目录下的所有文件名
        ArrayList<String> fileName = new ArrayList<String>();
        for (int i = 0; i < files.length; i++) {
            fileName.add(files[i].getName());
        }
        model.addAttribute("files", fileName);
        return "showDownFiles";
    }
    /**
     * 执行下载
     */
    @RequestMapping("down")
    public String down(@RequestParam String filename,
            HttpServletRequest request, HttpServletResponse response) {
        String aFilePath = null; // 要下载的文件路径
        FileInputStream in = null; // 输入流
        ServletOutputStream out = null; // 输出流
        try {
            // 从workspace\.metadata\.plugins\org.eclipse.wst.server.core\
            // tmp0\wtpwebapps下载
            aFilePath = request.getServletContext().getRealPath("uploadfiles");
            // 设置下载文件使用的报头
            response.setHeader("Content-Type", "application/x-msdownload");
            response.setHeader("Content-Disposition", "attachment; filename="
                    + toUTF8String(filename));
            // 读入文件
            in = new FileInputStream(aFilePath + "\\" + filename);
            // 得到响应对象的输出流,用于向客户端输出二进制数据
            out = response.getOutputStream();
            out.flush();
            int aRead = 0;
            byte b[] = new byte[1024];
            while ((aRead = in.read(b)) != -1 & in != null) {
                out.write(b, 0, aRead);
            }
            out.flush();
            in.close();
            out.close();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        logger.info("下载成功");
        return null;
    }
    /**
     * 下载保存时中文文件名的字符编码转换方法
     */
    public String toUTF8String(String str) {
        StringBuffer sb = new StringBuffer();
        int len = str.length();
        for (int i = 0; i < len; i++) {
            // 取出字符中的每个字符
            char c = str.charAt(i);
            // Unicode码值为0~255时,不做处理
            if (c >= 0 && c <= 255) {
                sb.append(c);
            } else { // 转换 UTF-8 编码
                byte b[];
                try {
                    b = Character.toString(c).getBytes("UTF-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    b = null;
                }
                // 转换为%HH的字符串形式
                for (int j = 0; j < b.length; j++) {
                    int k = b[j];
                    if (k < 0) {
                        k &= 255;
                    }
                    sb.append("%" + Integer.toHexString(k).toUpperCase());
                }
            }
        }
        return sb.toString();
    }
}

创建文件列表页面

<table>
        <tr>
            <td>被下载的文件名</td>
        </tr>
        <!--遍历 model中的 files-->
        <c:forEach items="${files}" var="filename">
            <tr>
                <td>
                    <a href="${pageContext.request.contextPath }/down?filename=${filename}">${filename}</a>
                </td>
            </tr>
        </c:forEach>
    </table>

拦截器

在开发一个网站时可能有这样的需求:某些页面只希望几个特定的用户浏览。对于这样的访问权限控制,应该如何实现呢?拦截器就可以实现上述需求。在 Struts 2 框架中,拦截器是其重要的组成部分,Spring MVC 框架也提供了拦截器功能。

Spring MVC 的拦截器(Interceptor)与 Java Servlet 的过滤器(Filter)类似,它主要用于拦截用户的请求并做相应的处理,通常应用在权限验证、记录请求信息的日志、判断用户是否登录等功能上。

先继承

public class Myinter implements HandlerInterceptor {
    //执行后台方法之前执行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    request.getRequestURI();//只能拿到mvc_war_exploded/test路劲
    request.getRequestURL();//拿的全部路劲
        return false;
    //这里的返回值要是false的话不接着往下执行 要是true的话往下继续执行
    }
    //后台方法完成执行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }
    //页面渲染完成后
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

写配置

<!--拦截器配置-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--全部拦截-->
            <mvc:mapping path="/**"/>
           <!-- <mvc:exclude-mapping path=""/> 不包括谁-->
            <bean class="com.xiong.inter.Myinter"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

异常处理

继承HandlerExceptionResolver重写

public class myexe implements HandlerExceptionResolver {
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //ex.printStackTrace();//打印的报错信息
        ModelAndView mav=new ModelAndView();
        mav.setViewName("error");
        return mav;
    }
}

添加容器里面

<!--加载异常到容器-->
    <bean class="com.xiong.exce.myexe"></bean>
    <!-- 或者扫描全部包-->
    <context:component-scan base-package="com.xiong.controller"/>

在这里插入图片描述

继承异常处理类

public class exse extends Exception{
    String msssage;

    public String getMsssage() {
        return msssage;
    }

    public void setMsssage(String msssage) {
        this.msssage = msssage;
    }
}

哪里会报错try一下

在这里插入图片描述

然后带着返回信息返回页面

在这里插入图片描述

创建 BaseController 类,并在该类中使用 @ExceptionHandler 注解声明异常处理方法

public class BaseController {
    /** 基于@ExceptionHandler异常处理 */
    @ExceptionHandler
    public String exception(HttpServletRequest request, Exception ex) {
        request.setAttribute("ex", ex);
        // 根据不同错误转向不同页面,即异常与view的对应关系
        if (ex instanceof SQLException) {
            return "sql-error";
        } else if (ex instanceof MyException) {
            return "my-error";
        } else {
            return "error";
        }
    }
}

将所有需要异常处理的 Controller 都继承 BaseController 类

@Controller
public class TestExceptionController extends BaseController{
    ...
}

然后在springmvc配置扫描全部

<context:component-scan base-package="controller" />

json处理

json是什么

JSON(JavaScript Object Notation, JS 对象标记)是一种轻量级的数据交换格式。与 XML 一样,JSON 也是基于纯文本的数据格式。它有对象结构和数组结构两种数据结构

格式是{“name”:“vale”}要是还有的话那逗号隔开(,)

要是数组的话加[ “Porsche”, “BMW”, “Volvo” ]

springmvc处理json

加上一个@ResponseBody

作用:@ResponseBody的作用其实是将java对象转为json格式的数据。

@responseBody注解的作用是将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据。
注意:在使用此注解之后不会再走视图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。

jackson 默认

fastjson 阿里的 (jsonbject , .parse )

1.@ResponseBody:返回的数据 不走视图解析器,返回josn数据

2.加入json依赖,new对象,封装,返回字符串

3.mvc配置,就可以直接返回对象啦

添加jackson依赖

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

第一种方式做

在这里插入图片描述

第二种方式在xml文件添加依赖

    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
        </mvc:message-converters>
    </mvc:annotation-driven>

然后

在这里插入图片描述

ajax的使用

在这里插入图片描述
在这里插入图片描述

第一个常规 第二个是简单

ssm整合

这里有mybatis和spring整合把他拿过来然后在把springmvc配置和依赖导进来就好

https://blog.csdn.net/wuzhangxiong123/article/details/109336408

springmvc,mybatis和spring整合

依赖文件

<!--springmvc依赖-->
<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.9.RELEASE</version>
    </dependency>
<dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.3</version>
    </dependency>
    <!-- mybatis和spring -->
  <dependency>
			<groupId>com.mchange</groupId>
			<artifactId>c3p0</artifactId>
			<version>0.9.5.5</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>2.0.5</version>
		</dependency>
		<!--这里使用jdbc方式连接,所以导入jdbc包。如果需要用连接池,就导入对应连接池的包 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>5.2.9.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>5.2.9.RELEASE</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.9.6</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.5.1</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.47</version>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.16.20</version>
			<scope>provided</scope>
		</dependency>

spirng配置文件 注意:spirng一般也可以不用要 直接放到springmvc中

<?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:p="http://www.springframework.org/schema/p"
	xmlns:c="http://www.springframework.org/schema/c"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.2.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
	<context:component-scan base-package="xiongmao.qn.pojo"></context:component-scan>
	<context:annotation-config />
	<!-- 加载数据库配置项 -->
	<context:property-placeholder location="classpath:db.properties" />
	<!-- 配置数据源,这里用的是jdbc的方式。数据源可以替换为任意的数据库连接池,只需要导入对应的jar 包即可 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${jdbc.driver}" />
		<property name="jdbcUrl" value="${jdbc.url}" />
		<property name="user" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>


	<!-- 配置SqlSessionFactory -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 
	<!-- 配置mybatis核心配置文件 -->
		<!-- <property name="configLocation" value="classpath:mybatis.xml" />  -->
	<!-- 配置数据源 -->	
		<property name="dataSource" ref="dataSource" />
		<property name="mapperLocations" value="classpath:xiongmao/qn/mapper/*.xml" />
	</bean>
	<!-- <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />
	</bean> -->
	
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<property name="basePackage" value="xiongmao.qn.mapper" />
	</bean>
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"></property>
	</bean>
  	<!-- 配置事务的增强 -->
	<tx:advice id="txAdvice"
		transaction-manager="transactionManager">
			<tx:attributes> 
			<!-- isolation="DEFAULT" 隔离级别
		 	propagation="REQUIRED" 传播行为 
	 		read-only="false" 只读 
	 		timeout="-1" 过期时间 
	 		rollback-for="" -Exception 
	 		no-rollback-for="" +Exception 
	 		-->
			<tx:method name="transfer" propagation="REQUIRED" />
		</tx:attributes>
	</tx:advice>
	
</beans>

mybatis配置文件 注意:mybatis一般也可以不用要 直接放到springmvc中

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!-- 环境配置标签 -->
<!-- <settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings> -->
<typeAliases>
<package name="xiongmao.qn.pojo"/>
</typeAliases>
	<!--将mapper文件加入到配置文件中 -->
	<mappers>
		<!-- <mapper resource="Test.xml"/> -->
		<package name="xiongmao.qn.mapper"/>
	</mappers>
</configuration>

springmvc配置文件

<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.2.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
    <context:annotation-config></context:annotation-config>
    <context:component-scan base-package="com.xiong.controller"/>
    <!--处理器映射器-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
    <!--处理器适配器-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="suffix" value=".jsp"></property>
        <property name="prefix" value="/WEB-INF/"></property>
    </bean>
    <!--<mvc:annotation-driven/>
    <mvc:default-servlet-handler/>-->
    <!-- 配置MultipartResolver,用于上传文件,使用spring的CommonsMultipartResolver-->
    <bean id="multipartResolver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="10000000" />
        <property name="defaultEncoding" value="UTF-8" />
    </bean>
    <!--拦截器配置-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--全部拦截-->
            <mvc:mapping path="/**"/>
           <!-- <mvc:exclude-mapping path=""/> 不包括谁-->
            <bean class="com.xiong.inter.Myinter"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
    <!--加载异常到容器--><!-- 或者扫描全部包-->
    <bean class="com.xiong.exce.myexe"></bean>
</beans>

springmvc配置的web.xml文件配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
<!-- 配置 DispatcherServlet:springmvc核心-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <!-- 关联一个springmvc一个reoures配置文件-->
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!--设置执行级别-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--拦截的规则 -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!--匹配规则  -->
        <!--/:只匹配请求,不包括所有的.jsp
        /*:匹配所有的请求,包括jsp页面 -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!--<servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/tologin.jsp</url-pattern>
        <url-pattern>/insert.jsp</url-pattern>
    </servlet-mapping>-->
    <!-- 浏览器不支持put,delete等method,由该filter将/xxx?_method=delete转换为标准的http delete方法 -->
    <!--配置成浏览器可以识别的格式-->
    <!-- 配置HiddenHttpMethodFilter-->
    <filter>
        <filter-name>httpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>httpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

数据库连接配置jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/sss?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

国际化(了解)

自己写的国际化程序

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

国际化是商业软件系统的一个基本要求,因为当今的软件系统需要面对全球的浏览者。国际化的目的就是根据用户的语言环境的不同向用户输出与之相应的页面,以示友好。

程序国际化已成为 Web 应用的基本要求。随着网络的发展,大部分 Web 站点面对的已经不再是本地或者本国的浏览者,而是来自全世界各国、各地区的浏览者,因此国际化成为了 Web 应用不可或缺的一部分。

Java 国际化的思想是将程序中的信息放在资源文件中,程序根据支持的国家及语言环境读取相应的资源文件。资源文件是 key-value 对,每个资源文件中的 key 是不变的,但 value 随不同国家/语言变化。

Java 程序的国际化主要通过两个类来完成。

1)java.util.Locale

用于提供本地信息,通常称它为语言环境。不同的语言、不同的国家和地区采用不同的 Locale 对象来表示。

2)java.util.ResourceBundle

该类称为资源包,包含了特定于语言环境的资源对象。当程序需要一个特定于语言环境的资源时(例如字符串资源),程序可以从适合当前用户语言环境的资源包中加载它。采用这种方式可以编写独立于用户语言环境的程序代码,而与特定语言环境相关的信息则通过资源包来提供。

为了实现 Java 程序的国际化,必须事先提供程序所需要的资源文件。资源文件的内容由很多 key-value 对组成,其中 key 是程序使用的部分,而 value 是程序界面的显示。

资源文件的命名可以有如下 3 种形式:

  • baseName.properties。
  • baseName_language.properties。
  • baseName_language_country.properties。

baseName 是资源文件的基本名称,由用户自由定义,但是 language 和 country 必须为 Java 所支持的语言和国家/地区代码。例如:

  • 中国大陆:baseName_zh_CN.properties。
  • 美国:baseName_en_US.properties。

Java 中的资源文件只支持 ISO-8859-1 编码格式字符,直接编写中文会出现乱码。用户可以使用 Java 命令 native2ascii.exe 解决资源文件的中文乱码问题,使用 MyEclipse 编写资源属性文件,在保存资源文件时 MyEclipse 自动执行 native2ascii.exe 命令,因此在 MyEclipse 中资源文件不会出现中文乱码问题。

Java 支持的语言和国家

java.util.Locale类的常用构造方法如下:

public Locale(String language);
public Locale(String language, String country)。

其中,language 表示语言,它的取值是由小写的两个字母组成的语言代码。country 表示国家或地区,它的取值是由大写的两个字母组成的国家或地区代码。

实际上,Java 并不能支持所有国家和语言,如果需要获取 Java 所支持的语言和国家,开发者可以通过调用 Locale 类的 getAvailableLocales 方法获取,该方法返回一个 Locale 数组,该数组中包含了 Java 所支持的语言和国家。

下面的 Java 程序简单示范了如何获取 Java 所支持的国家和语言:

import java.util.Locale;public class Test {    public static void main(String[] args) {        // 返回Java所支持的语言和国家的数组        Locale locales[] = Locale.getAvailableLocales();        // 遍历数组元素,依次获取所支持的国家和语言        for (int i = 0; i < locales.length; i++) {            // 打印出所支持的国家和语言            System.out.println(locales[i].getDisplayCountry() + "="                    + locales[i].getCountry() + ""                    + locales[i].getDisplayLanguage() + "="                    + locales[i].getLanguage());        }    }}

Java 程序的国际化

假设有如下简单 Java 程序:

public class TestI18N {    public static void main(String[] args) {        System.out.println("我要向把不同国家的人民问好:您好!");    }}

为了让该程序支持国际化,需要将“我要向不同国家的人民问好:您好!”对应不同语言环境的字符串,定义在不同的资源文件中。

在 Web 应用的 src 目录下新建文件 messageResource_zh_CN.properties 和 messageResource_ en_US.properties。然后给资源文件 messageResource_zh_CN.properties 添加“hello=我要向不同国家的人民问好:您好!”内容,保存后可看到如图 1 所示的效果。

Unicode编码资源文件
图 1 Unicode 编码资源文件

图 1 显示的内容看似是很多乱码,实际上是 Unicode 编码文件内容。至此,资源文件 messageResource_zh_CN.properties 创建完成。

最后给资源文件 messageResource_en_US.properties 添加“hello=I want to say hello to all world!”内容。

现在将 TestI18N.java 程序修改成如下形式:

import java.util.Locale;import java.util.ResourceBundle;public class TestI18N {    public static void main(String[] args) {        // 取得系统默认的国家语言环境        Locale lc = Locale.getDefault();        // 根据国家语言环境加载资源文件        ResourceBundle rb = ResourceBundle.getBundle("messageResource", lc);        // 打印出从资源文件中取得的信息        System.out.println(rb.getString("hello"));    }}

上面程序中的打印语句打印的内容是从资源文件中读取的信息。如果在中文环境下运行程序,将打印“我要向不同国家的人民问好:您好!”。

如果在“控制面板”中将计算机的语言环境设置成美国,然后再次运行该程序,将打印“I want to say hello to all world!”。需要注意的是,如果程序找不到对应国家/语言的资源文件,系统该怎么办?

假设以简体中文环境为例,先搜索如下文件:

messageResource_zh_CN.properties

如果没有找到国家/语言都匹配的资源文件,再搜索语言匹配文件,即搜索如下文件:

messageResource_zh.properties

如果上面的文件还没有搜索到,则搜索 baseName 匹配的文件,即搜索如下文件:

messageResource.properties

如果上面 3 个文件都找不到,则系统将出现异常。

带占位符的国际化信息

在资源文件中消息文本可以带有参数,例如:

welcome={0},欢迎学习 Spring MVC

花括号中的数字是一个占位符,可以被动态的数据替换。在消息文本中占位符可以使用 0~9 的数字,也就是说消息文本的参数最多可以有 10 个。例如:

welcome={0},欢迎学习 Spring MVC,今天是星期{1}。

如果要替换消息文本中的占位符,可以使用 java.text.MessageFormat 类,该类提供了一个静态方法 format,用来格式化带参数的文本。format 方法的定义如下:

public static String format(String pattern,Object …arguments)

其中,pattern 字符串就是一个带占位符的字符串,消息文本中的数字占位符将按照方法参数的顺序(从第二个参数开始)被替换。

替换占位符的示例代码如下:

纯文本复制
import java.text.MessageFormat;import java.util.Locale;import java.util.ResourceBundle;public class TestFormat {    public static void main(String[] args) {        // 取得系统默认的国家语言环境        Locale lc = Locale.getDefault();        // 根据国家语言环境加载资源文件        ResourceBundle rb = ResourceBundle.getBundle("messageResource", lc);        // 从资源文件中取得的信息        String msg = rb.getString("welcome");        // 替换消息文本中的占位符,消息文本中的数字占位符将按照参数的顺序        // (从第二个参数开始)被替换,即“我”替换{0}、“5”替换{1}        String msgFor = MessageFormat.format(msg, "我", "5");        System.out.println(msgFor);    }}

Spring MVC 的国际化是建立在 Java 国际化的基础之上的,Spring MVC 框架的底层国际化与 Java 国际化是一致的,作为一个良好的 MVC 框架,Spring MVC 将 Java 国际化的功能进行了封装和简化,开发者使用起来会更加简单、快捷。

由《Java国际化概念和使用介绍》教程可知国际化和本地化应用程序时需要具备以下两个条件:

  • 将文本信息放到资源属性文件中。
  • 选择和读取正确位置的资源属性文件。

下面讲解第二个条件的实现。

Spring MVC加载资源属性文件

在 Spring MVC 中不能直接使用 ResourceBundle 加载资源属性文件,而是利用 bean(messageSource)告知 Spring MVC 框架要将资源属性文件放到哪里。示例代码如下:

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleM essageSource">    <property name="basenames">        <list>            <value>/WEB-INF/resource/messages</value>            <value>/WEB-INF/resource/labels</value>        </list>    </property></bean>

语言区域的选择

在 Spring MVC 中可以使用语言区域解析器 bean 选择语言区域,该 bean 有 3 个常见实现,即 AcceptHeaderLocaleResolver、SessionLocaleResolver 和 CookieLocaleResolver。

1)AcceptHeaderLocaleResolver

根据浏览器 Http Header 中的 accept-language 域设定(accept-language 域中一般包含了当前操作系统的语言设定,可通过 HttpServletRequest.getLocale 方法获得此域的内容)。

改变 Locale 是不支持的,即不能调用 LocaleResolver 接口的 setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale)方法设置 Locale。

2)SessionLocaleResolver

根据用户本次会话过程中的语言设定决定语言区域(例如用户进入首页时选择语言种类,则此次会话周期内统一使用该语言设定)。

3)CookieLocaleResolver

根据 Cookie 判定用户的语言设定(Cookie 中保存着用户前一次的语言设定参数)。

由上述分析可知,SessionLocaleResolver 实现比较方便用户选择喜欢的语言种类,教程中使用该方法进行国际化实现。

下面是使用 SessionLocaleResolver 实现的 bean 定义:

如果采用基于 SessionLocaleResolver 和 CookieLocaleResolver 的国际化实现,必须配置 LocaleChangeInterceptor 拦截器,示例代码如下:

mvc:interceptors

</mvc:interceptors>

使用 message 标签显示国际化信息

在 Spring MVC 框架中可以使用 Spring 的 message 标签在 JSP 页面中显示国际化消息。在使用 message 标签时需要在 JSP 页面的最前面使用 taglib 指令声明 spring 标签,代码如下:

<%@taglib prefix=“spring” uri=“http://www.springframework.org/tags”%>

message 标签有以下常用属性。

  • code:获得国际化消息的 key。
  • arguments:代表该标签的参数。如果替换消息中的占位符,示例代码为“<spring:message code=“third” arguments=“888,999” />”,third 对应的消息有两个占位符 {0} 和 {1}。
  • argumentSeparator:用来分隔该标签参数的字符,默认为逗号。
  • text:code 属性不存在,或指定的 key 无法获取消息时所显示的默认文本信息。

在许多成熟的商业软件系统中可以让用户自由切换语言,而不是修改浏览器的语言设置。一旦用户选择了自己需要使用的语言环境,整个系统的语言环境将一直是这种语言环境。

Spring MVC 也可以允许用户自行选择程序语言。本章通过 Web 应用 springMVCDemo09 演示用户自定义切换语言,在该应用中使用 SessionLocaleResolver 实现国际化,具体步骤如下:

1)创建应用

创建应用 springMVCDemo09,并导入 Spring MVC 相关的 JAR 包。

2)创建国际化资源文件

在 WEB-INF/resource 目录下创建中英文资源文件 messages_en_US.properties 和 messages_zh_CN.properties。

messages_en_US.properties 的内容如下:

first=first
second=second
third={0} third{1}
language.en=English
language.cn=Chinese

messages_zh_CN.properties 的内容如下:

first=\u7B2C\u4E00\u9875
second=\u7B2C\u4E8C\u9875
third={0} \u7B2C\u4E09\u9875 {1}
language.cn=\u4E2D\u6587
language.en=\u82F1\u6587

3)创建视图 JSP 文件

在 WEB-INF/jsp 目录下创建 3 个 JSP 文件,即 first.jsp、second.jsp 和 third.jsp。

first.jsp 的代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><%@taglib prefix="spring" uri="http://www.springframework.org/tags"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body>    <a href="${pageContext.request.contextPath }/i18nTest?locale=zh_ CN">        <spring:message code="language.cn" /> </a> --    <a href="${pageContext.request.contextPath }/i18nTest?locale=en_US">        <spring:message code="language.en" /> </a>    <br>    <br>    <spring:message code="first" />    <br>    <br>    <a href="${pageContext.request.contextPath }/my/second">    <spring:message code="second" /> </a></body></html>

second.jsp 的代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><%@taglib prefix="spring" uri="http://www.springframework.org/tags"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body>    <spring:message code="second"/><br><br>    <a href="${pageContext.request.contextPath }/my/third">        <spring:message code="third" arguments="888,999"/>    </a></body></html>

third.jsp 的代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><%@taglib prefix="spring" uri="http://www.springframework.org/tags"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body>    <spring:message code="third" arguments="888,999" />    <br>    <br>    <a href="${pageContext.request.contextPath }/my/first">        <spring:message code="first" />    </a></body></html>

4)创建控制器类

该应用有两个控制器类,一个是 I18NTestController 处理语言种类选择请求,一个是 MyController 进行页面导航。在 src 目录中创建一个名为 controller 的包,并在该包中创建这两个控制器类。

I18NTestController.java 的代码如下:

package controller;import java.util.Locale;import org.springframework.web.bind.annotation.RequestMapping;@Controllerpublic class I18NTestController {    @RequestMapping("/i18nTest")    /**     * locale接收请求参数locale值,并存储到session中     */    public String first(Locale locale) {        return "first";    }}

MyController 的代码如下:

package controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;@Controller@RequestMapping("/my")public class MyController {    @RequestMapping("/first")    public String first() {        return "first";    }    @RequestMapping("/second")    public String second() {        return "second";    }    @RequestMapping("/third")    public String third() {        return "third";    }}

5)创建配置文件

在 WEB-INF 目录下创建配置文件 springmvc-servlet.xml 和 web.xml。web.xml 的代码与 Spring MVC 简单应用的相同,这里不再赘述。springmvc-servlet.xml 的代码如下:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xmlns:mvc="http://www.springframework.org/schema/mvc"    xmlns:p="http://www.springframework.org/schema/p"     xmlns:context="http://www.springframework.org/schema/context"    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">    <!-- 使用扫描机制扫描包 -->    <context:component-scan base-package="controller" />    <!-- 配置视图解析器 -->    <bean        class="org.springframework.web.servlet.view.InternalResourceViewResolver">        <property name="prefix" value="/WEB-INF/jsp/" />        <property name="suffix" value=".jsp" />    </bean>    <!-- 国际化操作拦截器,如果采用基于Session/Cookie则必须配置 -->    <mvc:interceptors>        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />    </mvc:interceptors>    <!-- 存储区域设置信息 -->    <bean id="localeResolver"        class="org.springframework.web.servlet.i18n.SessionLocaleResolver">        <property name="defaultLocale" value="zh_CN"></property>    </bean>    <!-- 加载国际化资源文件 -->    <bean id="messageSource"        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">        <!-- <property name="basename" value="classpath:messages" /> -->        <property name="basename" value="/WEB-INF/resource/messages" />    </bean></beans>

6)发布应用并测试

首先将 springMVCDemo09 应用发布到 Tomcat 服务器并启动 Tomcat 服务器,然后通过地址“http://localhost:8080/springMVCDemo08/my/first”测试第一个页面,运行结果如图 1 所示。

中文环境下first.jsp的运行结果
图 1 中文环境下 first.jsp 的运行结果

单击图 1 中的“第二页”超链接,打开 second.jsp 页面,运行结果如图 2 所示。

中文环境下second.jsp的运行结果
图 2 中文环境下second.jsp的运行结果

单击图 2 中的“第三页”超链接,打开 third.jsp 页面,运行结果如图 3 所示。

中文环境下third.jsp的运行结果
图 3 中文环境下third.jsp的运行结果

单击图 1 中的“英文”超链接,打开英文环境下的 first.jsp 页面,运行结果如图 4 所示。

英文环境下first.jsp的运行结果
图 4 英文环境下 first.jsp 的运行结果

单击图 4 中的 second 超链接,打开英文环境下的 second.jsp 页面,运行结果如图 5 所示。

英文环境下second.jsp的运行结果
图 5 英文环境下 second.jsp 的运行结果

单击图 5 中的 third 超链接,打开英文环境下的 third.jsp 页面,运行结果如图 6 所示。

英文环境下third.jsp的运行结果
图 6 英文环境下 third.jsp 的运行结果

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

springmvc <mvc:annotation-driven/><mvc:default-servlet-handler/>区别 ssm整合 的相关文章

  • uniapp滚动加载 下拉刷新

    前言 在日常开发中 滚动加载和下拉刷新是非常常见的功能 页面数据过多时 需要滚动加载优化性能 本篇技术分享博客将介绍如何在uniapp中实现滚动加载和下拉刷新 预览 滚动加载 下拉刷新 一 滚动加载 滚动加载指的是当用户滑动页面到底部时 自
  • MYSQL--基础--09--备份还原常用命令

    MYSQL 基础 09 备份还原常用命令 1 数据库信息 数据库地址 127 0 0 1 数据库用户名 root 数据库密码 1234 数据库名称 test1 数据库名称 test2 数据库名称 test3 mysqldump目录 usr
  • syntax error near unexpected token in 解决方案

    目录 一 引言 二 问题解决 三 总结 一 引言 近来在使用 shell 脚本时 从服务器上把脚本文件拿下来 本地修改完之后上传至服务器 运行时出现了如下的错误信息 最终排查之后 发现是系统兼容性问题 现就解决方案做出说明 二 问题解决 首
  • Github建个人静态网页

    如何将个人静态网页搭建在Github上 前言 最近有不少人问我如何将个人网站搭建在Github上 由于不能一一回复 所以我就将过程写成一篇小教程 发在csdn上面 仅供参考 17岁以下的小朋友不需要在家长的陪同下阅读本文 使用工具 Goog
  • 如何看懂别人的项目代码

    1 先运行别人的demo 然后再去看文档 2 运行调试 新的 1 了解项目 要知道这个项目是用来干嘛的 有什么样的功能 2 获取源代码 3 运行 4 一定要亲自运行一下 玩一玩 看看都有什么功能 都能完成什么事情 要想对项目源码了解 首先必
  • 基于python的种子搜索网站,你懂得!

    该项目是基于python的web类库django开发的一套web网站 给师弟做的毕业设计 本人的研究方向是一项关于搜索的研究项目 在该项目中 笔者开发了一个简单版的搜索网站 实现了对数据库数据的检索和更新 通过开发该项目 笔者学习和巩固了p
  • css自适应布局,缩放保持图片比例

    场景一 适合商品类展示型布局 后台的数据呈现列表数据返回 窗口宽度变化 图片比例不变 假设我们的图片宽高固定比例16 9 效果图满屏 效果图缩放时 移动端 直接看代码 里面会注释详细说明 div class parentBox div cl
  • Matter Project 入门 – Matter开发环境设置

    如果您尚未在计算机上本地运行 Ubuntu 您将需要一个替代方案来开发 Matter 设备 你需要什么 用于构建 Matter 终端设备固件的 Linux 环境 我们将为这个项目使用 Ubuntu 21 10 服务器 但任何 Ubuntu
  • 软考之运筹学计算-车床问题

    软考之运筹学计算 车床问题 一 真题示例 二 题意分析 三 解答 一 真题示例 某车间需要用一台车床和一台铣床加工A B C D四个零件 每个零件都需要先用车床加工 再用铣床加工 车床与铣床加工每个零件所需的工时 包括加工前的准备时间以及加
  • AndroidStudio新建项目报错build failed

    AndroidStudio新建项目报错build failed 报错信息 org gradle initialization ReportedException org gradle internal exceptions Location
  • VC6提示番茄助手过期

    VC6提示番茄助手过期 无法打开 在控制面板中卸载即可
  • FlinkCDC第二部分-搭建Flink单机服务,ctrl就完事~

    Flink版本 1 16 环境 Linux CentOS 7 0 jdk1 8 基础文件 flink 1 16 2 bin scala 2 12 tgz flink connector jdbc 3 0 0 1 16 jar flink s
  • string字符插入及截取操作

    1 string满足 运算符的重载 可以理解为拼接 s s 3 加在末尾 s 4 s 加在头部 2 append函数 插入整个字符串s2 s1 append s2 插入s2部分 如第四个字符到第七个字符 s1 append s3 3 6 插
  • linux使用读写锁pthread_rwlock_t

    使用读写锁 配置读写锁的属性之后 即可初始化读写锁 以下函数用于初始化或销毁读写锁 锁定或解除锁定读写锁或尝试锁定读写锁 下表列出了本节中讨论的用来处理读写锁的函数 表 4 9 处理读写锁的例程 操作 相关函数说明 初始化读写锁 pthre
  • Liunx下使用docker搭建ftp服务

    1 检索最新镜像 docker search vsftpd 2 拉取FTP镜像 docker pull fauria vsftpd 3 查看本机ip ifconfig 4 运行并创建container 方法1 运行时创建用户名和密码 doc
  • 计算机是仿生学,一种基于人体仿生学的计算机键盘的制作方法

    本实用新型属于计算机键盘技术领域 具体涉及一种基于人体仿生学的计算机键盘 背景技术 键盘是最常用也是最主要的输入设备 通过键盘 可以将英文字母 数字和标点符号等输入到计算机中 从而向计算机发出命令和输入数据等 键盘 由一组按阵列方式装配在一
  • 什么是软件测试、生命周期、软件开发模型、测试模型

    目录 1 什么是软件测试 2 软件测试和软件软件开发的区别 3 软件测试 Testing 和软件调试 Debug 的区别 4 什么是需求 5 需求是测试人员开展软件测试工作的依据 6 测试人员如何深入了解需求 7 测试用例 Test Cas
  • mysql 导入超大sql文件

    mysql u root p 登录mysql命令 可以登陆mysql服务器使用source命令导入 会快很多 我这里导入500M 大概用了5分钟 1 liunx登陆mysql mysql u 用户名 p 数据库名 然后输入密码 登陆mysq
  • Blender 雕刻

    文章目录 简介 基本操作 进入雕刻 雕刻工作区 强度 笔刷 纹理 笔画 衰减 动态拓扑 动态拓扑属性 重构网格 物体数据属性重构网格 雕刻自带的重构网格 镜像 同一个模型的不同网格 对其中一个雕刻 不影响其他的网格 快捷键 笔刷 自由线 显
  • 知识图谱——机器大脑中的知识库

    Published by liuzy on July 6 2015 作者 刘知远 清华大学 整理 林颖 RPI 版权所有 转载请注明出处 知识就是力量 英 弗兰西斯 培根 1 什么是知识图谱 在互联网时代 搜索引擎是人们在线获取信息和知识的

随机推荐

  • 计算机2.0培训心得,信息2.0培训心得体会

    今年7月份学校召开了关于学校信息化教育的会议 由于刚接触 我们听得一头雾水 于是就在摸索中开始了我们的信息化2 0工程培训学习 由于我组的化学科目特殊性 除了选择基础的A1技术支持的学前分析和A3演示文稿设计与制作外 我们还选择了B6技术支
  • IDEA报错解决:Cannot resolve com.oracle:ojdbc7:12.1.0.2或‘com.oracle:ojdbc7:12.1.0.2‘ not found

    1 到oracle官网下载ojdbc7 jar 附博主的ojdbc7 jar包下载地址 也可进入我的资源中下载 存入本地 不要存入maven仓库 2 打开cmd 切换到ojdbc7 jar所在文件夹 3 执行命令mvn install in
  • Vue(五)——调试

    一 console输出到控制台 如果Vue项目中 使用了eslint loader 代码规范 空格 缩进 console等测试语句 的话 就没法使用console 一定需要使用console可以尝试关闭eslint loader 在vue
  • Spring 如何从 IoC 容器中获取对象?

    前情回顾 前面几篇文章主要分析了 Spring IoC 容器如何初始化 以及解析和注册我们定义的 bean 信息 其中 Spring 中的 IoC 容器 对 Spring 中的容器做了一个概述 Spring IoC 容器初始化 和 Spri
  • 碰到了version `GLIBC_2.27' not found错误

    碰到了version GLIBC 2 27 not found错误 我查了下 因为glibc是系统级底层软件 自己编译的可能会跟原来的不一致 会导致系统不兼容 结果我在 etc ld so conf里面添加了 opt glibc 2 27的
  • C++/C笔试面试题目大大的集合

    C C笔试面试题目大大的集合 2010 10 22 00 08 3742人阅读 评论 0 收藏 举报 面试 c string 编译器 null 设计模式 1 const 有什么用途 请至少说明两种 答 1 可以定义 const 常量 2 c
  • 基于PHP的简单微博系统

    一 项目介绍 基于PHP的简单微博系统 php mysql apache开发 适合新手练习 可搭建在phpstudy下 有完整的sql文件和配置文件 三分钟快速部署 二 主要功能 1 注册 登录微博 2 个人中心 个人信息修改 查看我的关注
  • 【官方文档】《暗黑世界GM管理后台系统》部署+功能说明

    欢迎来到9秒 www 9miao com 暗黑三国管理后台说明文档 一 功能描述 该后台共分为三大部分 服务器管理 单服数据统计和扶持账号管理 1 服务器管理 根据管理后台数据库中填写的服务器信息 后面会讲到如何填写要管理的服务器的信息到数
  • golang http请求时设置代理ip

    在http Client中自定义Transport 设置Proxy即可 目前网上存在很多代理ip网站 本人也写过一些代理ip网址的爬取 见 GitHub 如果需要代理验证 那么如下进行设置 否则直接设置为url Parse http inp
  • CSS设计指南(第3版)》

    CSS设计指南 第3版 基本信息 原书名 Stylin with CSS a designer s guide 作者 英 Charles Wyke Smith 译者 李松峰 丛书名 图灵程序设计丛书 出版社 人民邮电出版社 ISBN 978
  • ATL与COM之间的关系、ATL的特点与基本使用方法

    ATL Active Template Library活动模板库 是一种微软程序库 支持利用C 语言编写ASP代码以及其它ActiveX程序 通过活动模板库 可以建立COM组件 然后通过ASP页面中的脚本对COM对象进行调用 这种COM组件
  • [R语言]R包的安装&帮助获取

    本文主要参考 Paul Teetor R语言经典实例 一书 在R语言中 包含的包中有各种应用函数 1 install packages packagename 安装R包 library package name 载入包 对于base包可省略
  • CentOS7安装oracle19c

    教程 https zhuanlan zhihu com p 571737575 CentOS7安装oracle19c教程 https zhuanlan zhihu com p 571737575 一 准备工作 1创建 oracle 用户 以
  • 关于指针

    指针的一些基础知识 1 指针的定义 数据在内存中的地址也称为指针 如果一个变量存储了一份数据的指针 我们就称它为指针变量 在C语言中 允许用一个变量来存放指针 这种变量称为指针变量 指针变量的值就是某份数据的地址 这样的一份数据可以是数组
  • 利用docker部署TF深度学习模型(附件文件较大,并无上传。部署参考步骤即可)

    一 介绍 docker Docker 是一个开源的应用容器引擎 基于 Go 语言 并遵从 Apache2 0 协议开源 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级 可移植的容器中 然后发布到任何流行的 Linux 机器上
  • 预编译过程中的相关知识点

    1 文件包含顺序 在头文件中 1 包含自定义头文件 2 包含第三方库的头文件 3 包含标准库头文件 在源文件中 1 包含该源文件对应的头文件 2 包含自定义头文件 3 包含第三方库的头文件 4 包含标准库头文件
  • 【Python】pip安装opencv-python包失败与换清华源提速

    文章目录 出现的问题 解决的方法 换源 出现的问题 在Windows10系统中 在cmd中 或者在pycharm的Terminal中 输入pip install opencv python会出现如下报错 ERROR Exception Tr
  • Python:ImportError: DLL load failed:找不到指定的模块 解决方案

    解决方法 检查numpy scipy matplotlib scikit learn的版本是否更新到最新且符合当前Python版本 如果出现不是最新的版本 先卸载该版本 windows pip uninstall numpy 再去http
  • 2019下半年阿里面试失败总结

    结果预览 2年半第一次出去面试 也是第一次面试阿里 打击不小 收货也不少 最终倒在二面笔试题上 虽有不甘 但仍需收拾心情 继续努力 一面总结 在一面上 跟网上大多数的反馈相同 都是比较Java基础项 然后往深度问 我整理了下 因为我简历上写
  • springmvc <mvc:annotation-driven/><mvc:default-servlet-handler/>区别 ssm整合

    文章目录 概述 概念和核心 什么是MVC springmvc第一个程序搭建 先到依赖 idea搭建项目 eclipse搭建 在spirngmvc xml配置文件写上这个 web xml写上servlet配置 匹配优先级 流程和原理 执行流程