目录
第二章、SpringMVC注解式开发
2.1 @RequestMappring定义请求规则
2.1.1 指定模块名称
@RequestMappring注解在类上,可以给类中的方法加一个公共的前缀,叫做模块名称。
修改Controller对象:
@Controller
/**
* @RequestMapping:
* value:所有请求地址的公共部分,叫做模块名称
* 位置:放在类的上面
*/
@RequestMapping("/test")
public class MyController {
@RequestMapping(value = "/some.do")
public ModelAndView doSome(HttpServletRequest request){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","欢迎使用springmvc做web开发" + request.getParameter("name"));
mv.addObject("fun","执行的是doSome方法");
mv.setViewName("show");
//返回mv
return mv;
}
@RequestMapping(value = "/other.do")
public ModelAndView doOther(){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","欢迎使用springmvc做web开发");
mv.addObject("fun","执行的是doFirst方法");
mv.setViewName("other");
return mv;
}
}
修改index.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>第一个springmvc项目</p>
<p><a href="test/some.do">发起some.do的get请求</a></p><br/>
<p><a href="test/other.do">发起first.do的get请求</a></p><br/>
</body>
</html>
2.1.2 对请求提交方式的定义
指定请求方式method属性。
修改Controller对象:
@Controller
@RequestMapping("/test")
public class MyController {
/**
* @RequestMapping: 请求映射
* 属性:method,表示请求的方式。它的值是RequestMethod类的枚举值
* 例如表示get请求方式,RequestMethod.GET
* post请求方式,RequestMethod.POST
*
* 如果请求方式错误,会发生405错误
*/
//指定some.do使用get请求方式
@RequestMapping(value = "/some.do",method = RequestMethod.GET)
public ModelAndView doSome(HttpServletRequest request){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","欢迎使用springmvc做web开发" + request.getParameter("name"));
mv.addObject("fun","执行的是doSome方法");
mv.setViewName("show");
//返回mv
return mv;
}
//指定other.do使用post请求方式
@RequestMapping(value = "/other.do",method = RequestMethod.POST)
public ModelAndView doOther(){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","欢迎使用springmvc做web开发");
mv.addObject("fun","执行的是doFirst方法");
mv.setViewName("other");
return mv;
}
//不指定请求方式,没有限制
@RequestMapping(value = "/first.do")
public ModelAndView doFirst(){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","欢迎使用springmvc做web开发");
mv.addObject("fun","执行的是doFirst方法");
mv.setViewName("first");
return mv;
}
}
修改index.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>第一个springmvc项目</p>
<p><a href="test/some.do">发起some.do的get请求</a></p><br/>
<form action="test/other.do" method="post">
<input type="submit" value="post请求other.do"/>
</form>
<br/>
<p><a href="test/first.do">发起first.do的get请求</a></p><br/>
<form action="test/first.do" method="post">
<input type="submit" value="post请求first.do"/>
</form>
</body>
</html>
2.2 处理器方法的参数
处理器方法可以包含以下四类参数,这些参数会在系统调用时由系统自动赋值,即开发人员可以在方法内直接使用。
①HttpServletRequest
②HttpServletResponse
③HttpSession
④请求中所携带的请求参数:逐个接收;对象接收
2.2.1 逐个参数接收
要求:处理器(控制器)方法的形参名和请求中参数名必须一致。同名的请求参数赋给同名的形参。名字对应即可,和形参位置无关。
index.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>提交参数给Controller</p>
<form action="receiveproperty.do" method="post">
姓名:<input type="text" name="name"/><br/>
年龄:<input type="text" name="age"/><br/>
<input type="submit" value="提交参数"/><br/>
</form>
</body>
</html>
Controller对象:
public class MyController {
/**
* 逐个接收请求参数:
* 要求:处理器(控制器)方法的形参名和请求中参数名必须一致
* 同名的请求参数赋值给同名的形参
* 框架接收请求参数
* 1.使用request对象接收请求参数
* String strName = request.getParameter("name");
* String strAge = request.getParameter("age");
* 2.springmvc框架通过DispatcherServlet调用MyController的doSome()方法
* 调用方法时,按名称对应,把接收的参数赋值给形参
* doSome(strName,Integer.valueOf(strAge))//此处如果age定义成了int类型,如果不填写,age为"",无法转换,因此改成Integer类型,当不填写时,会赋值null
* 框架会提供类型转换的功能,能把String转为int,long,float,double等类型。
*
* 400状态码:是客户端错误,表示提交请求参数过程中,发生了问题。
*/
@RequestMapping(value = "/receiveproperty.do")
public ModelAndView doSome(String name,Integer age){
System.out.println("doSome,name="+ name + ",age=" + age);
//可以在方法中直接使用name,age
ModelAndView mv = new ModelAndView();
mv.addObject("myname",name);
mv.addObject("myage",age);
//show是试图文件的逻辑名称(文件名称)
mv.setViewName("show");
//返回mv
return mv;
}
}
2.2.2 利用过滤器解决中文乱码问题
当使用get请求方式时,提交中文不存在乱码问题;当使用post请求方式时,如果提交参数值是中文,接收后显示在页面上会产生中文乱码问题,此时需要使用过滤器处理乱码的问题。
过滤器可以自定义,也可以使用框架中提供的过滤器CharacterEncodingFilter。
在web.xml文件中注册声明过滤器。
<!--注册声明过滤器,解决post请求乱码的问题-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!--设置项目中使用的字符编码-->
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<!--强制请求对象(HttpServletRequest)使用encoding编码的值-->
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<!--强制响应对象(HttpServletResponse)使用encoding编码的值-->
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<!--
/*:表示强制所有的请求先通过过滤器处理。
-->
<url-pattern>/*</url-pattern>
</filter-mapping>
2.2.3 校正请求参数名@RequestParam
指若请求URL携带的参数名称与处理方法中指定的参数名不相同时,则需要在处理方法参数钱,添加一个注解@RequestParam("请求参数名"),指定请求URL所携带参数的名称。该注解是对处理器方法参数进行修饰的,value属性指定请求参数的名称。
index.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>请求参数名和处理器方法的形参名不一样</p>
<form action="receiveparam.do" method="post">
姓名:<input type="text" name="rname"/><br/>
年龄:<input type="text" name="rage"/><br/>
<input type="submit" value="提交参数"/><br/>
</body>
</html>
Controller对象:
@Controller
public class MyController {
/**
* 请求中参数名和处理器方法的形参名不一样
* @RequestParam: 逐个接收请求参数中,解决请求中参数名形参名不一样的问题
* 属性: 1.value 请求中的参数名
* 2.required 是一个boolean,默认是true
* true:表示请求中必须包含此参数
* false:表示请求中可以没有此参数
* 位置:在处理器方法的形参定义的前面
*/
@RequestMapping(value = "/receiveparam.do")
public ModelAndView receiveParam(@RequestParam(value = "rname",required = false) String name,
@RequestParam(value = "rage",required = false) Integer age){
System.out.println("doSome,name="+ name + ",age=" + age);
//可以在方法中直接使用name,age
ModelAndView mv = new ModelAndView();
mv.addObject("myname",name);
mv.addObject("myage",age);
//show是试图文件的逻辑名称(文件名称)
mv.setViewName("show");
//返回mv
return mv;
}
}
2.2.4 对象参数接收
将处理器方法的参数定义为一个对象,只要保证请求参数名与这个对象的属性同名即可。
实体类:
//保存请求参数值的一个普通类
public class Student {
//属性名和请求中参数名要一样
private String name;
private Integer age;
}
public class School {
private String name;
}
index.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>使用java对象接收请求参数</p>
<form action="receiveobject.do" method="post">
姓名:<input type="text" name="name"/><br/>
年龄:<input type="text" name="age"/><br/>
<input type="submit" value="提交参数"/><br/>
</form>
</body>
</html>
Controller对象:
@Controller
public class MyController {
/**
* 处理器方法形参是java对象,这个对象的属性名和请求中参数名是一样的。
* 框架会创建形参的java对象,给属性赋值。请求中的参数是name,框架会调用setName()
* 如果两个不同的类有一样名字的属性,会共同赋值。
*/
@RequestMapping(value = "/receiveobject.do")
public ModelAndView receiveObject(Student myStudent, School mySchool){
//可以在方法中直接使用name,age
ModelAndView mv = new ModelAndView();
mv.addObject("myname",mySchool.getName());
mv.addObject("myage",myStudent.getAge());
mv.addObject("mystudent",myStudent);
mv.addObject("myschool",mySchool);
//show是试图文件的逻辑名称(文件名称)
mv.setViewName("show");
//返回mv
return mv;
}
}
2.3 处理器方法的返回值
2.3.1 返回ModelAndView
若处理器方法处理完后,需要跳转到其它资源,且又要在跳转的资源间传递数据,此时处理器方法返回ModelAndView比较好。当然,若要返回ModelAndView,则处理器方法中需要定义 ModelAndView对象。
在使用时,若该处理器方法只是进行跳转而不传递数据,或只是传递数据而并不向任何资源跳转(如对页面的Ajax异步响应),此时若返回ModelAndView,则将总是有一部分多余:要么Model多余,要么View多余,即此时返回ModelAndView将不合适。
2.3.2 返回String
处理器方法返回的字符串可以指定逻辑视图名,通过视图解析器解析可以将其转换为物理视图地址。
index.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>处理器方法返回String表示视图名称</p>
<form action="returnString-view.do" method="post">
姓名:<input type="text" name="name"/><br/>
年龄:<input type="text" name="age"/><br/>
<input type="submit" value="提交参数"/><br/>
</form>
<br/>
<p>处理器方法返回String表示视图完整路径</p>
<form action="returnString-view2.do" method="post">
姓名:<input type="text" name="name"/><br/>
年龄:<input type="text" name="age"/><br/>
<input type="submit" value="提交参数"/><br/>
</form>
<br/>
</body>
</html>
Controller对象:
@Controller
public class MyController {
/**
* 处理器方法返回String---表示逻辑视图名称,需要配置视图解析器
*/
@RequestMapping(value = "/returnString-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:逻辑视图名称,项目中配置了视图解析器
//框架对试图执行forward转发操作
return "show";
}
/**
* 处理器方法返回String---表示完整视图路径,此时不能配置视图解析器
*/
@RequestMapping(value = "/returnString-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);
//完整视图路径,项目中不能配置视图解析器
//框架对试图执行forward转发操作
return "/WEB-INF/view/show.jsp";
}
}
2.3.3 返回void
若处理器对请求处理后,无需跳转到其他任何资源,此时可以让处理器方法返回void。
对于处理器方法返回void的应用场景,ajax响应。ajax请求服务端返回的就是数据,和视图无关。
1.在maven中加入jackson依赖。
<!--Jackson依赖-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
2.引入jQuery库。
3.index.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="js/jquery-3.4.1.js"></script>
<script type="text/javascript">
$(function () {
$("button").click(function () {
$.ajax({
url:"returnVoid-ajax.do",
data:{
name:"zhangsan",
age:20
},
type:"post",
dataType:"json",//我需要的是json格式的数据
success:function (resp) {
//resp从服务器端返回的是json格式的字符串{"name":"zhangsan","age":20}
//jquery会把字符串转为json对象,赋值给resp形参。
alert(resp.name + " " + resp.age);
}
})
})
})
</script>
</head>
<body>
<button id="btn">发起ajax请求</button>
</body>
</html>
4.Controller对象:
@Controller
public class MyController {
/**
* 处理器方法返回void,响应ajax请求
* 手工实现ajax,json数据:代码有重复的 1.java对象转为json;2.通过HttpServletResponse输出json数据
*/
@RequestMapping(value = "/returnVoid-ajax.do")
public void doReturnVoidAjax(HttpServletResponse response, String name, Integer age) throws IOException {
System.out.println("doReturnVoidAjax,name = " + name + ",age = " + age);
//处理ajax,使用json做数据的格式
//假设现在service调用完成了,使用Student表示处理结果
Student student = new Student();
student.setName(name);
student.setAge(age);
String json="";
//把结果的对象转为json格式的数据
if(student != null){
ObjectMapper om = new ObjectMapper();
json = om.writeValueAsString(student);
System.out.println(json);
}
//输出数据,响应ajax的请求
response.setContentType("application/json;charset=utf-8");//告诉浏览器是一个json格式的数据
PrintWriter pw = response.getWriter();
pw.println(json);
pw.flush();
pw.close();
}
}
2.3.4 返回对象Object---原理解释
处理器方法也可以返回Object对象。这个Object可以是Integer,String,自定义对象,Map,List等。但返回的对象不是作为逻辑视图出现的,而是作为直接在页面显示的数据出现的。
返回对象,需要使用@ResponseBody注解,将转换后的JSON数据放入到响应体中。
1.在maven中加入jackson依赖。
<!--Jackson依赖-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
2.声明注解驱动。将Object数据转化为JSON数据,需要由消息转换器HttpMessageConverter完成。而转换器的开启,需要由<mvc:annotation-driven/>来完成。在springmvc配置文件中声明注解驱动,会自动创建HttpMessageConveter接口的8个实现类对象。
注解驱动的功能:完成java对象到json、xml、text、二进制等数据格式的转换。
HttpMessageConveter接口:消息转换器。功能是定义了java转为json、xml等数据格式的方
法,这个接口有很多的实现类,这些实现类完成了java对象到json、java对象到xml、java对象
到二进制数据的转换。
canWrite和write方法是控制器类把结果输出到浏览器时使用的。
canWrite:作用是检查处理器方法的返回值,能不能转为var2表示的数据格式。
MediaType:表示数据格式的,如json、xml等等。
write:把处理器方法的返回值对象,调用jackson中的ObjectMapper转为json字符串。
json = om.writeValueAsString(student);
八个实现类:
代码实现:
<!--注解驱动-->
<mvc:annotation-driven />
3.在处理器方法的上面加入@ResponseBody注解。通过HttpServletResponse输出数据,响应ajax请求的。这个注解完成的功能就是手动完成部分中的:
response.getWriter();
pw.println(json);pw.flush();
pw.close();
2.3.5 返回自定义对象
index.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="js/jquery-3.4.1.js"></script>
<script type="text/javascript">
$(function () {
$("button").click(function () {
$.ajax({
url:"returnStudentJson.do",
data:{
name:"zhangsan",
age:20
},
type:"post",
dataType:"json",//我需要的是json格式的数据
success:function (resp) {
//resp从服务器端返回的是json格式的字符串{"name":"zhangsan","age":20}
//jquery会把字符串转为json对象,赋值给resp形参。
alert(resp.name + " " + resp.age);
}
})
})
})
</script>
</head>
<body>
<button id="btn">发起ajax请求</button>
</body>
</html>
Controller对象:
@Controller
public class MyController {
/**
* 处理器方法返回一个Student,通过框架转为json,响应ajax请求
* @ResponseBody:
* 作用:把处理器方法返回的对象转为json后,通过HttpServletResponse输出给浏览器。
* 位置:方法的定义上面,和其他注解没有顺序的关系。
* 返回对象框架的处理流程:
* 1.框架会把返回Student类型,调用框架中的ArrayList<HttpMessageConverter>中每个类的canWrite()方法,
* 检查那个HttpMessageConverter接口的实现类能处理Student类型的数据---MappingJackson2HttpMessageConverter
*
* 2.框架会调用实现类的write(),即MappingJackson2HttpMessageConverter的write()方法
* 把"xxy"的student对象转为json格式,调用jackson的ObjectMapper实现转为json
* 默认contextType:application/json;charset=utf-8
*
* 3.框架会调用@ResponseBody把2的结果数据输出到浏览器,ajax请求处理完成
*/
@RequestMapping(value = "/returnStudentJson.do")
@ResponseBody
public Student soStudentJsonObject(String name,Integer age){
//调用service,获取请求结果数据,Student对象表示结果数据
Student student = new Student();
student.setName("xxy");
student.setAge(24);
return student;//会被框架转为json
}
}
2.3.6 返回List对象
index.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="js/jquery-3.4.1.js"></script>
<script type="text/javascript">
$(function () {
$("button").click(function () {
$.ajax({
url:"returnStudentJsonArray.do",
data:{
name:"zhangsan",
age:20
},
type:"post",
dataType:"json",//我需要的是json格式的数据
success:function (resp) {
//resp从服务器端返回的是json格式的字符串{"name":"zhangsan","age":20}
//jquery会把字符串转为json对象,赋值给resp形参。
$.each(resp,function (i,n) {
alert(n.name + " " + n.age)
})
}
})
})
})
</script>
</head>
<body>
<button id="btn">发起ajax请求</button>
</body>
</html>
Controller对象:
@Controller
public class MyController {
/**
* 处理方法返回List<Student>
* 返回对象框架的处理流程:
* 1.框架会把返回ListStudent<>类型,调用框架中的ArrayList<HttpMessageConverter>中每个类的canWrite()方法,
* 检查那个HttpMessageConverter接口的实现类能处理Student类型的数据---MappingJackson2HttpMessageConverter
*
* 2.框架会调用实现类的write(),即MappingJackson2HttpMessageConverter的write()方法
* 把多个student对象转为json格式,调用jackson的ObjectMapper实现转为json array
* 默认contextType:application/json;charset=utf-8
*
* 3.框架会调用@ResponseBody把2的结果数据输出到浏览器,ajax请求处理完成
*/
@RequestMapping(value = "/returnStudentJsonArray.do")
@ResponseBody
public List<Student> soStudentJsonObjectArray(String name, Integer age){
List<Student> list = new ArrayList<>();
//调用service,获取请求结果数据,Student对象表示结果数据
Student student1 = new Student();
student1.setName("xxy");
student1.setAge(24);
list.add(student1);
Student student2 = new Student();
student2.setName("张三");
student2.setAge(20);
list.add(student2);
return list;
}
}
2.3.7 返回String对象
index.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="js/jquery-3.4.1.js"></script>
<script type="text/javascript">
$(function () {
$("button").click(function () {
$.ajax({
url:"returnStringData.do",
type:"post",
dataType:"text",
success:function (resp) {
alert("返回的是文本数据:" + resp)
}
})
})
})
</script>
</head>
<body>
<button id="btn">发起ajax请求</button>
</body>
</html>
Controller对象:
@Controller
public class MyController {
/**
* 处理器方法返回的是String,这里String表示数据的,不是之前讲的视图。
* 区分返回值String是数据,还是视图,看有没有@ResponseBody注解
* 如果有@ResponseBody注解,返回String就是数据,反之就是视图。
*
* 默认使用"text/plain;charset=ISO-8859-1"作为contentType,导致中文有乱码
* 解决方案:给RequestMapping增加一个属性produces,使用这个属性指定新的contentType
*
* 返回String对象框架的处理流程:
* 1.框架会把返回String类型,调用框架中的ArrayList<HttpMessageConverter>中每个类的canWrite()方法,
* 检查那个HttpMessageConverter接口的实现类能处理String类型的数据---StringHttpMessageConverter
*
* 2.框架会调用实现类的write(),即MappingJackson2HttpMessageConverter的write()方法
* 把字符串按照指定的编码处理text/plain;charset=ISO-8859-1
* 这里过滤器的设置是无效的,因为ajax请求不会经过过滤器。
*
* 3.框架会调用@ResponseBody把2的结果数据输出到浏览器,ajax请求处理完成
*/
@RequestMapping(value = "/returnStringData.do",produces = "text/plain;charset=utf-8")
@ResponseBody
public String doStringData(){
return "hello springmvc 返回对象,表示数据";
}
}
PS:根据动力节点课程整理,如有侵权,联系删除。