课程链接:SpringMVC教程
开始时间:2022-01-23
实际开发过程中,请求参数名和处理器方法的形参名可能不一样
比如一个是前端工程师写的,提交的参数名和我们写的不一样,这个时候需要用RequestParam注解来统一。
例如index.jsp中写
<p>请求参数名和处理器方法的形参名不一样p>
<form action="receiveparam.do" method="post">
姓名:<input type="text" name="rname"> <br/>
年龄:<input type="text" name="rage"> <br/>
<input type="submit" value="提交参数">
form>
在MyController里面进行处理
使用注解
@RequestParam(value=“传进来的参数名”,required=false) String “自己定义后面用的参数名”
required默认是true,代表着传参的时候必须有值,没有就报错
@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
//处理some.do请求了。 相当于service调用处理完成了。
ModelAndView mv = new ModelAndView();
mv.addObject("myname",name);
mv.addObject("myage",age);
//show是视图文件的逻辑名称(文件名称)
mv.setViewName("show");
return mv;
}
还可以用对象来接收参数最常用
保存参数值到对象里面
属性名和请求名要一致
/**
* 处理器方法形参是java对象, 这个对象的属性名和请求中参数名一样的
* 框架会创建形参的java对象, 给属性赋值。 请求中的参数是name,框架会调用setName()
* @return
*/
@RequestMapping(value = "/receiveobject.do")
public ModelAndView receiveParam( Student myStudent){
System.out.println("receiveParam, name="+myStudent.getName()+" age="+myStudent.getAge());
//可以在方法中直接使用 name , age
//处理some.do请求了。 相当于service调用处理完成了。
ModelAndView mv = new ModelAndView();
mv.addObject("myname",myStudent.getName());
mv.addObject("myage",myStudent.getAge());
mv.addObject("mystudent",myStudent);
//show是视图文件的逻辑名称(文件名称)
mv.setViewName("show");
return mv;
}
<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="提交参数">
form>
使用@Controller 注解的处理器的处理器方法,其返回值常用的有四种类型:
➢ 第一种: ModelAndView(既要跳转又需要传递数据才用)
➢ 第二种: String
➢ 第三种:无返回值 void
➢ 第四种:返回自定义类型对象
@RequestMapping(value = "/returnString-view.do")
public String doReturnView(HttpServletRequest request, String name, Integer age) {
System.out.println("doReturnView, name=" + name + " age=" + age);
//可以自己手工添加数据到request作用域,这样功能就和ModelAndView重合了
request.setAttribute("myname", name);
request.setAttribute("myage", age);
// show : 逻辑视图名称,项目中配置了视图解析器
// 框架对视图执行forward转发操作
return "show";
}
完整视图路径,项目中不能配置视图解析器,需要把解析器注释掉
@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";
}
处理器方法也可以返回 Object 对象。 这个 Object 可以是 Integer, String, 自定义对象,
Map, List 等。但返回的对象不是作为逻辑视图出现的,而是作为直接在页面显示的数据出
现的。
返回对象,需要使用@ResponseBody 注解, 将转换后的 JSON 数据放入到响应体中。
判断是返回值是否是返回逻辑视图,就看有没有@ResponseBody 注解
现在做ajax, 主要使用json的数据格式。 实现步骤三步:
HttpMessageConverter接口:消息转换器。
功能:定义了java转为json,xml等数据格式的方法。 这个接口有很多的实现类。
这些实现类完成 java对象到json, java对象到xml,java对象到二进制数据的转换
//不一定用json,这里以json为例
json = om.writeValueAsString(student);
response.setContentType("application/json;charset=utf-8");
PrintWriter pw = response.getWriter();
pw.println(json);
来看看示例
写MyController
* 处理器方法返回一个Student,通过框架转为json,响应ajax请求
*
* @ResponseBody: 作用:把处理器方法返回对象转为json后,通过HttpServletResponse输出给浏览器。
* 位置:方法的定义上面。 和其它注解没有顺序的关系。
/**
*/
@RequestMapping(value = "/returnStudentJson.do")
//需要加这个注解 ResponseBody
@ResponseBody
public Student doStudentJsonObject(String name, Integer age) {
//调用service,获取请求结果数据 , Student对象表示结果数据
Student student = new Student();
student.setName("李四同学");
student.setAge(20);
return student; // 会被框架转为json
}
在SpringMVC.xml中添加配置
<mvc:annotation-driven/>
index.jsp中写js代码
<head>
<title>Title</title>
<script type="text/javascript" src="js/jquery-3.4.1.js"></script>
<script type="text/javascript">
$(function () {
$("button").click(function () {
//alert("button click");
$.ajax({
url: "returnStudentJson.do",
data: {
name: "zhangsan",
age: 20
},
type: "post",
dataType: "json",
success: function (resp) {
alert(resp.name + " " + resp.age);
}
})
})
})
</script>
</head>
* 返回对象框架的处理流程:
* 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请求处理完成
MyController
@RequestMapping(value = "/returnStudentJsonArray.do")
//需要加这个注解 ResponseBody
@ResponseBody
public List<Student> doStudentJsonObjectArray(String name, Integer age) {
List<Student> list = new ArrayList<>();
Student student = new Student();
student.setName("李四同学");
student.setAge(20);
list.add(student);
student = new Student();
student.setName("张三");
student.setAge(28);
list.add(student);
return list;
}
index.jsp中修改
<script type="text/javascript">
$(function () {
$("button").click(function () {
//alert("button click");
$.ajax({
url: "returnStudentJsonArray.do",
data: {
name: "zhangsan",
age: 20
},
type: "post",
dataType: "json",
success: function (resp) {
//依次拿出变量
$.each(resp, function (i, n) {
// i是循环变量,n是数组中的对象
alert(n.name + " " + n.age)
})
}
})
})
})
script>
MyController
@RequestMapping("/returnStringData.do")
@ResponseBody
public String doStringData(String name, Integer age) {
return "Hello SpringMVC 返回对象,表示数据";
}
然后我们发现此时传的数据不再是json了
<script type="text/javascript">
$(function () {
$("button").click(function () {
//alert("button click");
$.ajax({
url: "returnStringData.do",
data: {
name: "zhangsan",
age: 20
},
type: "post",
dataType: "text",
success: function (resp) {
alert(resp)
}
})
})
})
</script>
如果这个dataType还是json,那么就根本不显示
但我们改为text,有了显示,但还是有乱码
这个乱码和过滤器处理的乱码不一样。
过滤器是处理 Tomcat把结果写入响应头不乱码
这里是把结果返回给浏览器,浏览器解码方法错了导致的
解决方法
在MyController方法上添加produces
@RequestMapping(value = "/returnStringData.do", produces = "text/plain;charset=utf-8")
我们写了很多子程序,那么分别是交给谁来处理的?
程序 | 处理器 |
---|---|
index.jsp | Tomcat(jsp会转为servlet) |
js/jquery-3.4.1.js | Tomcat |
静态图片.jpg | Tomcat |
test.html(静态页面) | Tomcat |
some.do | DispatcherServlet(在web.xml中配置可以判断出)SpringMVC框架处理 |
Tomcat本身能处理静态资源的访问,html,图片,js都属于静态资源
Tomcat本身默认带了一个default的servlet,可以处理静态资源,也可以处理没有映射到其他servlet的请求。
比如我们配置了俩servlet,aservlet和bservlet,此时要访问一个c,我们没有配置,那就访问默认的default的servlet
我们现在回过来看配置的web.xml
servlet-mapping>
<servlet-name>mywebservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
使用斜杠的话,会代替Tomcat的default,把交给Tomcat的东西给拦截了
导致静态资源也交给dispatcherServlet处理,但是他能处理吗?他处理不了,他没那个能力你知道吧。
动态资源能处理,因为有MyController去处理。
那我们想解决这个问题,就可以考虑能不能让dispatcherServlet收到的请求再转发回Tomcat进行处理呢?
第一种方式
只需要在SpringMVC.xml配置文件中添加
<mvc:default-servlet-handler/>
== 第二种方式来配置==
可以在SpringMVC.xml文件中写上
<mvc:resources mapping="/images/**" location="/images/"/>
<mvc:resources mapping="/js/**" location="/js/"/>
这样也可以实现静态资源的访问
但是如果我们有很多静态资源,这样一个个写肯定不方便
所以一般把所有静态资源放到一个文件夹static里面
这样仅需要配置
<mvc:resources mapping="/static/**" location="/static/"/>
这里讨论了一下绝对路径和相对路径
相对路径中加斜杠的问题
首先来看情况1
1) 在你的页面中的,访问地址不加 “/”
<a href="user/some.do">
访问的是: http://localhost:8080/ch06_path/index.jsp
路径: http://localhost:8080/ch06_path/ (注意,这里的ch06_path就是我们在Tomcat服务器发布的那个名称)
资源: index.jsp
在index.jsp发起 user/some.do请求,访问地址变为 http://localhost:8080/ch06_path/user/some.do
当你的地址 没有斜杠开头,例如 user/some.do , 当你点击链接时, 访问地址是
当前页面的地址 加上 链接的地址。
http://localhost:8080/ch06_path/ + user/some.do
在页面中的,访问地址加 “/”
<a href="/user/some.do">
访问的是: http://localhost:8080/ch06_path/index.jsp
路径: http://localhost:8080/ch06_path/
资源: index.jsp
点击 /user/some.do, 访问地址变为 http://localhost:8080/user/some.do
参考地址是 你的服务器地址, 也就是 http://localhost:8080
缺一个ch06_path
所以我们要解决的话,可以选择在href后面填上这一句
但是这样处理不够灵活
如果你的资源不能访问: 加入
${pageContext.request.contextPath}
<a href="${pageContext.request.contextPath}/user/some.do">发起user/some.do的get请求</a>
这样粗看有些麻烦,不如直接去掉斜杠,但是这样还是比较规范的,我们可以看到下面这种情况
index.jsp 访问 user/some.do , 返回后现在的地址: http://localhost:8080/ch06_path/user/some.do
这个很好理解
http://localhost:8080/ch06_path/user/some.do
路径: http://localhost:8080/ch06_path/user/
资源: some.do
但在此之后,在index.jsp中 user/some.do ,就变为 http://localhost:8080/ch06_path/user/user/some.do
有两个user了,我们就没办法访问到想访问的页面了
因为我们上面说过
当你的地址 没有斜杠开头,例如 user/some.do , 当你点击链接时, 访问地址是
当前页面的地址 加上 链接的地址。 http://localhost:8080/ch06_path/ + user/some.do
在点击一次后,路径变为了
http://localhost:8080/ch06_path/user/
如果再次加上 链接的地址user/some.do,就出现了刚才的情况。
解决方案:
1.加入${pageContext.request.contextPath} (变成加斜杠的方式)
2.加入一个base标签, 是html语言中的标签。 表示当前页面中访问地址的基地址。
你的页面中所有 == 没有==“/”开头的地址,都是以base标签中的地址为参考地址
使用base中的地址 + user/some.do 组成访问地址
这样不管怎么跳转,还是以base地址为基础
我们这里不管加没加斜杠,都是相对地址,那么这个相对地址相对的是谁,就通过设置base把他固定下来
获取指定路径
<%
String basePath = request.getScheme() + "://" +
request.getServerName() + ":" + request.getServerPort() +
request.getContextPath() + "/";
%>
<head>
<title>Titletitle>
<base href="<%=basePath%>" />
head>
<body>
<p>第一个springmvc项目p>
<p><a href="user/some.do">发起user/some.do的get请求a> p>
<br/>
body>
string的四段分别是获取协议 服务器ip 端口号 以及访问路径的
此时链接上就没有第一个斜杠了
结束时间:2022-01-28