SpringMVC框架学习
1.基本理论
1.三层架构
- 在开发服务器端程序、一般都基于两种形式,一种C/S架构程序、一种B/S架构程序
- 使用Java语言基本上开发B/S架构的程序、B/S架构又分成三层架构
- 三层架构
1.表现层:WEB层,用来和客户端进行数据交互的,表现层一般采用MVC的设计模式 2.业务层:处理具体业务逻辑的 3.持久层:用来操作数据库的
2.什么是MVC
? ? ? ? ?MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。 是将业务逻辑、数据、显示分离的方法来组织代码。
MVC主要作用是降低了视图与业务逻辑间的双向偶合。
MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在差异。
- Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或
JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和 服务层 (行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。 - View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。
- Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型
数据返回给视图,由视图负责展示。 也就是说控制器做了个调度员的工作。
最典型的MVC就是JSP + servlet + javabean的模式。
3.SpringMVC是什么
? ? ? ? ?SpringMVC是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级Web框架,属于SpringFrameWork的后续产品,已融合在Spring Web Flow里面,Spring框架提供了构建Web应用程序的全功能MVC模块,使用Spring可插入MVC架构,从而在使用Spring进行WEB开发的时候,可选择Spring的SpringMVC框架或集成其他MVC开发框架
? ? ? ? ?SpringMVC现在已成为主流的MVC框架之一,它通过一套注解,让一个简单的Java类成为处理请求的控制器,而无须实现任何接口,他同时还支持RESTful编程风格的请求
3.1、Model1时代
? ? ? ? ?在web早期的开发中,通常采用的都是Model1。 ? ? ? ? ?Model1中,主要分为两层,视图层和模型层。 ? ? ? ? ?Model1优点:架构简单,比较适合小型项目开发; ? ? ? ? ?Model1缺点:JSP职责不单一,职责过重,不便于维护;
3.2、Model2时代
Model2把一个项目分成三部分,包括视图、控制、模型。
- 用户发请求
- Servlet接收请求数据,并调用对应的业务逻辑方法
- 业务处理完毕,返回更新后的数据给servlet
- servlet转向到JSP,由JSP来渲染页面
- 响应给前端更新后的页面
职责分析: Controller:控制器 - 取得表单数据
- 调用业务逻辑
- 转向指定的页面
Model:模型 - 业务逻辑
- 保存数据的状态
View:视图 - 显示页面
Model2这样不仅提高的代码的复用率与项目的扩展性,且大大降低了项目的维护成本。Model 1模式的 实现比较简单,适用于快速开发小规模项目,Model1中JSP页面身兼View和Controller两种角色,将控 制逻辑和表现逻辑混杂在一起,从而导致代码的重用性非常低,增加了应用的扩展性和维护的难度。 Model2消除了Model1的缺点。
4.SpringMVC优势
(1)SpringMVC框架提供了一整套完善的组件。
不同于以前框架只提供接口,然后让使用者自己根据接口写实现类来实现功能,SpringMVC提供了一整套完善的组件,可以直接使用。这就相当于以前的框架只给你提供设计图纸,你需要根据设计图纸自己把工具造出来,而现在SpringMVC直接给你一套现成的工具箱,里面有你用得到的各种工具。
而且使用SpringMVC框架提供这些工具也巨简单,通过一些简单的注解就搞定了,不需要编写繁琐冗长的代码,简直比夏天喝雪碧还要爽。
(2)SpringMVC是以强大的Spring容器为基础的框架。
如果同学你使用过Spring容器,那你一定知道Spring容器的对象托管功能有多么的好用。它不需要你自己去创建和释放对象,Spring容器帮你全搞定! 同样地,能够放入Spring容器里面的这个SpringMVC工具箱,里面各种工具类的管理也是不需要操心的。而这省心省力的优点,是其他框架都没有的。
(3)框架的配置简单又不失灵活性。
SpringMVC框架的常用配置项就已经涵盖了项目中80%的配置需求,简单的项目甚至可以做到零配置,拿过来就用。
(4)代码的可重用性很高。
翻译成大白话就是,一个成熟的,上线稳定运行过的SpringMVC项目,经过简单修改,甚至不用修改,就可以作为另一个新项目开发的基础。这样能在开发新项目时省很多力气。
(5)可扩展性好。
如果SpringMVC框架提供的工具不能100%满足你的需求,你需要定制开发,SpringMVC框架同样也提供了相应的接口,可以进行工具的升级。这样你在遇到强力精英怪的时候,照样能用SpringMVC框架打败它。
(6)清晰的角色划分
- 前端控制器(DispatcherServlet)
- 请求到处理器映射(HandlerMapping)
- 处理器适配器(HandlerAdapter)
- 视图解析器(ViewResolver)
- 处理器或页面控制器(Controller)
- 验证器(Validator)
- 命令对象(Command 请求参数绑定到的对象就叫命令对象)
- 表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)
(7)SpringMVC和Struts2的优略分析
共同点:
- 他们都是表现层框架,都是基于MVC模型编写的
- 他们的底层都离不开原始ServletAPI
- 他们处理请求的机制都是一个核心控制器
区别:
- Spring MVC的入口是Servlet、而Struts2是Filter
- SpringMVC是基于方法设计,而Struts2是基于类,Struts2每次执行都会创建一个动作类,所有SpringMVC比Struts2快
- SpringMVC使用更加简洁,同时还支持JSR303,处理ajax的请求更方便
- Struts2的OGNL表达式使页面的开发效率相比SpringMVC更高些,但执行效率并没有比JSTL提升
2.SpringMVC的入门案例
案例需求:
导入依赖包pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>SpringMAC</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>SpringMAC Maven Webapp</name>
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring-version>5.0.2.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>SpringMAC</finalName>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
创建两个文件夹java和resources分别作为各自root 需要配置springmvc.xml的配置文件 配置Tomcat服务器
配置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>
<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:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
配置springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.springT"/>
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
<mvc:annotation-driven/>
</beans>
配置测试页面jsp
<%--
Created by IntelliJ IDEA.
User: 程序员小徐同学
Date: 2022-01-25
Time: 10:39
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>hell SpringMVC</title>
</head>
<body>
<h3>入门程序</h3>
<a href="hello">跳转页面</a>
</body>
</html>
配置测试成功页面
<%--
Created by IntelliJ IDEA.
User: 程序员小徐同学
Date: 2022-01-25
Time: 10:49
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>转换成功</h3>
</body>
</html>
编写实现跳转类
package com.springT.Controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ControllerDemo {
@RequestMapping(path = "/hello")
public String hellspring(){
System.out.println("hell springmvc");
return "success";
}
}
return返回的值成功加载到success.jsp页面
1.配置流程
1.其中服务器,加载配置文件
- DIspatcherServlet对象创建
- springmvc.xml被加载了
- ControllerDemo创建成对象
2.发送请求,后台处理
SpringMVC的原理如下图所示: 当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制 器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图 渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者。 2.3、SpringMVC执行原理
简要分析执行流程
- DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,
DispatcherServlet接收请求并拦截请求。 我们假设请求的url为 : http://localhost:8080/SpringMVC/hello 如上url拆分成三部分: http://localhost:8080服务器域名 SpringMVC部署在服务器上的web站点 hello表示控制器 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。 - HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据
请求url查找Handler。 - HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器
为:hello。 - HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
- HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
- Handler让具体的Controller执行。
- Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
- HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
- DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
- 视图解析器将解析的逻辑视图名传给DispatcherServlet。
- DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
- 最终视图呈现给用户。
2.涉及的组件讲解
2.1 DispatcherServlet:前端控制器 ? ? ? ? ?用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其他组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性 2.2 HandlerMapping:处理映射器 ? ? ? ? ?handlerMapping负责根据用户请求找到Handler即处理器,SpringMVC提供不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式 2.3 Handler:处理器 ? ? ? ? ?通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行 2.3 View Resolver:视图解析器 ? ? ? ? ?View Resolver负责将处理结果生成View视图,View Resolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户 2.4 View:视图 ? ? ? ? ? SpringMVC框架提供了很多的View视图类型的支持,包括:jstlView、FreemarkerView、pdfView等,我们最常用的视图是jsp
一般情况下需要通过页面标签或页面模板技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面
2.5 <mvc:annotation-driver> 说明
? ? ? ? ? ?在SpringMVC的各个组件中,处理器映射器、处理器适配器、视图解析器称为SpringMVC的三大组件 使用<mvc:annotation-driver> 自动加载 RequestMappingHandlerMapping(处理器映射器)和RequestMappingHandlerAdapter(处理器适配器),可用在SpringMVC.xml配置文件中使用<mvc:annotation-driver>替代注解处理器和适配器的配置 它就相当于在xml中配置了:
<mvc:annotation-driven/>
RequestMapping的属性:value:用于请求的URL、他和path属性作用是一样的 ? ? ? path:用于指定请求路径 ? ? ? method:用于指定请求的方式 ? ? ? params:用于指定限制请求参数的条件,它支持简单的表达式,要请求参数的key和value必须和配置一模一样 例如: ? ? ? params = {”accountName“},表示请求参数必须有accountName ? ? ? params = {”money!100“},表示请求参数money不能是100 ? ? ? headers:用于指定限制请求消息头的条件
method = {RequestMethod.POST}现在请求方式对其的限制
public class ControllerDemo {
@RequestMapping(path = "/hello" ,method = {RequestMethod.POST},params = {"username"})
public String hellspring(){
System.out.println("hell springmvc");
return "success";
}
}
3使用注解@Controller
- @Controller注解类型用于声明Spring类的实例是一个控制器(在讲IOC时还提到了另外3个注
解); - Spring可以使用扫描机制来找到应用程序中所有基于注解的控制器类,为了保证Spring能找到你的
控制器,需要在配置文件中声明组件扫描。
<context:component-scan base-package="com.kuang.controller"/>
- 增加一个ControllerTest2类,使用注解实现;
@Controller
public class ControllerTest2{
@RequestMapping("/t2")
public String index(Model model){
model.addAttribute("msg", "ControllerTest2");
return "test";
}
}
4RequestMapping
- @RequestMapping
- @RequestMapping注解用于映射url到控制器类或一个特定的处理程序方法。可用于类或方法上。
用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。 为了测试结论更加准确,我们可以加上一个项目名测试 myweb 只注解在方法上面
@Controller
public class TestController {
@RequestMapping("/h1")
public String test(){
return "test";
}
}
@Controller
@RequestMapping("/admin")
public class TestController {
@RequestMapping("/h1")
public String test(){
return "test";
}
}
5RestFul 风格
概念 Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设 计的软件可以更简洁,更有层次,更易于实现缓存等机制。 功能 资源:互联网所有的事物都可以被抽象为资源 资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。 分别对应 添加、 删除、修改、查询。 传统方式操作资源 :通过不同的参数来实现不同的效果!方法单一,post 和 get 学习测试
- 在新建一个类 RestFulController
@Controller
public class RestFulController {
}
- 在Spring MVC中可以使用 @PathVariable 注解,让方法参数的值对应绑定到一个URI模板变量
上。
@Controller
public class RestFulController {
@RequestMapping("/commit/{p1}/{p2}")
public String index(@PathVariable int p1, @PathVariable int p2,
Model model){
int result = p1+p2;
model.addAttribute("msg", "结果:"+result);
return "test";
}
}
思考:使用路径变量的好处? 使路径变得更加简洁; 获得参数更加方便,框架会自动进行类型转换。 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法,如这 里访问是的路径是/commit/1/a,则路径与方法不匹配,而不会是参数转换失败。
- 我们来修改下对应的参数类型,
@RequestMapping("/commit/{p1}/{p2}")
public String index(@PathVariable int p1, @PathVariable String p2, Model
model){
String result = p1+p2;
model.addAttribute("msg", "结果:"+result);
return "test";
}
使用method属性指定请求类型 用于约束请求的类型,可以收窄请求范围。指定请求谓词的类型如GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE等
@RequestMapping(value = "/hello",method = {RequestMethod.POST})
public String index2(Model model){
model.addAttribute("msg", "hello!");
return "test";
}
小结: Spring MVC 的 @RequestMapping 注解能够处理 HTTP 请求的方法, 比如 GET, PUT, POST, DELETE 以 及 PATCH。 所有的地址栏请求默认都会是 HTTP GET 类型的。 方法级别的注解变体有如下几个: 组合注解
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
@GetMapping 是一个组合注解 它所扮演的是 @RequestMapping(method =RequestMethod.GET) 的一个快捷方式。 平时使用的会比较多!
6结果跳转方式
6.1、ModelAndView
设置ModelAndView对象 , 根据view的名称 , 和视图解析器跳到指定的页面 . 页面 : {视图解析器前缀} + viewName +{视图解析器后缀
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
对应的controller类
public class ControllerTest1 implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("msg","ControllerTest1");
mv.setViewName("test");
return mv;
}
}
6.2、ServletAPI
通过设置ServletAPI , 不需要视图解析器 .
- 通过HttpServletResponse进行输出
- 通过HttpServletResponse实现重定向
- 通过HttpServletResponse实现转发
@Controller
public class ResultGo {
@RequestMapping("/result/t1")
public void test1(HttpServletRequest req, HttpServletResponse rsp)
throws IOException {
rsp.getWriter().println("Hello,Spring BY servlet API");
}
@RequestMapping("/result/t2")
public void test2(HttpServletRequest req, HttpServletResponse rsp)
throws IOException {
rsp.sendRedirect("/index.jsp");
}
@RequestMapping("/result/t3")
public void test3(HttpServletRequest req, HttpServletResponse rsp)
throws Exception {
req.setAttribute("msg","/result/t3");
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,rsp);
}
}
6.3、SpringMVC
通过SpringMVC来实现转发和重定向 - 无需视图解析器; 测试前,需要将视图解析器注释掉
@Controller
public class ResultSpringMVC {
@RequestMapping("/rsm/t1")
public String test1(){
return "/index.jsp";
}
@RequestMapping("/rsm/t2")
public String test2(){
return "forward:/index.jsp";
}
@RequestMapping("/rsm/t3")
public String test3(){
return "redirect:/index.jsp";
}
}
通过SpringMVC来实现转发和重定向 - 有视图解析器; 重定向 , 不需要视图解析器 , 本质就是重新请求一个新地方嘛 , 所以注意路径问题. 可以重定向到另外一个请求实现 .
@Controller
public class ResultSpringMVC2 {
@RequestMapping("/rsm2/t1")
public String test1(){
return "test";
}
@RequestMapping("/rsm2/t2")
public String test2(){
return "redirect:/index.jsp";
}
}
7、数据处理
7.1、处理提交数据
1、提交的域名称和处理方法的参数名一致 提交数据 : http://localhost:8080/hello?name=kuangshen
@RequestMapping("/hello")
public String hello(String name){
System.out.println(name);
return "hello";
}
2、提交的域名称和处理方法的参数名不一致 提交数据 : http://localhost:8080/hello?username=kuangshen
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name){
System.out.println(name);
return "hello";
}
3、提交的是一个对象 要求提交的表单域和对象的属性名一致 , 参数使用对象即可
- 实体类
public class User {
private int id;
private String name;
private int age;
}
- 提交数据 : http://localhost:8080/mvc04/user?name=kuangshen&id=1&age=15
- 处理方法 :
@RequestMapping("/user")
public String user(User user){
System.out.println(user);
return "hello";
}
后台输出 : User { id=1, name=‘kuangshen’, age=15 } 说明:如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null。
7.2、数据显示到前端
第一种 : 通过ModelAndView 我们前面一直都是如此 . 就不过多解释
public class ControllerTest1 implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("msg","ControllerTest1");
mv.setViewName("test");
return mv;
}
}
第二种 : 通过ModelMap ModelMap
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name, ModelMap model){
model.addAttribute("name",name);
System.out.println(name);
return "hello";
}
第三种 : 通过Model Model
@RequestMapping("/ct2/hello")
public String hello(@RequestParam("username") String name, Model model){
model.addAttribute("msg",name);
System.out.println(name);
return "test";
}
7.3、对比
Model 只有寥寥几个方法只适合用于储存数据,简化了新手对于Model对象的操作和理解;
ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特
性;
ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。
当然更多的以后开发考虑的更多的是性能和优化,就不能单单仅限于此的了解。 请使用80%的时间打好扎实的基础,剩下18%的时间研究框架,2%的时间去学点英文,框架的官方文档 永远是最好的教程。
7.4、乱码问题
测试步骤:
- 我们可以在首页编写一个提交的表单
<form action="/e/t" method="post">
<input type="text" name="name">
<input type="submit">
</form>
- 后台编写对应的处理类
@Controller
public class Encoding {
@RequestMapping("/e/t")
public String test(Model model,String name){
model.addAttribute("msg",name);
return "test";
}
}
- 输入中文测试,发现乱码
不得不说,乱码问题是在我们开发中十分常见的问题,也是让我们程序猿比较头大的问题! 以前乱码问题通过过滤器解决 , 而SpringMVC给我们提供了一个过滤器 , 可以在web.xml中配置 . 修改了xml文件需要重启服务器!
<filter>
<filter-name>encoding</filter-name>
<filterclass>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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
但是我们发现 , 有些极端情况下.这个过滤器对get的支持不好 . 处理方法 : 4. 修改tomcat配置文件 : 设置编码!
<Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
- 自定义过滤器
package com.kuang.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
public class GenericEncodingFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse
response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse myResponse=(HttpServletResponse) response;
myResponse.setContentType("text/html;charset=UTF-8");
HttpServletRequest httpServletRequest = (HttpServletRequest)
request;
HttpServletRequest myrequest = new
MyRequest(httpServletRequest);
chain.doFilter(myrequest, response);
}
@Override
public void init(FilterConfig filterConfig) throws
ServletException {
}
}
class MyRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;
private boolean hasEncode;
public MyRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public Map getParameterMap() {
String method = request.getMethod();
if (method.equalsIgnoreCase("post")) {
try {
request.setCharacterEncoding("utf-8");
return request.getParameterMap();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else if (method.equalsIgnoreCase("get")) {
Map<String, String[]> parameterMap =
request.getParameterMap();
if (!hasEncode) {
for (String parameterName : parameterMap.keySet()) {
String[] values = parameterMap.get(parameterName);
if (values != null) {
for (int i = 0; i < values.length; i++) {
try {
values[i] = new String(values[i]
.getBytes("ISO-8859-1"), "utf8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
hasEncode = true;
}
return parameterMap;
}
return super.getParameterMap();
}
@Override
public String getParameter(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
if (values == null) {
return null;
}
return values[0];
}
@Override
public String[] getParameterValues(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
return values;
}
}
这个也是我在网上找的一些大神写的,一般情况下,SpringMVC默认的乱码处理就已经能够很好的 解决了! 然后在web.xml中配置这个过滤器即可! 乱码问题,需要平时多注意,在尽可能能设置编码的地方,都设置为统一编码 UTF-8!
3.还有什么问题可以留言给我,会尽心解答的,觉得文章不错的话点个赞把
|