文件上传、过滤器、监听器
1.文件上传
1.1 使用工具
文件上传需要对请求中传的的文件流进行解析,一般会选择工具来对文件流进行解析
- 文件上传相关的jar包
commons-fileupload-1.3.3.jar
commons-io-2.5.jar
1.2 文件上传
- 文件上传请求由浏览器发起
<form action="myUpload" method="post" enctype="multipart/form-data">
<input type="text" name="uname"><br>
<input type="file" name="myfile"><br>
<input type="submit">
</form>
需要文件选择框并且设置了name属性,form的method为post,加设置enctype=“multipart/form-data”,此时form提交时,会把选择到的文件以二进制数据形式发送到服务器,否则不会发送文件
- 服务器需要对请求中的文件数据进行解析,还原成文件,这个由jar包中提供的类完成
//如果页面中加了 enctype="multipart/form-data" 提交数据的方式发生改变 不会封装成键值对
//getParameter 取不到值
//req.getParameter("xxx");
//enctype="multipart/form-data"
//默认使用iso-8859-1 解析 需要把中文的内容 根据iso-8859-1拆解 再用utf-8 重组
/*
* 上传文件
* 1. form中设置 method="post" enctype="multipart/form-data"
* 2. 服务器使用 commons-fileupload-1.2.jar 对数据流解析
* 3.在指定的服务器位置创建一个与上传的文件同名的空文件
* 4.把工具解析出的临时文件的内容 复制到新创建的文件中
*
* */
@WebServlet("/myUpload")
public class MyUploadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//multipart/form-data 处理上传文件的servlet和普通数据的servlet分开 处理数据格式不同
//项目所在实际路径 web文件夹同级
String basePath = req.getServletContext().getRealPath("/");
//创建拼接+文件上传地址的对象
String myFolder = "upload\\";
//解析流中数据的核心对象
boolean ismultipart = ServletFileUpload.isMultipartContent(req);
if(ismultipart){
//生成FileItem的工厂 创建fileItem对象 上传的数据封装成fileItem(既可以表示为普通数据 也可以文件对象 )
//普通数据 fileItem
// 文件对象 fileItem
//可以设置生成数据的参数
DiskFileItemFactory dff = new DiskFileItemFactory();
//通过工厂生成上传文件对象
ServletFileUpload sfu = new ServletFileUpload(dff);
try {
//列表里放入所有的fileItem对象
List<FileItem> lf = sfu.parseRequest(req);
//
for(FileItem fi:lf){
if(!fi.isFormField()){
//处理文件
//存放上传文件的目录
String fileFullName = basePath+myFolder+fi.getName();
//写入的时候 myFolder文件夹必须存在 可回顾第一阶段知识io流
File newFile = new File(fileFullName);
//把临时文件 写入到指定的文件中
fi.write(newFile);
}else{
//处理普通字段
System.out.println(fi.getFieldName()+" --- "+fi.getString());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/*
必须有name属性 不管是名字还是文件
文件名字最好不是中文 要不然需要转格式
流中数据 根据格式 都生成临时文件
普通字段 isFormField = true name=null FieldName=uname
文件 isFormField = false name=test.png FieldName=myfile
*/
1.3 Ajax文件上传
l 文件上传使用form传递,普通数据取值变得非常麻烦,可以把文件上传和普通表单提交的流程分开,通过工具把文件单独上传到服务器(异步上传),并在页面接收存储的地址(相对路径),用户填完数据提交表单时,文件已上传过,只需要提交普通表单即可。
后台
//项目所在实际路径
String basePath = req.getServletContext().getRealPath("/"); //这个是编译时的路径 在out里
//存放上传文件的目录
String fileFolder = "upload/";
//临时文件工厂
DiskFileItemFactory dff = new DiskFileItemFactory();
//临时文件工厂 解析数据时 使用该工厂
ServletFileUpload sfu = new ServletFileUpload(dff);
String imgSrc ="";
try {
List<FileItem> list = sfu.parseRequest(req);
for(FileItem fi:list){
if(!fi.isFormField()){
//文件 把工厂中的临时文件 复制到服务的指定位置的文件里
File newFile = new File(basePath+fileFolder+fi.getName()); //上面已经加了"/"了
fi.write(newFile);
//复制完毕后的文件地址
imgSrc = fileFolder+"/"+fi.getName();
}
}
} catch (Exception e) {
e.printStackTrace();
}
resp.setContentType("text/html;charset=utf-8");
PrintWriter pw = resp.getWriter();
pw.print("{\"imgsrc\":\""+imgSrc+"\"}");
pw.flush();
pw.close();
前端
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<script src="js/jquery-3.4.1.min.js"></script>
<script src="js/ajaxfileupload.js"></script>
<script>
$(function(){
$("#myfile").change(function(){
console.log(1);
//ajaxFileUpload
$.ajaxFileUpload({
url:"ajaxUpload",//地址
type:"post",//请求类型
data:{},
fileElementId:"myfile",
secureuri:false,
dataType:"text",//返回数据的类型
success:function(data){//响应成功时的回调函数 data表示返回的数据
//console.log(data);
var jsonobj = JSON.parse(data)
//console.log(jsonobj);
$("#fileurl").val(jsonobj.imgSrc); //选择文件按钮后边 显示选择的文件名字
$("#showImg").html('<img src="'+jsonobj.imgSrc+'">');
}
});
})
})
</script>
</head>
<body>
<form action="myRegist" method="post">
<input type="text" name="uname" placeholder="用户名"><br>
<input type="text" name="uphone" placeholder="手机号"><br>
<input type="text" name="uemail" placeholder="邮箱"><br>
<input type="text" name="uaddr" placeholder="住址"><br>
<input type="file" id="myfile" name="myfile"><br>
<input type="hidden" id="fileurl" name="fileurl" value="xxx/xxx.png">
<input type="submit">
</form>
<div id="showImg">
</div>
</body>
</html>
2.Filter过滤器
2.1 什么是过滤器
-
过滤器是向 Web 应用程序的请求和响应处理添加功能的Web 服务组件
-
Filter是一个可以加在servlet前执行的组件,可以通过这个机制制作一些通用性的功能,跟生活中用的水的过滤器的机制很相似。
2.2 过滤器生命周期
2.3 过滤器典型案例
//如果servlet与filter配置地址相同 访问同一个地址时 filter会先运行
//同一个地址可以配置多个filter filter执行的先后顺序
// 配置文件 配置的先后 //web.xml里配置
// 注解 类名排列先后 //filter1比filter2先
// fitler一般用来做通用功能
// 需要和通配符*搭配 如果配置为/* 所有的网络请求都会走过滤器 包括 html css js bootstrap等 各种图片
// 做通用功能
// 1.处理请求字符编码
// 2.访问限制(权限功能)
@WebFilter("/*")
public class MyFilter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//从session中取权限列表
/**
* 在登录访问控制之后
* 权限过滤 较细粒度的访问控制
* servletRequest -->> HttpServletRequest
* servletResponse -->> HttpServletResponse
*判断用户是否具有权限 通过用户访问的url
*myreq.getRequestURI() 获取请求的路径
*myreq.getServletPath() 获取当次要访问的servlet配置的路径
*
*
*
* 配置白名单 白名单
* 忽略静态资源
* 忽略某些特定模块
*
*
* 跟权限列表匹配
*
* 如果是ajax请求 页面跳转无效
* 响应没有权限相关的数据
*
* 页面中请求的响应上 加上对没有权限的处理(location.href 转到一个精美的没有权限页面)
*/
//创建servlet拥有访问权限页面的集合
List<String> userAuth =new ArrayList<String>();
userAuth.add("/ajaxProd");
userAuth.add("/ajaxOrder");
userAuth.add("/ajaxXXX");
//web应用走的都是http协议 像ServletRequest servletRequest这些子类实例都可以强转
//将ServletRequest转换成HttpServletRequest格式 用来取要访问的页面
HttpServletRequest myreq = (HttpServletRequest) servletRequest;
String servletPath = myreq.getServletPath();
//白名单 黑名单
//忽略静态资源
//忽略某些特定模块
//设置这些静态资源直接通过 为白名单
if(servletPath.endsWith(".html")||servletPath.endsWith(".js")||
servletPath.endsWith(".css")||servletPath.endsWith(".png")||
servletPath.endsWith(".jpeg")||"/text".equals(servletPath)){
filterChain.doFilter(myreq,servletResponse);
}else{
//询问是否有访问该页面权限
if(userAuth.contains(servletPath)){
//有权限
filterChain.doFilter(myreq,servletResponse); //这句话就是带着参数继续往下走servlet
}else{
//没有权限
ReturnEntity returnEntity = new ReturnEntity();
returnEntity.setReturnCode(ReturnCode.NO_AUTH.getCode());
returnEntity.setReturnMSG(ReturnCode.NO_AUTH.getMsg());
servletResponse.setContentType("text/html;charset=utf-8");
PrintWriter out = servletResponse.getWriter();
//返回json格式字符串 通过返回的数据跳转到一个提示没有访问权限精致页面
out.print(JSON.toJSONString(returnEntity));
out.flush();
out.close();
}
}
}
@Override
public void destroy() {
}
}
3.监听器
3.1 什么是监听器
监听器是javaweb组件中提供的另外一种机制,用来监控域对象的创建、销毁过程(在发生创建、销毁时,可以执行自己的代码)以及域对象中属性的创建、替换、销毁。
- 监听web对象创建与销毁的监听器
ServletContextListener
HttpSessionListener
ServletRequestListener
- 监听web对象属性变化
ServletContextAttributeListener
HttpSessionAttributeListener
ServletRequestAttributeListener
3.2 监听器配置和使用
HttpSessionListener为例
public class MyListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent arg0) {
//session创建时执行的代码
}
@Override
public void sessionDestroyed(HttpSessionEvent arg0) {
//session销毁时执行的代码
}
}
Web.Xml中配置
<listener>
<listener-class>com.javasm.listener.MyListener</listener-class>
</listener>