1. 今日内容
2. 响应数据和结果视图
2.1 控制器方法的返回值分类
2.1.1 字符串
controller 方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。
例子:
2.1.2 void
方法没有返回值,默认情况下,会以该方法的虚拟路径到视图解析器中找物理地址,一般都不会存在,然后报错。
一般我们这样用:
2.1.3 ModelAndView(返回字符串底层调用的是ModelAndView)
ModelAndView 是 SpringMVC 为我们提供的一个对象,该对象也可以用作控制器方法的返回值。
2.2 转发和重定向
下面两种方式不能用视图解析器解析,所以要写绝对路径,/
代表项目根路径,即从项目名开始(包括项目名)。
2.2.1 forward 转发
2.2.2 Redirect 重定向
注意:重定向的jsp文件不能写在WEB-INF目录中,否则无法找到。
2.3 ResponseBody 响应 json 数据
2.3.1 静态资源不能被引用
DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而 不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置 :
- location元素表示webapp目录下的包下的所有文件
- mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b
<!-- 设置静态资源不过滤 -->
<mvc:resources location="/css/" mapping="/css/**"/> <!-- 样式 -->
<mvc:resources location="/images/" mapping="/images/**"/> <!-- 图片 -->
<mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript -->
2.3.2 将json数据封装成JavaBean对象
导入下面的jar包(必须导入jar包,不然会报运行错误)然后使用@RequestBody User user
,会自动封装成User对象。
导入的jar包如下:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.10</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.10</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.10</version>
</dependency>
<script>
$(function () {
$("#btn").click(function () {
$.ajax({
url:"hello/sayHello",
type:"post",
data:JSON.stringify({"username":"zhang", "password":"123"}),
contentType:"application/json",
dataType:"json",
success:function(){
}
});
});
});
</script>
@RequestMapping("/sayHello")
public String sayHello(@RequestBody User user){
System.out.println(user);
return "success";
}
2.3.3 ResponseBody 响应 json 数据
用@Response
注解方法的返回值,将JavaBean对象转为json对象。
如下:
<script>
$(function () {
$("#btn").click(function () {
$.ajax({
url:"hello/sayHello",
type:"post",
data:JSON.stringify({"username":"zhang", "password":"123"}),
contentType:"application/json",
dataType:"json",
success:function(data){
alert(data.username);
alert(data.password);
}
});
});
});
</script>
@RequestMapping("/sayHello")
public @ResponseBody User sayHello(@RequestBody User user){
System.out.println(user);
return user;
}
3. SpringMVC实现文件上传
3.1 文件上传前置知识
- 文件上传的必要前提
- 文件上传的原理分析
Content-Type: multipart/form-data; boundary=${bound}
。其中${bound}
是一个占位符,代表我们规定的分割符,可以自己任意规定,但为了避免和正常文本重复了,尽量要使用复杂一点的内容。如:--------------------56423498738365
。如果不指定,会自动生成。
3.2 传统方式上传文件
- 导入文件上传的jar包
<!--上传文件用到的jar包-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
- 编写文件上传的JSP页面
<form action="hello/testUpload" method="post" enctype="multipart/form-data">
<label>点击按钮上传文件:</label>
<input type="file" name="upLoad"> <br>
<input type="submit" value="提交">
</form>
- 编写文件上传的Controller控制器
@RequestMapping("testUpload")
public String testUpload(HttpServletRequest request) throws Exception {
//1. 得到要存放的目录
String path = request.getSession().getServletContext().getRealPath("/upLoad/");
//2. 判断目录是否存在,若不存在,则创建
File file = new File(path);
if (!file.exists()) {
file.mkdir();
}
//3. 创建磁盘文件项工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
//4. 解析request对象,得到请求项们
List<FileItem> items = upload.parseRequest(request);
//5. 遍历请求项,找到文件项
for (FileItem item:items) {
if (item.isFormField()){
//是参数项
} else {
//是文件项
String fileName = item.getName();
//6. 使得文件名唯一
String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
fileName = uuid + "_" + fileName;
//7. 将文件写入磁盘上
item.write(new File(path, fileName));
//8. 删除临时文件。默认小于10MB会生成缓存, 清除掉,避免开销
item.delete();
}
}
return "success";
}
3.3 springmvc方式上传文件
由于表现层的所有处理都交给前端控制器:dispatchaerServlet
处理,所以,如果我们要利用框架解析request,获取文件项,再由dispatchaerServlet
交给控制器处理,也是由dispatchaerServlet`处理。其工作流程如下:
注意:前端jsp上文件加项的name值必须与后台contriller中绑定方法的参数名一样,否则无法绑定参数。
- 配置文件解析器
<!-- 配置文件解析器对象,要求id名称必须是multipartResolver CommonsMultipartResolver-通用组件解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置最大文件,字节为单位,10485760 = 10*1024*1024 = 10MB-->
<property name="maxUploadSize" value="10485760"></property>
</bean>
- jsp页面不变。
- 编写文件上传的Controller控制器
SpringMVC框架提供了MultipartFile对象,该对象表示上传的文件,要求变量名称必须和表单file标签的 name属性名称相同。
@RequestMapping("testUpload")
public String testUpload(HttpServletRequest request, MultipartFile upLoad) throws Exception {
//1. 得到要存放的目录
String path = request.getSession().getServletContext().getRealPath("/upLoad/");
//2. 判断目录是否存在,若不存在,则创建
File file = new File(path);
if (!file.exists()) {
file.mkdir();
}
//3. 使得文件名唯一
String fileName = upLoad.getOriginalFilename(); //注意:这里用getOriginalFilename()方法
String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
fileName = uuid + "_" + fileName;
//4. 将文件写入磁盘上
upLoad.transferTo(new File(path, fileName));
return "success";
}
注意:上面获取文件名时,用的是getOriginalFilename()
方法,而不是getName()
方法。
3.4 SpringMVC跨服务器方式文件上传
- 搭建图片服务器
重新建一个WEB项目,并运行,其webapp/upLoad/
目录下,存放上传的文件。 - jsp页面不变。
- 编写文件上传的Controller控制器
@RequestMapping(value="/fileupload3")
public String fileupload3(MultipartFile upload) throws Exception{
// 1. 定义图片服务器的请求路径
String path = "http://localhost:9090/day02_springmvc5_02image/upLoad/";
// 2. 获取到上传文件的名称
String filename = upload.getOriginalFilename();
// 3. 把文件的名称唯一化
String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
filename = uuid+"_"+filename;
// 4. 向图片服务器上传文件
//4.1 创建客户端对象
Client client = Client.create();
// 连接图片服务器
WebResource webResource = client.resource(path+filename);
// 上传文件
webResource.put(upload.getBytes());
return "success";
}
4. SpringMVC的异常处理
4.1 异常处理思路
Controller调用service,service调用dao,异常都是向上抛出的,最终有DispatcherServlet找异常处理器进 行异常的处理。 关系如下图:
4.2 SpringMVC的异常处理
- 自定义异常类,即自定义类继承
package cn.wanghao.springmvc.exception;
public class SysException extends Exception {
private String message;
public SysException(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
- 自定义异常处理器,继承
HandlerExceptionResolver
接口
package cn.wanghao.springmvc.exception;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SysExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
SysException err = null;
if (e instanceof SysException) {
err = (SysException) e;
} else {
err = new SysException("请联系管理员");
}
ModelAndView mv = new ModelAndView();
mv.addObject("errorMsg", err);
mv.setViewName("error");
return mv;
}
}
- 配置异常处理器
除了dispatcaherServlet是在web.xml配置外。其余的什么器都是其类或者自定义其继承类,在springmvc.xml中用bean标签实例化就构成了什么什么器,
<!--开启异常处理器-->
<bean id="sysExceptionResolver" class="cn.wanghao.springmvc.exception.SysExceptionResolver"></bean>
- 出现异常的地方:
@RequestMapping("/myExcepion")
public String testMyExcepion() throws SysException {
try {
int i = 10/0;
} catch (Exception e) {
//打印错误信息
e.printStackTrace();
//抛出异常
throw new SysException("查询用户出错!");
}
return "success";
}
5. SpringMVC中的拦截器
5.1 拦截器作用
简单来说,拦截器与过滤器功能类似,但是过滤器比拦截器的范围更大。
5.2 自定义拦截器
5.2.1 第一步:编写一个普通类实现 HandlerInterceptor 接口
HandlerInterceptor 接口的定义如下:
上述的代码中,preHandler()和postHandler()
可以使用转发与重定向。
编写拦截器,可以用Ctrl + O
查看已经继承的类以及类的方法:
package cn.wanghao.springmvc.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class InterceptorResolver implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("执行拦截器...去");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("执行拦截器...来");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("最后拦截器释放资源");
}
}
5.2.2 第二步:配置拦截器
<!--开启拦截器-->
<mvc:interceptors>
<!--配置第一个拦截器-->
<mvc:interceptor>
<!--要拦截哪些路径-->
<mvc:mapping path="/hello/*"/>
<!--不要拦截哪些路径-->
<!--<mvc:exclude-mapping path="/hello/*" />-->
<!--配置自己编写的拦截器-->
<bean class="cn.wanghao.springmvc.interceptor.InterceptorResolver"></bean>
</mvc:interceptor>
<!--后续第二个...拦截器-->
</mvc:interceptors>
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/84650.html