内容大纲
项目地址:https://github.com/Jonekaka/javaweb-springMVC-55
具体
搭建环境
54上篇已经讲述
第一章:响应数据和结果视图
springmvc_day02_01_response
返回值分类
返回字符串
java
jsp
返回空
- 如果控制器的方法返回值编写成void,执行程序报404的异常,默认查找JSP页面没有找到。
- 默认会跳转到@RequestMapping(value=”/initUpdate”) initUpdate的页面。
- 可以使用请求转发或者重定向跳转到指定的页面
默认值:弱对应关系,返回sucess找sucess.jsp,返回void寻找testvoid.jsp
没有指定要寻找的界面,但是软件自己猜
java
之前的
修改后,指定要去调用哪个界面,产生强关联.
重定向两次请求,请求转发,一次请求,而且需要自己写完整路径,软件不猜了
jsp
返回值是ModelAndView对象
- ModelAndView对象是Spring提供的一个对象,可以用来调整具体的JSP视图
和返回字符串的效果相同,但是写法不同,这个写法更为底层,返回字符串底层原理依赖此
最后都交给视图解析器解析
java
SpringMVC框架提供的转发和重定向
用关键字转发和重定向,用不了视图解析器,要写正确的路径
重定向需要写项目路径,这个底层已经加了,不用写
java
ResponseBody响应json数据
假如ajax异步请求,如何接受后台的json数据
前端控制器拦截
DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而
不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置
位置,文件路径(xx下不拦截谁)
通过json发送请求和接受
按键发送json请求
jsp
接受到后弹窗收到的内容
那么是否存在一种可能,将数据组自动json相互转化
导入jar包
java
获得请求体的内容,@RequestBody
这里已经自动将收到的json数据打包进user了
如果返回对象,前端默认的也是json,这里自动转化
以前还需要response写输出流,现在不必
第二章:SpringMVC实现文件上传
springmvc_day02_02_fileupload
导入文件上传的jar包
必要条件:
A form 表单的 enctype 取值必须是:multipart/form-data
(默认值是:application/x-www-form-urlencoded)
(—解释—:)【将整个表单分成几个部分,可能有的是文本框,有的是文件的内容等等】
enctype:是表单请求正文的类型
B method 属性取值必须是 Post
(—解释—:)【如果是get,会把内容弄到地址栏上,有限制。】
C 提供一个文件选择域
原理分析
使用分隔符分成了若干部分
—————————–7de1a433602ac 分界符
Content-Disposition: form-data; name=“userName” 协议头
aaa 协议的正文
—————————–7de1a433602ac
Content-Disposition: form-data; name=“file”;
filename=“C:\Users\zhy\Desktop\fileupload_demofile\b.txt”
Content-Type: text/plain 协议的类型(MIME 类型)
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
—————————–7de1a433602ac–
然后取得内容写入就得到了文件
第三方组件封装
使用 Commons-fileupload 组件实现文件上传,需要导入该组件相应的支撑 jar 包:Commons-fileupload 和
commons-io。commons-io 不属于文件上传组件的开发 jar 文件,但Commons-fileupload 组件从 1.1 版本开始,它
工作时需要 commons-io 包的支持。
解决
创建工程时如果提示副工程,不需要关闭即可
导入坐标依赖
传统文件上传。
jsp
java
之所以删除临时文件,是因为上传文件>10k,就会生成临时文件,否则在内存中直接搞定
对于名字设定唯一值
@RequestMapping("/fileupload1")
public String fileuoload1(HttpServletRequest request) throws Exception {
System.out.println("文件上传...");
// 使用fileupload组件完成文件上传
// 上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
// 判断,该路径是否存在
File file = new File(path);
if(!file.exists()){
// 创建该文件夹
file.mkdirs();
}
// 解析request对象,获取上传文件项
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
// 解析request
List<FileItem> items = upload.parseRequest(request);
// 遍历
for(FileItem item:items){
// 进行判断,当前item对象是否是上传文件项
if(item.isFormField()){
// 说明普通表单向
}else{
// 说明上传文件项
// 获取上传文件的名称
String filename = item.getName();
// 把文件的名称设置唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid+"_"+filename;
// 完成文件上传
item.write(new File(path,filename));
// 删除临时文件
item.delete();
}
}
return "success";
}
SpringMVC传统方式文件上传
原理分析
解析request请求,交给文件解析器拿到上传的文件项信息,返回一个上传文件对象
自带的一个解析对象,通过参数绑定数据传送
解析器在spring.xml中配置
SpringMVC框架提供了MultipartFile对象,该对象表示上传的文件,要求变量名称必须和表单file标签的
name属性名称相同。
spring.xml
<!--配置文件解析器对象-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10485760" />
</bean>
jsp
<h3>Springmvc文件上传</h3>
<form action="/user/fileupload2" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload" /><br/>
<input type="submit" value="上传" />
</form>
java
/**
* SpringMVC文件上传
* @return
*/
@RequestMapping("/fileupload2")
//上传对象自带
public String fileuoload2(HttpServletRequest request, MultipartFile upload) throws Exception {
System.out.println("springmvc文件上传...");
// 使用fileupload组件完成文件上传
// 上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
// 判断,该路径是否存在
File file = new File(path);
if(!file.exists()){
// 创建该文件夹
file.mkdirs();
}
// 说明上传文件项,文件已经不需要自己解析了
// 获取上传文件的名称
String filename = upload.getOriginalFilename();
// 把文件的名称设置唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid+"_"+filename;
// 完成文件上传
upload.transferTo(new File(path,filename));
return "success";
}
SpringMVC跨服务器方式文件上传
在实际开发中,我们会有很多处理不同功能的服务器。例如:
应用服务器:负责部署我们的应用
数据库服务器:运行我们的数据库
缓存和消息服务器:负责处理大并发访问的缓存和消息
文件服务器:负责存储用户上传文件的服务器。
提高我们项目 的运行效率
新建服务
注意端口不要重复
java
/**
* 跨服务器文件上传
* @return
*/
@RequestMapping("/fileupload3")
public String fileuoload3(MultipartFile upload) throws Exception {
System.out.println("跨服务器文件上传...");
// 定义上传文件服务器路径
String path = "http://localhost:9090/uploads/";
// 说明上传文件项
// 获取上传文件的名称
String filename = upload.getOriginalFilename();
// 把文件的名称设置唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid+"_"+filename;
// 创建客户端的对象
Client client = Client.create();
// 和图片服务器进行连接
WebResource webResource = client.resource(path + filename);
// 上传文件
webResource.put(upload.getBytes());
return "success";
}
jsp
<h3>跨服务器文件上传</h3>
<form action="/user/fileupload3" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload" /><br/>
<input type="submit" value="上传" />
</form>
第三章:SpringMVC的异常处理
springmvc_day02_03_exception
出现异常查看具体信息是开发者的事情,使用者不需要这么详细的信息
异常处理器调度异常界面,展示友好的异常信息
异常信息类,java,接受异常信息
编写异常类
/**
* 自定义异常类
*/
public class SysException extends Exception{
// 存储提示信息的
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public SysException(String message) {
this.message = message;
}
}
ctrl alt T快速选择代码,然后环绕代码生成if else,try catch等
异常处理类
@RequestMapping("/testException")
public String testException() throws SysException{
System.out.println("testException执行了...");
try {
// 模拟异常
int a = 10/0;
} catch (Exception e) {
// 打印异常信息
e.printStackTrace();
// 抛出自定义异常信息
throw new SysException("查询所有用户出现错误了...");//就是刚才写的错误信息类,构造方法
}
return "success";
}
编写处理器
继承接口,当有异常时检测到有处理器就交给处理器执行
/**
* 异常处理器
*/
public class SysExceptionResolver implements HandlerExceptionResolver{
/**
* 处理异常业务逻辑
* @param request
* @param response
* @param handler
* @param ex
* @return
*/
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// 获取到异常对象,判断类型是否符合,不符合就强转
SysException e = null;
if(ex instanceof SysException){
e = (SysException)ex;
}else{
e = new SysException("系统正在维护....");
}
// 创建ModelAndView对象,这个是返回值,可以跳转页面
ModelAndView mv = new ModelAndView();
//存键值对
mv.addObject("errorMsg",e.getMessage());
//跳转页面,error.jsp
mv.setViewName("error");
return mv;
}
配置异常处理器srping.xml
<!--配置异常处理器-->
<bean id="sysExceptionResolver" class="cn.Learn_Java.exception.SysExceptionResolver"/>
第四章:SpringMVC框架中的拦截器
springmvc_day02_04_interceptor
拦截器的概述
- SpringMVC框架中的拦截器用于对处理器进行预处理和后处理的技术。
- 可以定义拦截器链,连接器链就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链
中的拦截器会按着定义的顺序执行。 - 拦截器和过滤器的功能比较类似,类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。有区别
- 过滤器是Servlet规范的一部分,任何框架都可以使用过滤器技术。 2. 拦截器是SpringMVC框架独有的。
- 过滤器配置了/*,可以拦截任何资源。 4. 拦截器只会对控制器中的方法进行拦截。如果访问的是 jsp,html,css,image 或者 js 是不会进行拦截的。
- 拦截器也是AOP思想的一种实现方式
- 想要自定义拦截器,需要实现HandlerInterceptor接口。
jsp
<a href="user/testInterceptor" >拦截器</a>
java类
@RequestMapping("/testInterceptor")
public String testInterceptor(){
System.out.println("testInterceptor执行了...");
return "success";
}
拦截器
继承接口后发现没有方法报错,那是因为他内部默认的方法已经默认实现了,如果不使用预制的可以重写
spring.xml
配置拦截器
先执行拦截器然后放行,否则
<!--配置拦截器-->
<mvc:interceptors>
<!--配置拦截器-->
<mvc:interceptor>
<!--要拦截的具体的方法-->
<mvc:mapping path="/user/*"/>
<!--不要拦截的方法,写一个就行,既然这个拦截了,其他的肯定不拦截,反之亦然
<mvc:exclude-mapping path=""/>
-->
<!--配置拦截器对象-->
<bean class="cn.Learn_Java.controller.cn.Learn_Java.interceptor.MyInterceptor1" />
</mvc:interceptor>
<!--配置第二个拦截器-->
<mvc:interceptor>
<!--要拦截的具体的方法-->
<mvc:mapping path="/**"/>
<!--不要拦截的方法,
<mvc:exclude-mapping path=""/>
-->
<!--配置拦截器对象-->
<bean class="cn.Learn_Java.controller.cn.Learn_Java.interceptor.MyInterceptor2" />
</mvc:interceptor>
</mvc:interceptors>
拦截器类
拦截器1,内部有三个方法,说明白,可以有多个拦截器
在这些类中,能够调用界面已经是最终的步骤,因此无返回拦截效果
不要奇怪,他们不是一起执行的,而是第一个拦截器确实已经执行完了,进入下一个,然后返回时发现条件又满足了继续一个个的拦截
/**
* 自定义拦截器
*/
public class MyInterceptor1 implements HandlerInterceptor{
/**
* 预处理,controller方法执行前
* return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
* return false不放行
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor1执行了...前1111");
// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
return true;
}
/**
* 后处理方法,controller方法执行后,只会拦截方法,success.jsp执行之前
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor1执行了...后1111");
// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
}
/**
* success.jsp页面执行后,该方法会执行,优先级更低
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor1执行了...最后1111");
}
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/100238.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...