目前我们所写的项目,持久层、业务层的类都放入到Spring容器之中了。他们之间需要注入非常方便,只需要通过@Autowired注解即可。
但是由于Servlet整个生命周期都是被Tomcat进行管理的,一个功能对应一个Servlet并且无法把Servlet放入到Spring容器中。所以每次编写Servlet时都需要编写init方法先获取到Spring容器,然后从Spring容器中取出需要使用的Bean。
Front(前端)设计模式就是有一个前端(不是前端专业那个前端,是最前面的意思)统一入口,在统一入口根据请求url调用自己的编写的普通方法。
新建com.bjsxt.controller.EmpController。
// 这个类是自定义的普通类,所以可以放入到Spring容器中
// 因为这个类是控制层代码,所以用@Controller注解
@Controller
public class EmpController {
// 当前类已经放入到了Spring容器,所以可以自动注入
@Autowired
private EmpService empService;
public void delete(){
// 删除员工的代码
}
public void show(){
// 显示员工信息的代码
}
}
新建com.bjsxt.controller.MyServlet。
这个Servlet就是Front设计模式中的前端。是请求的统一入口。
// 在Servlet中,url-pattern取值为/表示拦截除了URL以JSP结尾以外的所有URL
@WebServlet("/")
public class MyServlet extends HttpServlet {
private EmpController empController;
@Override
public void init(ServletConfig config) throws ServletException {
WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(config.getServletContext());
myController = wac.getBean("empController", EmpController.class);
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String uri = req.getRequestURI();
// 因为在Tomcat插件配置的项目名叫做bjsxt,所以需要去掉uri中的/bjsxt/
String path = uri.substring(7);
System.out.println(path);
if(path.equals("delete")){
empController.delete();
}else if(path.equals("showDept")){
empController.showDept();
}else if(path.equals("showEmp")){
empController.showEmp();
}
}
}
这样带来的好处是:
只需要在一个Servlet中编写获取容器Bean的代码,减少了代码冗余。
不需要为每个控制器都创建一个类,而是可以在一个普通Java类中提供普通实例方法代表以前servlet中的service方法。
因为可以自己编写普通Java类,这类可以放入到Spring容器中,注入Service更方便。
同时因为是自己编写的Java,所以可以进行一些封装,对其他操作进行简化。
- 本质为Spring 框架的一个扩展,在Spring官方ZIP包就是一个spring-webmvc.jar的jar包。
- Spring MVC属于Spring Framework的二级子项目。
- Spring MVC是基于Front设计模式。
- Spring MVC中已经帮助编写了前端入口的DispatcherServlet,里面编写了请求分发功能,但是并没有提供
@WebServlet
注解,需要我们在web.xml手动编写配置。
- EmpController在Spring MVC称为控制器类(Handler),里面的方法称为:控制单元(HandlerMethod)
Spring MVC在MVC三层中都有自己的功能。例如:
M:在模型层包含:数据校验。
V:在视图层包含:国际化、标签库。
C:在控制层包含的功能就更多了:转发重定向、参数、拦截器、作用域等。
- 因为Spring MVC属于Spring的子框架,所以Spring MVC中可以使用Spring框架的全部内容。
- Spring MVC有一个专门的容器,这个容器里面放Spring MVC中全部Bean,且这个容器属于Spring容器的子容器。
- Spring MVC子容器可以调用Spring 父容器的全部内容。但是Spring父容器不能调用Spring MVC子容器内容。
在只使用Spring MVC框架时需要导入spring-webmvc依赖即可。
org.springframework
spring-webmvc
5.3.16
在resources中新建springmvc.xml。这个文件的名称是随意的,只要和web.xml中配置对应上就可以。
web.xml的配置是为了让前端控制器DispatcherServlet生效。并且加载Spring MVC的配置文件。
Tomcat:
1、由于配置了1 ,Tomcat启动时就会创建 DispatcherServlet 对象。2、DispatcherServlet对象创建后会执行初始化方法, servletConfig对象读取 servlet的初始化参数(
) ,根据读取到的初始化参数值创建 springmvc容器。(设置spring容器为父容器,逻辑上的父子 关系)。 springmvc配置文件中配置了
com.zqwl.controller 包中的类中存在@Controller注解,将该类交给springmvc 容器管理。
3、只要获取到了springmvc容器就可以获取springmvc容器中的控制类对象
4、DispatcherServlet映射路径为 /,除了.jsp其他全部能够匹配。客户端发起求: 协议://ip:port/qqq,访问的资源 /qqq 和 DispatcherServlet 的映射路径 / 可以 匹配。
5、匹配后执行DispatcherServlet中 service 方法,从springmvc容器中获取控制 类,通过控制器类找到控制单元,
可以根据 请求资源 和 控制单元 的注解值找到对应的控制单元,执行控制单元, 处理请求。
ds
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc.xml
1
ds
/
@Controller// 放入到Spring MVC容器中
public class FirstController {
/*
* 官方标准写法:
* 返回值是ModelAndView,对象中存储跳转资源路径及作用域值
*/
// 当前方法的映射路径
@RequestMapping("/first")
public ModelAndView test1(){
ModelAndView modelAndView = new ModelAndView("first.jsp");
return modelAndView;
}
/*
* 简化写法(平时使用的方式)
* 返回值是String,表示跳转的资源路径
*/
@RequestMapping("/first2")
public String test2(){
return "first.jsp";
}
}
在webapp下新建first.jsp。在文件中随意写一句话。
- @RequestMapping注解可以写在控制器类上,也可以写在控制单元方法上。
- 如果写在类上,表示当前类所有控制单元的映射路径,都以指定路径开头。
- 如果写在方法上,表示当前方法的映射路径。最终访问这个控制单元的映射路径为:类上@RequestMapping映射路径+方法上@RequestMapping映射路径。
@Controller
@RequestMapping("/global")
public class FirstController {
@RequestMapping("/first3")
public String test3(){
return "first.jsp";
}
}
在@RequestMapping注解中提供了很多参数。
1.path:映射的路径。
映射一个访问路径:path = {"aa"} 省略{} path = "aa"
映射多个访问路径:path = {"aa,bb"}。
2.value:和path作用相同,只有一个value属性时,value可以省略。
3.name:添加描述信息。
4.method:允许的请求方式。
RequestMethod.POST
RequestMethod.GET
...
简化:
@GetMapping 为 @RequestMapping(method = RequestMethod.GET)
@PostMapping 为 @RequestMapping(method = RequestMethod.POST)
...
5.params: 指定请求中必须携带的请求参数。
6.headers: 指定请求中必须携带的请求头。7.consumes:表示处理请求内容(Content-Type)的类型。
8.produces:配合@ResponseBody注解使用,指定响应内容的类型。单独使用没有意 义。
/*
* EmpController:为控制器类,控制器类中可以有多个控制单元。
* 本质为普通的bean,交给springmvc容器管理
* */
@RequestMapping("/lyx")
@Controller
public class EmpController {
/* 控制单元 */
//请求映射(控制单元映射的路径)
@RequestMapping(value = "/a" ,name="name属性")
public String querry(){
System.out.println("querry执行了");
return "/first.jsp";
}
@RequestMapping(value = "b",name = "value属性,只有value属性时,可以直接写value的值")
public String bb(){
System.out.println("value属性执行了");
return "/first.jsp";
}
@RequestMapping(path = "c",name = "path属性和value属性使用方式是相同的,但是不可以省略")
public String cc(){
System.out.println("path属性执行了");
return "/first.jsp";
}
/*
* method属性类型是RequestMethod[],RequestMethod是枚举类型,支持HTTP协议中绝大多数请求类型。
* */
@RequestMapping(path = "d", method = RequestMethod.GET,name = " RequestMethod.GET 表示只接受GET情求")
public String method1(){
System.out.println("RequestMethod.GET属性执行了");
return "/first.jsp";
}
@RequestMapping(path = "e", method = RequestMethod.POST,name = " RequestMethod.POST 表示只接受POST情求")
//如果接收到GET请求,会在控制台提示 Request method 'GET' not supported
public String method2(){
System.out.println("RequestMethod.POST");
return "/first.jsp";
}
@RequestMapping(path = "f", method = {RequestMethod.POST,RequestMethod.GET},
name = " {RequestMethod.POST,RequestMethod.GET} 表示即接受POST情求又接收get请求")
public String method3(){
System.out.println("{RequestMethod.POST,RequestMethod.GET}");
return "/first.jsp";
}
//简写方式
@GetMapping("g")
public String method4(){
System.out.println("@GetMapping");
return "/first.jsp";
}
@PostMapping("h")
public String method5(){
System.out.println("@PostMapping");
return "/first.jsp";
}
// params属性类型是String[],表示请求中必须包含指定名称的请求参数。
@RequestMapping (value = "i",params = {"name","pwd"})//多个参数用{}
public String params(){
System.out.println("params");
return "/first.jsp";
}
//headers属性类型是String[],表示请求头中必须包含指定的请求头参数。
//consumers表示处理请求内容(Content-Type)的类型,平时多不设置,由Spring MVC自动判断。
// produces类型是String[],作用是设置@ResponseBody注解的响应内容类型
@RequestMapping (value = "aa",produces = "text/html;charset=utf-8",name = "设置@ResponseBody注解的响应内容类型")
@ResponseBody
public String produces() {
System.out.println("produces");
return "登龙";
}
}
- 映射路径就是web.xml中
的值或者@WebServlet("")注解的值。
- 映射路径无论是在Servlet中还是在Spring MVC中,都表示:当URL中出现指定路径时会执行Servlet的方法或执行Spring MVC的控制单元。
映射路径:写法上也支持路径的写法。在Java中路径是使用 / 进行分隔,表示目录层次。
在Spring MVC 的映射路径也支持多层写法,例如下面的代码表示URL为 http://localhost:8081/bjsxt/test/test2 时执行这个控制单元。
@RequestMapping("/test/test2")
public String test2(){
return "first.jsp";
}
映射路径中映射表示当控制器需要和视图资源进行跳转、引用等涉及到路径问题时会认为在webapp目录中映射一个虚拟资源。映射路径最后一个表示资源名称(test2),前面无论多少层都表示文件夹。
所以在控制单元(/test/test2)跳转到视图资源(first.jsp)时,由于路径中写的是相对路径(return "first.jsp";)所以Tomcat会在webapp/test目录下找一个叫做first.jsp的文件。显然是不存在这样的资源,first.jsp是在webapp目录下。
只需要在返回值中使用绝对路径就可以减少出错的情况。跳转时 / 表示项目根目录,也就是webapp目录的根目录。
@RequestMapping("/test/test2")
public String test2(){
return "/first.jsp";
}
在Spring MVC中支持Ant风格的映射路径写法。所谓的Ant风格就是支持三种特殊的符号。
符号 | 解释 |
---|---|
? |
匹配任意单字符 |
* |
匹配0或者任意数量的字符 |
** |
匹配0或者更多数量的目录 |
解释说明:
使用Ant的特殊符号时,表示模糊匹配。可能出现客户端发送过来的URL能匹配上多个映射路径,这时的优先级为:
固定值 (bjsxt1) > ?形式(bjsxt?) > 一个*
号(/*
) > (/**)
形式。
// 优先级最高
@RequestMapping("/bjsxt1")
public String testAnt1(){
System.out.println("bjsxt");
return "/first.jsp";
}
// 优先级低于bjsxt1。总长度为6,bjsxt开头,后面跟个任意内容符号
@RequestMapping("/bjsxt?")
public String testAnt2(){
System.out.println("bjsxt");
return "/first.jsp";
}
// 优先级低于?。一层路径,任意内容
@RequestMapping("/*")
public String testAnt3(){
System.out.println("11111");
return "/first.jsp";
}
// 优先级低于*。任意层路径
@RequestMapping("/**")
public String testAnt4(){
System.out.println("22222");
return "/first.jsp";
}
转发和重定向。这两个概念都是出现在资源之间相互跳转的。
两者区别:
(1)转发为一次请求,tomcat内部跳转。重定向为多次请求,不是tomcat内部跳转。
(2)转发是一次请求,无论服务器内部转发多少次,请求对象都不变。所以转发可以共享 请求域的值。同时对于客户端浏览器URL是不变的。
重定向后需要客户端重新发起请求,和重定向之前不是一个请求。所以重定向后不能获 取到之前设置在请求域的值。同时客户端浏览器URL是改变的。
(3)转发只能跳转到当前项目内部资源。重定向可以跳转到外部资源。例如:从自己的项目中跳转到百度应该使用重定向。
(4)转发时资源路径如果是绝对路径,第一个 / 表示当前项目根目录。
重定向时资源路径时绝对路径,第一个 / 表示 Tomcat 的 webapps目录,即:当前项目的上层目录。
转发的代码实现:
request.getRequestDispatcher("/first.jsp").forward(request,response);
重定向的代码实现:
response.sendRedirect("/bjsxt/first.jsp");
- 在Spring MVC框架中,默认情况下都使用转发进行寻找资源。
- 在资源路径前面添加forward: 表示转发。因为写不写forward:都是转发,所以为了代码写起来简单一些,多省略forward: 。
- 如果希望使用重定向跳转到其他资源,只能在资源路径最前面明确添加redirect:,下面代码就是使用重定向方式的写法。
@RequestMapping("/test/test2")
public String test2(){
return "redirect:/first.jsp";
}
在Spring MVC中无论是转发还是重定向,使用绝对路径时/都表示项目根目录。
这种设计对于开发者来说更加友好,不用在区分到底是转发,还是重定向了。
- 在平时学习过程中,我们多会把JSP文件放入到webapp目录中,或在webapp下新建一个目录把页面资源放入到目录中,这种情况JSP都是可以通过浏览器直接访问的。
- 但是在一些特定的项目中,从安全性等方面考虑不希望客户端通过浏览器直接访问对应的资源。
- 这时就可以把资源放入到WEB-INF目录中。因为在Java Web项目中规定:WEB-INF中资源是不允许被客户端直接访问,需要先访问控制器,通过控制器的转发来访问这些资源。
- 这种目录结构也更加负责MVC开发模式,更能体现出控制器的作用。
如果项目中所有的JSP、CSS、JavaScript、图片都放入到WEB-INF中,那所有的资源都必须先执行控制器。这样对于刚学习这种写法的人可能觉得实现起来更加复杂了。但是从项目角度上却是更加安全了,也可以在控制器方法中加入自己想要加入的逻辑。
1.ModelAndView:模型数据(存储业务数据)和视图
Model:模型数据(存储模型层中查询到的数据)
View: 视图(页面属于视图中的一种)
2. 控制单元执行完成后,将控制单元返回的结果固定封装为ModelAndView对象。Model中存储了业务数据,View通常存储视图名。最终目的:将Model中的业务数据通过 视图 渲染 到客户端。
底层源码:
ModelAndView mv;
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
执行控制单元,控制单元返回结果封装为ModelAndView。3. 视图解析器:ViewResolver(接口),根据ModelAndView对象中解析出的视图名找到 对应的视图对象,并返回。
示例:
以.jsp视图为例:
1.控制单元执行后,执行handle(processedRequest, response, mappedHandler.getHandler()),返回ModelAndView对象 (viewname为index.jsp)
2.获取到ModelAndView后,执行render(mv, request, response);
3.在render方法中调用了view = resolveViewName(viewName, mv.getModelInternal(), locale, request),获取到视图名。
4.在resolveViewName方法中, 视图解析器 根据视图名找到对应的视图对象,并返回。
(1)默认的使用的视图解析器:InternalResourceViewResourceView。
(2) .jsp的视图对象为:InternalResourceView。
5.返回视图对象后,调用view.render(mv.getModelInternal(), request, response)。实际完 成Model中的数据通过视图响应回到客户端。
6. .jsp的InternalResourceView的视图对象渲染时:
(1)将Model中的数据存储到请求域对象中。
(2)将请求转发到.jsp -> .java(获取请求去对象中的数据)-> .class -> 将结果输出 到客户端。
Spring MVC 定义了
ViewResolver
和View
接口:
- 视图解析器用来解析逻辑视图,将其解析成真正的视图对象。
- SpringMVC 提供了一个视图解析器的接口 ViewResolver,所有具体的视图解析器必须实现该接口。
- AbstractCachingViewResolver:抽象类,这种视图解析器会把它曾经解析过的视图保存起来,然后每次要解析视图的时候先从缓存里面找,如果找到了对应的视图就直接返回,如果没有就创建一个新的视图对象,然后把它放到一个用于缓存的map中,接着再把新建的视图返回。使用这种视图缓存的方式可以把解析视图的性能问题降到最低。
- UrlBasedViewResolver:它是对ViewResolver的一种简单实现,而且继承了AbstractCachingViewResolver,主要就是提供的一种拼接URL的方式来解析视图,它可以让我们通过prefix属性指定一个指定的前缀,通过suffix属性指定一个指定的后缀,然后把返回的逻辑视图名称加上指定的前缀和后缀就是指定的视图URL了。如prefix=/WEB-INF/,suffix=.jsp,返回的视图名称viewName=test,则UrlBasedViewResolver解析出来的视图URL就是/WEB-INF/test.jsp。默认的prefix和suffix都是空串。
- InternalResourceViewResolver:它是URLBasedViewResolver的子类,所以URLBasedViewResolver支持的特性它都支持。在实际应用中InternalResourceViewResolver也是使用的最广泛的一个视图解析器。InternalResourceViewResolver解释为内部资源视图解析器。InternalResourceViewResolver会把返回的视图名称都解析为InternalResourceView对象,InternalResourceView会把Controller处理器方法返回的模型数据都存放到对应的request属性中,然后通过RequestDispatcher在服务器端把请求forword到目标URL
- ThymeleafViewResolver:Thymeleaf视图解析器,映射成一个 Thymeleaf 模板文件。
- FreeMarkerViewResolver:UrlBasedViewResolver的子类。FreeMarkerViewResolver会把Controller处理方法返回的逻辑视图解析为FreeMarkerView。
对于项目结构比较固定,页面按照一定规则放在特定位置,且返回值内容比较长时,就可以配置视图解析器。在springmvc.xml配置下面内容。
配置了视图解析器后,控制单元返回值就不需要写前缀和后缀的内容了,写起来更加简单。
@RequestMapping("/showSuiyi")
public String showSuiyi(){
return "suiyi";// 由视图解析器拼接:prefix + suiyi + suffix。具体:/WEB-INF/page/ + suiyi + .jsp
}
@RequestMapping("/showSuiyi2")
public String showSuiyi2(){
return "suiyi2";// 由视图解析器拼接:prefix + suiyi + suffix。具体:/WEB-INF/page/ + suiyi2 + .jsp
}
当自定义视图解析器后,返回值前面和后面都会固定拼接字符串(在没有使用其他注解情况下)。但是如果控制单元执行完,并不希望跳转到视图,而是跳转到控制器,这时需要在返回值前面明确添加forward:或redirect: ,这样就不走视图解析器了。
@RequestMapping("/showSuiyi3")
public String showSuiyi3(){
return "suiyi3";// 跳转到 /WEB-INF/page/suiyi3.jsp
}
@RequestMapping("/demo")
public String demo(){
return "forward:/showSuiyi3"; // 不走视图解析器了。跳转到/showSuiyi3控制器单元
}
按照SpringMVC的使用流程,需要在web.xml文件中配置DispatcherServlet的拦截范围,而我们配置的拦截范围为”/”,表示拦截除jsp请求以外的所有请求。这样造成,请求是js,css,图片等静态资源的请求,也会被拦截,调用对应的单元方法来处理请求。但是,我们是一个静态资源的请求,不应该按照普通单元方法请求的流程来处理,而是将对应的静态资源响应给浏览器使用。
Spring MVC 支持静态资源配置,当URL满足指定路径要求时不再去找控制单元,而是直接转发到特定路径中静态资源。
例如项目结构:
需要在springmvc.xml中配置静态资源放行 :
(1) 紧耦方式。获取原生Servlet API,通过原生Servlet API获取请求参数、设置响应内容、设置作用域的值。
(2)解耦方式。使用Spring MVC提供的方式获取请求参数、设置响应内容、设置作用域的值。
@RequestMapping("/demo")
public String demoServlet(HttpServletRequest req){
String name = req.getParameter("name");
return "index";
}
@RequestMapping("/out")
public void testOut(HttpServletResponse resp) throws IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.print("bjsxt");
}
解耦方式是Spring MVC独有方式。是Spring MVC给开发者提供的:
(1)获取请求中内容
(2)设置作用域值
(3)设置响应内容
等写法。
获取普通表单参数,只需要包含在控制单元中提供与请求参数同名的方法参数即可。
Spring MVC会自动进行类型转换。
@RequestMapping("/testParam")
public String testParam(String name,Integer age){//用int类型在接收到null时会报错
System.out.println(name+","+age);
return "suiyi";
}
@RequestParam是方法参数级注解。每个控制单元方法参数前面都能写这个注解。在@RequestParam注解里面提供了四个属性,分别:
(1)name: 可以使用name指定请求参数名。
@RequestMapping("/testParam")
public String testParam(@RequestParam(name="name") String name123, Integer age){
System.out.println(name123+","+age);
return "suiyi";
}
(2)value:是name属性的别名。功能和name属性相同。
(3)defaultValue:默认值。表示当请求参数中没有这个参数时给与的默认值。
@RequestMapping("/testParam")
public String testParam(@RequestParam("name") String name123,@RequestParam(defaultValue = "16") Integer age){
System.out.println(name123+","+age);
return "suiyi";
}
(4)required:boolean类型,表示请求中是否必须包含此参数。
当使用类对象作为参数时,要求属性名和参数名对应,类型转换由Spring MVC自动完成。不支持@RequestParam注解。
@RequestMapping("/testBean")
public String testBean(People peo){
System.out.println(peo);
return "suiyi";
}
既然Spring MVC中又支持JavaBean的形式,又支持使用简单类型接收。当两种方式都使用时,且类中和简单类型重名时,Spring MVC会都给设置上。
当使用数组进行接收时,需要数组对象名和请求参数名一致。如果不想一致,可以使用@RequestParam("hovers")定义请求参数名。
@RequestMapping("/testHover")
public String testHovers(String [] hovers){
System.out.println(Arrays.toString(hovers));
return "suiyi";
}
在使用List进行接收时,必须在参数前面添加@RequestParam注解,注解中内容就是请求参数名。
@RequestMapping("/testHover")
public String testHovers(@RequestParam("hovers") List hovers){
System.out.println(hovers);
return "suiyi";
}
默认情况下必须保证客户端参数格式和服务器日期格式一致。可以在计算机屏幕右下角查看到日期格式。
所以只要保证客户端传递过来的日期是yyyy/MM/dd hh:mm:ss的格式,Spring MVC会自动进行类型转换。其中小时分钟秒可以省略不写。
@RequestMapping("/testDate")
public String testDate(Date date){
System.out.println(date.toLocaleString());
return "suiyi";
}
如果觉得默认的格式无法满足要求,可以使用@DateTimeFormat自定义时间格式。
//@DateTimeFormat可以写在控制单元Date类型参数之前,也可以写在JavaBean的属性上面。
@RequestMapping("/testDate")
public String testDate(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date){
System.out.println(date.toLocaleString());
return "suiyi";
}
在HTTP协议中,请求头参数会有很多。如果希望接收请求头数据可以使用@RequestHeader进行接收。
在控制单元方法参数中添加对应名称的参数,并在参数前面添加@RequestHeader注解。
@RequestMapping("/testHeader")
public String testHeader(@RequestHeader String Accept){
System.out.println(Accept);
return "suiyi";
}
//Spring MVC对于接收请求参数时名称不区分大小写。所以下面的写法也是可以的。
@RequestMapping("/testHeader")
public String testHeader(@RequestHeader String accept){
System.out.println(accept);
return "suiyi";
}
只需要在控制单元方法参数中添加Model对象,对象名称任意。
Model是一个接口,里面有很多子接口和实现类。当放置Model接口时,Spring MVC默认注入的是BindingAwareModelMap。
//在Model接口中有很多个方法,里面最常用的有两个addAttribute(String,Object)和addAllAtributes(Map)。
@RequestMapping("/testScope1")
public String testScope1(Model model){
// 设置一个作用域值
model.addAttribute("name","value");
// 设置多个作用域值
Map map = new HashMap<>();
map.put("name2","value2");
model.addAllAttributes(map);
return "suiyi";
}
直接在控制单元方法上添加一个Map,然后向Map对象中put值就可以了。
@RequestMapping("/testScope2")
public String testScope2(Map map){
map.put("name","value");
return "suiyi";
}
- Tomcat8及之后的版本已经将Get请求乱码进行了处理,不需要额外处理。
- Tomcat7默认的接收请求GET方式的是IOS-8859-1,如果希望正确的显示中文,还需要手动把内容转换为UTF-8编码。
方式一:
@RequestMapping("/testEncoding")
public String testEncoding(String name) throws UnsupportedEncodingException {
System.out.println("接收到name:"+name);
String newName = new String(name.getBytes("iso-8859-1"),"utf-8");
System.out.println("转换后的name:"+newName);
return "suiyi";
}
方式二:在tomcat中配置URIEncoding=utf-8。
- 在Spring MVC提供了一个类CharacterEncodingFilter,里面直接写好了POST方式中文乱码解决代码。
- 想让CharacterEncodingFilter生效,就需要在web.xml文件中配置下面内容。
- 表示所有的请求编码都设置为UTF-8编码。
code
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
code
/*