文章目录
一、springMVC返回值分类
1.1 返回值为String字符串
返回值为string的话,字符串的内容表示视图的名称,默认情况下时转发请求(视图解析器),其中也可以修改为重定向。
1.1.1 返回值为string,方法中存在请求转发
如果方法中返回值为请求转发,例如:return “forward:index.jsp”;那么程序就可以请求转发到指定的路径。相当于
“request.getRequestDispatcher(“url”).forward(request,response)”,请求可以转发到jsp,也可以到其他的控制器方法
注意:“forward:转发的JSP路径”,不走视图解析器,所以需要编写完整的路径。如果使用了forward,则路径必须写成实际视图的路径
//如果方法体中也有请求转发重定向,则String也无效。
@RequestMapping("show4")
public String show4(){
System.out.println("返回值是String");
//默认情况就是请求转发回去index.jsp页面
// return "index";
//另一种请求转发
return "forward:index.jsp";
}
1.1.2 返回值为string,方法中存在重定向
如果方法中返回值为重定向,就需要在返回值里面使用redirect
//重定向 不支持视图解析器
@RequestMapping("show5")
public String show5(){
System.out.println("返回值是String,重定向");
return "redirect:index.jsp";
}
相当于“response.sendRedirect(url)”,如果重定向到jsp页面的话,那么jsp页面不能写到WEB-INF目录下。否则无法找到
1.1.3 另一种返回方式
@RequestMapping("show6")
public String show6(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("返回值是String,重定向");
ModelAndView modelAndView = new ModelAndView();
//请求会走这里 不会参与下面的return
request.getRequestDispatcher("/index.jsp").forward(request,response);
response.getWriter().write("返回值是string,且中间有一个请求转发");
return "redirect:index.jsp";
}
最后的返回值如果是重定向,方法中又存在请求转发的情况,那么请求则会按着请求转发去执行
1.2 返回字符串的应用场景
应用场景1:直接返回视图名称,例如跳转到某个功能主页。
问题:我们可以直接通过/+文件名称.jsp直接访问页面,为什么请求springMVC,由springMVC控制返回的页面
**结果:**对于webapp目录下面的页面,用户可以直接访问。但是,通常情况下为了页面安全的考虑,一般会将相关的页面资源放在
WEB-INF目录下,这个目录下面的资源用户不能直接访问,只能通过后台的资源跳转进行访问。
比如:登录之后才能查看的信息,我们就需要把这些资源放在该目录下,controller层根据用户是否登录来进行页面的跳转。可以保证资源的
安全。
应用场景2:controller在登录成功时候重定向主页面,失败请求转发回登录页面
这个时候就需要使用到上面方法中存在重定向和请求转发,这时候返回的资源路径不会走视图解析器,而是直接转发或重定向到指定的路径
重定向后的标签不能加WEB-INF,重定向是客户端重新发送的请求,WEB-INF目录下的页面依旧访问不到,请求转发的话可以加WEB-INF
问题:为什么controller在登录成功时候重定向主页面,失败请求转发回登录页面
回答:当客户端登录成功的话。使用请求转发会主页面的话,浏览器的地址栏的url保留的还是登录时候的请求信息,如果这时候我们重
新刷新页面,那么就会造成二次表单提交的情况,增大服务器的压力。所以登录成功的话需要重定向到主页面,这个时候浏览器的地址栏就
会是主页面的url。
当客户端登录失败,我们需要给用户提供一定的提示信息,比如:用户名还是密码输入错误的情况。如果使用重定向的话,这时候用户无法
获取到服务器响应回的提示信息。重定向是两次请求,第二次的请求是不能够获取第一次请求中的数据(除非将错误信息存放在session和
application域中,不建议这样做)。使用转发请求返回登录页面,那么就可以获取到request域中的数据。所以登录失败请求转发到登录页面
1.3 返回值为ModelAndView
ModelAndView对象是Spring提供的一个对象,可以用来调整具体的JSP视图。里面可以封装视图和模型(存储的数据在request域中)
1.3.1 正常的返回
前端请求Controller的资源,返回值为ModelAndView,并且其中的addObject存放的数据。前台可以使用el表达式进行获取存放的数据
@RequestMapping("show1")
public ModelAndView show1(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
modelAndView.addObject("msg","show1执行,返回值是ModelAndView");
return modelAndView;
}
1.3.2 方法中存在重定向或者请求转发
方法体中有请求转发和重定向操作,ModelAndView无效,请求会根据请求转发的内容进行发送。
其中springMVC的视图解析器在有请求转发或者重定向的时候无效,那么就需要填写实际视图的完整路径
@RequestMapping("show2")
public ModelAndView show2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ModelAndView modelAndView = new ModelAndView();
//请求转发脱离了springMVC的规则,不应用视图解析器。
request.getRequestDispatcher("/index.jsp").forward(request,response);
//为modelandView设置
modelAndView.setViewName("index");
modelAndView.addObject("msg","show1执行,返回值是ModelAndView");
return modelAndView;
}
//重定向
@RequestMapping("show3")
public ModelAndView show3(HttpServletResponse response) throws ServletException, IOException {
ModelAndView modelAndView = new ModelAndView();
//重定向脱离了springMVC的规则,不应用视图解析器。
response.sendRedirect("/index.jsp");
//为modelandView设置
modelAndView.setViewName("index");
modelAndView.addObject("msg","show1执行,返回值是ModelAndView");
return modelAndView;
}
使用场景
应用场景比较随意,可以用来做页面的跳转(modelAndView.setViewName()),也可以在跳转到页面的时候携带一些数据
(modelAndView.addObject())
1.4 返回值为void
当返回值是void的时候,默认请求转发到【视图解析器前缀+方法名+视图解析器后缀】的界面,如果没有该页面存在,那么就会报404错误
二、响应json数据
ResponseBody这个注解可以让我们返回的内容以json形式。json字符串和JavaBean对象互相转换的过程中,需要使用jackson的jar包。
在pom.xml的文件中引入jar包。
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.2</version>
</dependency>
controller代码
@RequestMapping("show8")
@ResponseBody
public Map<String,Object> show8() throws IOException, ServletException {
Map<String,Object> map=new HashMap<>();
map.put("result",true);
map.put("msg","返回Map转换为json");
return map;
// 响应头:Content-Type: application/json;charset=UTF-8
}
当我们使用了该注解,那么返回值就会是json的形式返回
我们在返回值是String类型的情况下,加上注解,那么注解会将返回的将会是一个字符串
@RequestMapping("show9")
@ResponseBody
public String show9() {
System.out.println("使用@ResponseBody注解,返回值是一个string");
//默认返回字符串,就会使用视图解析器前缀加后缀拼接的路径,如果加了@ResponseBody注解。返回的将会是一个字符串
return "index";
}
另外,我们返回值是一个List集合,集合中是实体类Account
//使用集合返回,对象为实体类
@RequestMapping("show10")
@ResponseBody
public List<Account> show10(HttpServletResponse response) throws IOException {
List<Account> list = new ArrayList<>();
list.add(new Account(1,"123",new Date()));
list.add(new Account(2,"456",new Date()));
list.add(new Account(3,"789",new Date()));
//Date转换为毫秒值
System.out.println(list.toString());
return list;
}
默认情况下,Date类型前端解析的会是毫秒值
使用@JsonFormat(pattern = “yyyy-MM-dd”) 可以指定返回前台的格式
public class Account {
private Integer aid;
private String aname;
@JsonFormat(pattern = "yyyy-MM-dd")//后台返回前台的格式
//前台发送数据格式是默认的进行传递 yyyy/MM/dd 解析Account类的发送格式
//当前端发送数据格式为json时,需要按着@JsonFormat的格式进行传递
private Date abirthday;
}
补充一个前台发送表单数据的形式
对于同一个form表单莱索,获取表单中的数据
<form id="formAjax">
aid:<input name="aid" id="aid" /><br>
aname:<input name="aname" id="aname" /><br>
abirthday:<input name="abirthday" id="abirthday"/><br>
<input type="button" id="btn1" value="ajax提交数据,请求数据类型默认形式,数据格式为json">
<input type="button" id="btn2" value="ajax提交数据,请求数据类型默认形式,数据格式为json,使用jquery序列化">
<input type="button" id="btn3" value="ajax提交数据,请求数据类型为json ">
</form>
<script>
$(function(){
$("#btn1").click(function () {
var list={
aid:$("#aid").val(),
aname:$("#aname").val(),
abirthday:$("#abirthday").val()
}
$.ajax({
type:"POST",
data:list,
url: "test1" ,
success:function (result) {
console.log(result)
console.log(result.msg)
}
})
})
$("#btn2").click(function () {
//将表单中的控件和值 自动获取,是一个字符串
var list= $("#formAjax").serialize();
console.log($("#formAjax").serialize())
//aid=1&aname=123&abirthday=2020%2F02%2F02
$.ajax({
type:"POST",
data:list,
url: "test1" ,
success:function (result) {
console.log(result)
console.log(result.msg)
}
})
})
$("#btn3").click(function () {
var list={
aid:$("#aid").val(),
aname:$("#aname").val(),
abirthday:$("#abirthday").val()
}
$.ajax({
type:"POST",
data:JSON.stringify(list),
url: "test2",
contentType:"application/json;charset=UTF-8",
success:function (result) {
console.log(result)
console.log(result.msg)
}
})
})
});
</script>
第一种:
发送内容: aid=1&aname=123&abirthday=2020%2F02%2F02
var list={
aid:$("#aid").val(),
aname:$("#aname").val(),
abirthday:$("#abirthday").val()
}
第二种:使用jquery序列化
发送内容:aid=1&aname=123&abirthday=2020%2F02%2F02
var list= $("#formAjax").serialize();
第三个方法:JSON.stringify(list):方法可以将JavaScript 对象转换为 JSON 字符串
后台java代码
前端发送ajax 默认请求类型 application/x-www-form-urlencoded; charset=UTF-8 ,但是发送形式还是以字符串发送
后台可以直接通过对象获取数据,并且封装到对象中
@Controller
public class RequestBodyTest {
//前端发送ajax 默认请求类型 application/x-www-form-urlencoded; charset=UTF-8 发送形式还是以字符串发送
//后台可以直接通过对象获取数据,并且封装到对象中 aid=1&aname=123&abirthday=2020%2F02%2F02
//jquery的序列化也是如此 aid=1&aname=123&abirthday=2020%2F02%2F02
@RequestMapping("/test1")
@ResponseBody
public Map<String, Object> test1(Account account){
System.out.println("jiehsu ");
Map<String, Object> map=new HashMap<>();
map.put("retsult",true);
map.put("msg",account.getAname()+account.getAid());
System.out.println(JSON.toJSONString(account,true));
return map;
}
//前端发送的数据格式为json
//使用@RequestBody 之后 前台发送的字符串格式应该设置为json字符串的格式
//{"aid":"1","aname":"2","abirthday":"2020-02-02"}
//get提交 没有请求体 取不到
@RequestMapping("/test2")
@ResponseBody
public Map<String, Object> test2( @RequestBody Account account){
System.out.println("格式ajax");
Map<String, Object> map=new HashMap<>();
map.put("retsult",true);
map.put("msg",account.getAname()+account.getAid());
System.out.println(JSON.toJSONString(account,true));
return map;
}
//@RequestBody 注解 将请求体中的数据转换为字符串
@RequestMapping("/test3")
@ResponseBody
public Map<String, Object> test3( @RequestBody String string) {
Map<String, Object> map = new HashMap<>();
map.put("retsult", true);
map.put("msg", string);
System.out.println(string);
return map;
}
}