目录
- 前提
- 我们现在需要考虑的
- 第一个需要考虑的:SpringMVC中单元方法如何获取请求数据
-
- 问题:
- 解决:
- 实现:
- SpringMVC对restful请求的支持
-
- 问题:
- 解决:
- 实现:
- restful格式请求后台获取请求数据
前提
之前我们已经优化了controller层,也就是对servlet的书写
深度学习springMVC(一)为什么要学习springMVC,实现基本使用流程(看不懂你打我)
通过以上的基本流程,我们已经跑通了,从浏览器输入地址,到controller里面的,执行controller层里面对应方法里面的逻辑。
我们现在需要考虑的
已经跑通了逻辑,现在我们需要考虑的就是如何写里面的逻辑代码,如何接受请求的数据,如何把处理后的数据返回给前端。
第一个需要考虑的:SpringMVC中单元方法如何获取请求数据
问题:
在学习了SpringMVC的基本使用流程后,发现SpringMVC将Servlet进行了封装,在外部声明控制器类,并在其中声明单元方法。DispatcherServlet根据请求动态的调用对应的单元方法处理请求,所以我们需要在单元方法中声明请求处理的逻辑代码。而请求的处理需要获取本次请求的请求数据,那么在单元方法中如何获取请求数据呢?
解决:
请求被tomcat接受后会调用DispatcherServlet处理请求,Tomcat会将封装了此次请求数据的request对象作为实参传递给DispatcherServlet的service方法,而service方法中又会根据请求调用对应的单元方法处理请求,所以只需要在service方法中将请求数据作为实参传递给单元方法使用即可。注意,单元方法必须声明对应的形参接收数据。
实现:
方式一:紧耦方式
DispatcherServlet中的service方法直接将此次请求的request对象传递给调用的单元方法即可。同时在单元方法上声明形参HttpServletRequest来接收request实参即可。
举例:
代码语言:javascript复制①在控制器类中声明请求处理单元方法,并在单元方法上声明形参,形参类型为HttpServletRequest,接收DispactherServlet传递的封装了此次请求的请求数据的request对象。
②在单元方法中使用request.getParameter(“键名”)获取请求数据
③在单元方法中声明请求处理的逻辑代码
代码语言:javascript复制@Controller
public class MyController {
/**
* 紧耦合方式获取请求数据
* 作用:获取请求数据
* 使用:在单元方法上声明HttpServletRequest形参,用来接收
* DispatcherServlet传递的封装了此次请求的请求数据的request对象。
* 然后我们在单元方法中正常的使用getParameter等方法获取请求数据。
* @return
*/
//声明单元方法:处理请求
@RequestMapping("req")
public String demoReq(HttpServletRequest request){
//获取请求数据
String uname= request.getParameter("uname");
int age= Integer.parseInt(request.getParameter("age"));
//处理请求
//响应结果
System.out.println("MyController.demoReq:我是紧耦合方式获取请求数据--" uname ":" age);
return "aa";
}
方式二:解耦方式
DispatcherServlet在其service方法中将请求数据根据需求从request对象中获取出来后,将数据直接传递给对应的单元方法使用。同时在单元方法上直接声明对应的形参接收请求数据即可。
1.形参属性名即为请求数据的键名
举例:
代码语言:javascript复制 /**
* 解耦合方式获取请求数据之请求数据的键名和单元方法的形参名一致
* 使用:
* 在单元方法上声明形参来接收请求数据,要求形参名和请求数据的键名一致。
* 注意:
* DispatcherServlet底层按照形参即是请求数据键名的方式获取请求数据,并且
* 将获取到的请求属性按照形参的类型转换后,传递给单元方法。
*
* @param uname
* @param age
* @return
*/
//声明单元方法:处理请求--解耦方式
@RequestMapping("argName")
public String demoArgName(String uname,int age){
//处理请求
System.out.println("MyController.demoArgName:我是解耦合方式获取请求数据--" "uname" ":" age);
//响应结果
return "aa";
}
//声明单元方法:处理请求---请求数据键名和单元方法的形参名不一致
2.形参名和请求数据的键名不一致
代码语言:javascript复制 /**
* 请求数据键名和单元方法形参名不一致
* 注意:
* 不会报错,DispatcherServlet底层仍然会将形参名作为请求数据的键名来获取请求数据
* 只不过获取不到,返回null值,DispatcherServlet会null值传递给单元方法。
* 注意2:
* 如果形参的类型为int等类型,当请求中没有对应的请求数据时。会出现类型转换异常。
* 尽量声明形参类型为包装类的类型
* @RequestParam注解解决:
* 使用:
* 在和请求数据键名不用的形参前使用该注解
* 属性:
* value:请求数据的键名。
* defaultValue:当请求中没有对应的请求数据时的默认值
* required:表明该形参必须赋值。
* true:表示必须
* false:表示非必须。
* 注意:required属性和defaultValue不要一起使用
*
* @param name
* @param age
* @return
*/
@RequestMapping("argNotName")
public String demoArgNotName(@RequestParam(value = "uname",defaultValue = "123") String name, Integer age){
//处理请求
System.out.println("MyController.demoArgNotName:请求数据键名和单元方法形参名不一致:" name ":" age);
//响应结果
return "aa";
}
3.使用实体类对象获取请求数据
代码语言:javascript复制 /**
*解耦方式使用实体类对象接收请求
* 要求:
* 实体类的属性和请求数据的键名一致,必须提供get/set方法。
* 注意:
* 实体类的属性类型使用包装类,避免请求中没有对应的数据时出现类型转换异常。
*/
@RequestMapping("argObject")
public String demoArgObject(User user){
//处理请求
System.out.println("MyController.demoArgObject:请求数据使用实体类对象接收:" user);
//响应结果
return "aa";
}
4.获取同键不同值的请求数据
代码语言:javascript复制 /**
* 解耦合方式获取同键不同值的数据
* 要求:
* 使用String类型的数组来接收,形参名为请求数据的键名
*/
@RequestMapping("argKeyNotValue")
public String demoArgKeyNotValue(String uname,Integer age,String[] fav){
//处理请求数据
System.out.println("MyController.demoArgKeyNotValue:获取同键不同值的请求数据:" uname ":" age ":" fav[0]);
//响应结果
return "aa";
}
5.混合使用紧耦和解耦方式获取请求数据
代码语言:javascript复制 /**
* 单元方法请求数据获取方式混合使用
*/
@RequestMapping("argAll")
public String demoArgAll(User user,String uname,String[] fav,HttpServletRequest request){
//处理请求
System.out.println("MyController.demoArgAll:获取请求数据方式混合使用:" user
":" uname ":" fav[0] ":"
request.getParameter("uname"));
//响应结果
return "aa";
}
SpringMVC对restful请求的支持
问题:
目前我们浏览器发起请求给服务器的时候,一般我们常用的请求方式有两个,get 和post方式。不管get还是post方式,请求数据的格式都是键值对格式,get 方式请求数据是在请求地址上以问号隔开的形式,拼接在请求地址后,post请求 呢是有专门的请求实体的,例如:
get方式请求:
localhost:8080/project/aa?uname=zhangsan&age=18
post方式请求:
地址:localhost:8080/project/aa
请求数据:
uname=zhangsan
age=18
要求我们后台获取请求数据的代码,必须按照指定的键名来获取请求数据。键名
就是请求数据的键名。这样造成,一旦请求数据的键名发生变更,造成后台的逻辑
代码也需要进行变更。前台的请求数据的键名和后台的逻辑代码之间的耦合性过 高,造成前台和后台的开发过程中相互依赖性过高。怎么办?
解决:
让前台和后台代码之间进行解耦。也就说不再让请求请求数据的键名造成前后台
代码之间的依赖。前台请求数据的键名发生变更,不影响后台逻辑代码的正常执行
实现:
请求数据不再以键值对的形式发送给后台使用。直接发送数据本身给后台即可。
既然请求数据不再使用键值对,请求数据必须按照指定的格式来进行发送。使用
restful格式。
restful格式:
传统的get方式请求格式:
localhost:8080/project/aa?uname=zhangsan&age18
restful请求格式:
localhost:8080/project/aa/zhangsan/18
注意:
restful格式要求请求数据作为请求地址的一部分发送给后台使用。
restful格式请求后台获取请求数据
代码语言:javascript复制 /***
* SpringMVC处理restful格式请求
*
* 1.
* 在 @RequestMapping注解中可以使用{字母}来声明单元方法的拦截范围
* 比如:
* @RequestMapping("aa/{uname}/{age}")
* 表示请求地址要请求的单元方法以aa开头,后面为两位任意。
* 2.
* 我们可以在单元方法的形参声明上使用注解@PathVariable
* 来告诉DispatcherServlet将请求地址中的数据截取后作为
* 实参传递给单元方法使用,默认按照地址占位中的参数名和
* 形参名一致的规则赋值,如果不一致可以在@PathVariable中
* 指明赋值@PathVariable("un")
*
* 3.
* 注意:
* 说白了SpringMVC的restful格式的支持就是单元方法模糊拦截 注解声明来实现。
*
*/
@RequestMapping("aa/{un}/{age}")
public String demoResful(@PathVariable("un") String uname,@PathVariable Integer age){
//处理请求
System.out.println("MyController.demoResful:SpringMVC处理restful格式请求:" uname ":" age);
//响应结果
return "aa";
}