- 一、@RequestMapping 定义请求规则
- 1. 指定模块名称
- 2. 对请求提交方式的定义
- 二、处理器方法的参数
- 1. 逐个参数
- 2. 校正请求参数名@RequestParam
- 3. 请求参数中文乱码问题
- 4. 对象参数接收
- 三、处理器方法的返回值
- 1. 返回 ModelAndView
- 2. 返回 String
- 四、返回对象Object
- 1. 环境搭建
- 2. 返回自定义类型对象
- 3. 返回List集合
- 3. 返回字符串对象
- 五、 解读url-pattern
- 1. *.do
- 2. /
- 3. 静态资源的访问
一、@RequestMapping 定义请求规则
1. 指定模块名称
通过@RequestMapping 注解可以定义处理器对于请求的映射规则
该注解可以注解在方法上,也可以注解在类上,但意义是不同的
value 属性值常以“/”开始
一个@Controller 所注解的类中,可以定义多个处理器方法。当然,不同的处理器方法所匹配的 URI 是不同的
这些不同的 URI 被指定在注解于方法之上的@RequestMapping 的value 属性中
但若这些请求具有相同的 URI 部分,则这些相同的 URI,可以被抽取到注解在类之上的@RequestMapping 的 value 属性中,此时的这个 URI 表示模块的名称
URI 的请求是相对于 Web 的根目录
下面的例子还是在第一个程序的上面进行改写
/**
*@RequestMapping:
* value:所有请求地址的公共部分,叫做模块名称
* 位置:放在类的上面
*/
@Controller
@RequestMapping(value = "/test")
public class MyController {
@RequestMapping(value = "/some.do")
public ModelAndView doSome(){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","欢迎使用springmvc");
mv.addObject("fun","执行的是doSome方法");
mv.setViewName("show");
return mv;
}
@RequestMapping(value = "/other.do")
public ModelAndView doOther(){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","欢迎使用springmvc");
mv.addObject("fun","执行的是doOther方法");
mv.setViewName("show");
return mv;
}
}
此时在index.jsp中
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
第一个springmvc项目
也就是把请求这些请求中相同的部分添加到了类的上面,添加了@RequestMapping(value = "/test")
2. 对请求提交方式的定义
对于@RequestMapping,其有一个属性 method,用于对被注解方法所处理请求的提交方式进行限制,即只有满足该method属性指定的提交方式的请求,才会执行该被注解方法
Method 属性的取值为 RequestMethod 枚举常量。常用的为 RequestMethod.GET 与RequestMethod.POST,分别表示提交方式的匹配规则为 GET 与 POST 提交
只要指定了处理器方法匹配的请求提交方式为 POST,则相当于指定了请求发送的方式:要么使用表单请求,要么使用 AJAX 请求。其它请求方式被禁用
当然,若不指定 method 属性,则无论是 GET 还是 POST 提交方式,均可匹配。即对于请求的提交方式无要求
例子如下:
@Controller
@RequestMapping(value = "/test")
public class MyController {
/**
*@RequestMapping:请求映射
* 属性:method:请求的方式,它的值是RequestMethod类枚举值
*/
@RequestMapping(value = "/some.do",method = RequestMethod.GET)
public ModelAndView doSome(){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","欢迎使用springmvc");
mv.addObject("fun","执行的是doSome方法");
mv.setViewName("show");
return mv;
}
/**
*
* 获取到请求参数
*/
@RequestMapping(value = "/other.do",method = RequestMethod.POST)
public ModelAndView doOther(HttpServletRequest request, HttpServletResponse response
, HttpSession session){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","欢迎使用springmvc,获取请求的参数:"+request.getParameter("name"));
mv.addObject("fun","执行的是doOther方法");
mv.setViewName("show");
return mv;
}
}
在index.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
第一个springmvc项目
二、处理器方法的参数
处理器方法可以包含以下四类参数,这些参数会在系统调用时由系统自动赋值,即程序员可在方法内直接使用
- HttpServletRequest
- HttpServletResponse
- HttpSession
- 请求中所携带的请求参数
1. 逐个参数
只要保证请求参数名与该请求处理方法的参数名相同即可
还是在上面的例子中,修改index.jsp页面
提交参数给Controller
然后修改处理器类
@Controller
@RequestMapping(value = "/test")
public class MyController {
/**
* 逐个接收请求参数:
* 要求: 处理器(控制器)方法的形参名和请求中参数名必须一致。
* 同名的请求参数赋值给同名的形参
*
* 框架接收请求参数
* 1. 使用request对象接收请求参数
* String strName = request.getParameter("name");
* String strAge = request.getParameter("age");
* 2. springmvc框架通过 DispatcherServlet 调用 MyController的doOther()方法
* 调用方法时,按名称对应,把接收的参数赋值给形参
* doOther(strName,Integer.valueOf(strAge))
* 框架会提供类型转换的功能,能把String转为 int ,long , float, double等类型。
*
* 400状态码是客户端错误, 表示提交请求参数过程中,发生了问题。
*/
@RequestMapping(value = "/receive.do")
public ModelAndView doOther(String name, Integer age){
// 可以直接使用name和age
ModelAndView mv = new ModelAndView();
// 获取到表单中的数据
mv.addObject("myname",name);
mv.addObject("myage",age);
mv.setViewName("show");
return mv;
}
}
此时在show页面就可以的到数据了
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
show.jsp
这些都是从request作用域获取到的数据
姓名:${myname}
年龄: ${myage}
2. 校正请求参数名@RequestParam
请求中参数名和处理器方法的形参名不一样
在index.jsp页面
请求参数名和处理器方法的形参名不一致
主要就是处理器中方法的名字和请求参数的名字不一样,这个时候需要添加注解
/**
*请求中参数名和处理器方法的形参名不一样
* @RequestParam:逐个解决请求中参数名和形参名不一致的问题
* 属性:
* 1. value,请求中参数的名称
* 2. required 是一个boolean,默认是true
* true表示请求中必须包含此参数
* 作为:在处理器方法的形参前面定义
*/
@RequestMapping(value = "/receiveparam.do")
public ModelAndView receiveParam(@RequestParam(value = "username") String name,
@RequestParam(value = "rage") Integer age){
ModelAndView mv = new ModelAndView();
// 获取到表单中的数据
mv.addObject("myname",name);
mv.addObject("myage",age);
mv.setViewName("show");
return mv;
}
这样就可以在show页面接收到数据了
3. 请求参数中文乱码问题
对于前面所接收的post请求,若含有中文,则会出现中文乱码问题
Spring 对于请求参数中的中文乱码问题,给出了专门的字符集过滤器,解决方法:
在 web.xml 中注册字符集过滤器,即可解决 Spring 的请求参数的中文乱码问题
注意:最好将该过滤器注册在其它过滤器之前。因为过滤器的执行是按照其注册顺序进行的
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc.xml
1
springmvc
*.do
characterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
forceRequestEncoding
true
forceResponseEncoding
true
characterEncodingFilter
/*
4. 对象参数接收
将处理器方法的参数定义为一个对象,只要保证请求参数名与这个对象的属性同名即可
1. 定义一个Student类
package com.md.vo;
/**
* @author MD
* @create 2020-08-12 15:33
*/
// 用于保存请求的参数的
public class Student {
// 属性名和请求参数名一样
private String name;
private Integer age;
public Student() {
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2. 在index.jsp中
使用java对象来接收请求参数
3. 在处理器类
package com.md.controller;
@Controller
@RequestMapping(value = "/test")
public class MyController {
/**
* 处理器方法形参是java对象,这个对象的属性名和请求中参数名一样
* 框架会创建形参的java对象,给属性赋值,请求中的参数是name,框架会调用setName()
*
*/
@RequestMapping(value = "/receiveobject.do")
public ModelAndView receiveObject(Student student){
ModelAndView mv = new ModelAndView();
// 获取到表单中的数据
mv.addObject("myname",student.getName());
mv.addObject("myage",student.getAge());
mv.setViewName("show");
return mv;
}
}
此时show页面也是可以接收到数据的
三、处理器方法的返回值
使用@Controller 注解的处理器的处理器方法,其返回值常用的有四种类型:
- 第一种:ModelAndView
- 第二种:String
- 第三种:无返回值 void
- 第四种:返回自定义类型对象
1. 返回 ModelAndView
若处理器方法处理完后,需要跳转到其它资源,且又要在跳转的资源间传递数据,此时处理器方法返回 ModelAndView 比较好。当然,若要返回 ModelAndView,则处理器方法中需要定义 ModelAndView 对象。
在使用时,若该处理器方法只是进行跳转而不传递数据,或只是传递数据而并不向任何资源跳转(如对页面的 Ajax 异步响应),此时若返回 ModelAndView,则将总是有一部分多余:要么 Model 多余,要么 View 多余。即此时返回 ModelAndView 将不合适
之前的例子中一直用的就是这个
2. 返回 String
处理器方法返回的字符串可以指定逻辑视图名,通过视图解析器解析可以将其转换为物理视图地址
例如:
在index.jsp页面中
处理器方法返回String表示视图名称
在springmvc.xml中配置视图解析器
在处理器中,
@Controller
public class MyController {
/**
* 处理器方法返回String--表示逻辑视图名称,需要配置视图解析器
*/
@RequestMapping(value = "/return-view.do")
public String doReturnView(HttpServletRequest request,String name , Integer age){
System.out.println("doReturnView , name="+name+" "+"age="+age);
// 这个时候可以自己手动的添加数据到request作用域
request.setAttribute("myname",name);
request.setAttribute("myage",age);
// show , 是逻辑视图名称,项目中已经配置了视图解析器
// 在这里,框架对视图执行的是转发操作
return "show";
}
}
由于配置了视图解析器,此时返回字符串show,这个字符串与视图解析器中的 prefix、suffix 相结合,即可形成要访问的 URI
当然,也可以直接返回资源的物理视图名。不过,此时就不需要再在视图解析器中再配置前辍与后辍了
// 处理器方法返回的String,表示完整的视图路径,
// 此时不能配置视图解析器
@RequestMapping(value = "/return-view2.do")
public String doReturnView2(HttpServletRequest request,String name , Integer age){
System.out.println("---------doReturnView2--------- , name="+name+" "+"age="+age);
// 这个时候可以自己手动的添加数据到request作用域
request.setAttribute("myname",name);
request.setAttribute("myage",age);
// show , 是逻辑视图名称,项目中已经配置了视图解析器
// 在这里,框架对视图执行的是转发操作
return "/WEB-INF/view/show.jsp";
}
四、返回对象Object
处理器方法也可以返回 Object 对象。这个 Object 可以是 Integer,String,自定义对象,Map,List 等。但返回的对象不是作为逻辑视图出现的,而是作为直接在页面显示的数据出现的
返回对象,需要使用@ResponseBody 注解,将转换后的 JSON 数据放入到响应体中
1. 环境搭建
由于返回 Object 数据,一般都是将数据转化为了 JSON 对象后传递给浏览器页面的。而这个由 Object 转换为 JSON,是由 Jackson 工具完成的。所以需要导入 Jackson 的相关 Jar 包
1. 在pom.xml中
com.fasterxml.jackson.core
jackson-core
2.9.0
com.fasterxml.jackson.core
jackson-databind
2.9.0
2. 声明注解驱动
将 Object 数据转化为 JSON 数据,需要由消息转换器 HttpMessageConverter 完成。而转换器的开启,需要由
SpringMVC 使用消息转换器实现请求数据和对象,处理器方法返回对象和响应输出之间的自动转换
在springmvc.xml中添加
2. 返回自定义类型对象
返回自定义类型对象时,不能以对象的形式直接返回给客户端浏览器,而是将对象转换为 JSON 格式的数据发送给浏览器的
由于转换器底层使用了Jackson转换方式将对象转换为JSON数据,所以需要导入Jackson的相关 Jar 包
1. 定义数据类
package com.md.vo;
public class Student {
// 属性名和请求参数名一样
private String name;
private Integer age;
public Student() {
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
// set和get方法,
}
修改处理器
重点看注释
package com.md.controller;
@Controller
public class MyController {
/**
* 处理器方法返回一个Student,通过框架转为json,响应ajax请求
* @ResponseBody
* 作用:把处理器方法返回对象转为json后,通过HttpServletResponse输出给浏览器
* 位置:方法定义的上面
* 返回对象框架的处理流程:
* 1. 框架会把返回Student类型,调用框架的中ArrayList中每个类的canWrite()方法
* 检查那个HttpMessageConverter接口的实现类能处理Student类型的数据--MappingJackson2HttpMessageConverter
*
* 2.框架会调用实现类的write(), MappingJackson2HttpMessageConverter的write()方法
* 把林动的student对象转为json, 调用Jackson的ObjectMapper实现转为json
* contentType: application/json;charset=utf-8
*
* 3.框架会调用@ResponseBody把2的结果数据输出到浏览器, ajax请求处理完成
*/
@RequestMapping(value = "/returnStudentJson.do")
@ResponseBody
public Student doStudentJson(String name , Integer age){
// 调用service , 获取请求结果数据,Student对象表示结果数据
Student student = new Student("林动", 20);
// 会被框架转为json
return student;
}
}
在index.jsp页面
首先把jQuery导入进来,在webapp下建立js目录,jQuery复制进来就行了
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
3. 返回List集合
还是在上面的基础上,修改处理器MyController
package com.md.controller;
@Controller
public class MyController {
/**
* 处理器方法返回的是List
* 处理的方式和上面的一样,
*/
@RequestMapping(value = "/returnStudentJsonArray.do")
@ResponseBody
public List doStudentJsonArray(String name , Integer age){
List list = new ArrayList<>();
// 调用service , 获取请求结果数据,Student对象表示结果数据
Student student = new Student("林动", 20);
Student student1 = new Student("唐三", 20);
Student student2 = new Student("白昊天", 10);
list.add(student);
list.add(student1);
list.add(student2);
// 会被框架转为json的数组
return list;
}
}
此时在index.jsp页面上
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
这样点击按钮就可以获取到数据了
3. 返回字符串对象
若要返回非中文字符串,将前面返回数值型数据的返回值直接修改为字符串即可。
但若返回的字符串中带有中文字符 ,则接收方页面将会出现乱码 。此时需要使用@RequestMapping 的 produces 属性指定字符集
还是修改处理器
package com.md.controller;
@Controller
public class MyController {
/**
* 处理器方法返回的是String , String表示数据的,不是视图。
* 区分返回值String是数据,还是视图,看有没有@ResponseBody注解
*
* 如果有@ResponseBody注解,返回String就是数据,反之就是视图
*
*
* 默认使用“text/plain;charset=ISO-8859-1”作为contentType,导致中文有乱码,
* 解决方案:给RequestMapping增加一个属性 produces, 使用这个属性指定新的contentType.
*
*
* 返回对象框架的处理流程:
* 1. 框架会把返回String类型,调用框架的中ArtrayList中每个类的canWrite()方法
* 检查那个HttpMessageConverter接口的实现类能处理String类型的数据--StringHttpMessageConverter
*
* 2.框架会调用实现类的write(), StringHttpMessageConverter的write()方法
* 把字符按照指定的编码处理 text/plain;charset=ISO-8859-1
*
* 3.框架会调用@ResponseBody把2的结果数据输出到浏览器, ajax请求处理完成
*/
// 返回的是字符串,直接输出ajax请求,并不走过滤器,必须加属性才能解决乱码问题
@RequestMapping(value = "/returnStringData.do",produces = "text/plain;charset=utf-8")
@ResponseBody
public String doStringData(String name, Integer age){
return "我是返回的数据";
}
}
在index.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
五、 解读url-pattern
1. *.do
在没有特殊要求的情况下,SpringMVC 的中央调度器 DispatcherServlet 的*.do 或者 *.action, *.mvc
等
2. /
可以写为/,因为 DispatcherServlet 会将向静态资源的获取请求,例如.css、.js、.jpg、.png等资源的获取请求,当作是一个普通的 Controller 请求。中央调度器会调用处理器映射器为其查找相应的处理器,当然也是找不到的,
所以在这种情况下,所有的静态资源获取请求也均会报 404 错误
例如:
在index.jsp页面中存在一个访问图片的链接,演示将
1. 首先在Webapp下建立img目录,然后放一张图片
2. 然后在web.xml中
springmvc
/
修改index.jsp页面
此时图片是显示不出来的
3. 静态资源的访问
1. 使用
声 明 了
DefaultServletHttpRequestHandler 处理器对象。它会像一个检查员,对进入 DispatcherServlet的 URL 进行筛查,如果发现是静态资源的请求,就将该请求转由 Web 应用服务器默认的Servlet 处理。一般的服务器都有默认的 Servlet
在 Tomcat 中,有一个专门用于处理静态资源访问的 Servlet 名叫 DefaultServlet
所以,只需要在springmvc.xml中加入这个标签即可
2. 使用
在 Spring3.0 版本后,Spring 定义了专门用于处理静态资源访问请求的处理器ResourceHttpRequestHandler。并且添加了