第十二篇学习总结
一、文件上传
1、文件上传三要素
- 提供form表单,method必须是post
- form表单的enctype必须是multipart/form-data
- 提供input type="file" 类型文件上传
2、文件上传需要导入的包
实现文件上传要导入的两个包是file-ipload与commons-io
3、文件上传的servlet
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;
@WebServlet("/upload")
public class UploadServlet2 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 {
//设置参数
DiskFileItemFactory factory = new DiskFileItemFactory();
try {
//创建解析器
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("utf-8"); //设置编码格式
//解析上传的内容
List<FileItem> fileItems = upload.parseRequest(req);
for (FileItem fileItem : fileItems) {
// fileItem.getFieldName() :input的name值
//fileItem.getName() : 获取文件名
//组装新文件名
String oldName = fileItem.getName();
String newName = UUID.randomUUID().toString()+System.currentTimeMillis()+oldName.substring(oldName.lastIndexOf("."));
FileOutputStream fos =new FileOutputStream("d:\\ceshi\\"+newName);
InputStream is = fileItem.getInputStream();
byte[] bs = new byte[8192];
int len;
while ((len = is.read(bs)) != -1) {
fos.write(bs,0,len);
}
fos.close();
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
}
4、文件上传的注意问题
- 上传文件应该放在外界无法直接访问的目录下,比如位于WEB-INF目录下
- 为了防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
- 为了防止一个目录下面出现太多文件,要使用hash算法打散存储
- 要限制上传文件的最大值
- 要限制上传文件的类型
二、文件下载
实现文件下载的时候最重要的是要编写一个Servlet让浏览器不去解析文件而直接下载
import org.apache.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.FileUploadException;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.apache.tomcat.util.http.fileupload.servlet.ServletRequestContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;
import java.util.UUID;
@WebServlet("/download")
public class DownloadServlet 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 {
//重新设置了发送给浏览器的图片名与编码
resp.setHeader("content-disposition","attachment;fileName="+ URLEncoder.encode("图片.jpg","utf-8"));
FileInputStream fis = new FileInputStream("d:\\timg.jpg");
OutputStream os = resp.getOutputStream();
//小数组读写
byte[] bs = new byte[8192];
int len;
while ((len = fis.read(bs)) != -1) {
os.write(bs,0,len);
}
//只有真正是自己创建的流对象才需要关闭,
fis.close();
}
}
三、全局压缩
实现全局压缩要用到过滤器,最重要的是将自己组装的response伪装传给其他的Servlet,让servlet的返回数据写进我们提供的response中,然后自己再压缩返回给浏览器
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;
import java.util.zip.GZIPOutputStream;
@WebFilter("/*")
public class GzipFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//先找一个容器用来存储用户将要写回到浏览器的数据
// 给用户一个假的HttpServletResponse , 里面的流也是假的(我们自己造的存储空间)
//压缩
//告诉浏览器这时压缩之后的数据
//将数据写回到浏览器
HttpServletResponse response = (HttpServletResponse) servletResponse;
//想要压缩返回的内容,就必须要拦截输出流
MyResponse resp = new MyResponse(response);
filterChain.doFilter(servletRequest,resp);//放行
//获取所有返回的数据
byte[] bs = resp.getBytes();
//创建一个内存流, 用来存放压缩之后的数据
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(baos);
gzip.write(bs);
gzip.close();
bs = baos.toByteArray(); //获取到压缩之后的数据
//真正写回数据之前, 要告诉浏览器压缩格式, 让浏览器解压缩
response.setHeader("Content-Encoding","gzip");
//调用真正的数据流,将压缩之后的数据写回到浏览器
servletResponse.getOutputStream().write(bs);
}
@Override
public void destroy() {
}
public class MyResponse extends HttpServletResponseWrapper{
private ByteArrayOutputStream baos = new ByteArrayOutputStream();
private PrintWriter pw = null;
private MyOutputStream ms = null;
public MyResponse(HttpServletResponse response) {
super(response);
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
if(ms==null){
ms = new MyOutputStream(baos);
}
return ms;
}
@Override
public PrintWriter getWriter() throws IOException {
//当servlet调用getWriter获取字符流准备写出内容时,获取到的是一个假的输出流
//写出的内容都会放到内存流中
if(pw==null){
pw = new PrintWriter(baos);
}
return pw;
}
public byte[] getBytes() {
if(pw!=null){
pw.flush();
}
return baos.toByteArray();
}
}
public class MyOutputStream extends ServletOutputStream {
private ByteArrayOutputStream baos;
public MyOutputStream(ByteArrayOutputStream baos){
this.baos = baos;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setWriteListener(WriteListener writeListener) {
}
@Override
public void write(int b) throws IOException {
baos.write(b);
}
}
}
四、jQuery
jQuery是一个JavaScript函数库,提供了更为简洁的操作
1、安装
- 官网下载:
- 百度CDN
- 新浪CDN
- Google CDN
- Microsoft CDN
2、jQuery语法
$(selector).action(parameter):selector是选择器,action是事件,如果没有参数paramter是执行这个事件,如果有参数parameter是执行该事件的时候应该执行的函数
2.1 jQuery选择器
- 元素选择器:$("p")
- id选择器:$("#test")
- 类选择器:$(".test")
2.2 常见事件
鼠标事件 | 键盘事件 | 表单事件 | 文档/窗口事件 |
---|---|---|---|
click | keypress | submit | load |
dblclick | keydown | change | resize |
mouseenter | keyup | focus | scroll |
mouseleave | blur | unload |
3、jQuery效果
3.1 显示隐藏
- hide():隐藏元素
- show():显示元素
- toggle():切换显示与隐藏
3.2 淡入淡出
- fadeIn():淡入
- fadeOut():淡出
- fadeToggle():切换淡入与淡出
3.3 滑动
- slideDown():向下滑动
- slideUp():向上滑动
- slideToggle():切换
3.4 动画
animate()
4、jQuery HTML
4.1 捕获与设置
- text() - 设置或返回所选元素的文本内容
- html() - 设置或返回所选元素的内容(包括 HTML 标记)
- val() - 设置或返回表单字段的值
上面的三个方法,如果括号中有参数就是设置,没有参数就是获取
- attr("color","red"):设置属性
4.2 添加元素
- append() - 在被选元素的结尾插入内容
- prepend() - 在被选元素的开头插入内容
- after() - 在被选元素之后插入内容
- before() - 在被选元素之前插入内容
4.3 删除元素
- remove() - 删除被选元素(及其子元素)
- empty() - 从被选元素中删除子元素
4.4 CSS类
- addClass() - 向被选元素添加一个或多个类
- removeClass() - 从被选元素删除一个或多个类
- toggleClass() - 对被选元素进行添加/删除类的切换操作
- css() - 设置或返回样式属性
4.5 CSS方法
css()
5、jQuery遍历
- parent()
- parents()
- parentsUntil()
- children():返回被选元素的所有直接子元素
- find():所有后代元素
- siblings():所有同胞元素
- next():下一个同胞元素
6、AJAX
异步JavaScript和XML,在不加载整个网页的情况下。AJAX通过后台加载数据,并在网页上进行显示
- $.ajax()
- $.get()
- $.post()
五、MVC和三层模型
1、三层模型
- web:编写servlet,处理前台发送来的数据
- service:位于web层与Dao层之间,处理业务逻辑
- dao:用于和数据库交互
2、MVC模型
- M:model:模型模块,存储与操作的数据。对应于数据库,JavaBean。
- V:view:视图模块。系统应该具备和用户交流的能力。jsp,html。
- C:control:控制模块,控制视图和数据的连接。三层模型是对该层的细分。
3、异步检测用户名是否可用
解决这个问题的思路是在前台页面使用Ajax接收用户输入的用户名,然后发送到后台进行检测,返回特定的信息代表是否可用,然后Ajax中根据特定的信息回显告诉用户是否可用。
$.ajax({
//将要请求的servlet
url:"/user/register",
type:"post",
data:{userName:userName,password:password},
//返回的数据格式
dataType:"json",
success: function (data) {
//根据返回的code进行不同的操作
if(data.code==-1){
$("#message").text(data.message);
}else{
$("#message").text(data.message+",立即为您跳转页面");
setTimeout(function () {
location.href="/resource/pages/login.jsp";
},2000)
}
}
})
@WebServlet("/user/register")
public class Resgiter extends HttpServlet {
private UserService userService = new UserService();
@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 {
UserBean user = WebUtils.populate(UserBean.class,req);
//message是我们自己定义的一个类,里面有三个成员变量:code、message与data
//用于给Ajax返回数据,Ajax拿到数据之后进行判断用户名是否可用
ResponseMessage message = new ResponseMessage();
if(user.getUserName()==null||"".equals(user.getUserName().trim())){
message.setCode(-1);
message.setMessage("对不起,用户名不能为空");
WebUtils.writeOut(resp,message);
return;
}
//这个方法是用来检查用户名是否可用,返回的是boolean值
boolean flg = userService.checkUserName(user.getUserName());
if(!flg){
message.setCode(-1);
message.setMessage("对不起,用户名已经存在");
WebUtils.writeOut(resp,message);
return;
}
if(user.getPassword()==null||"".equals(user.getPassword().trim())){
message.setCode(-1);
message.setMessage("对不起,密码不能为空");
WebUtils.writeOut(resp,message);
return;
}
if(!user.getPassword().equals(user.getRepassword())){
message.setCode(-1);
message.setMessage("对不起,两次密码不一致");
WebUtils.writeOut(resp,message);
return;
}
//这个方法用来保存 用户
flg = userService.saveUser(user);
if(flg){
message.setCode(1);
message.setMessage("恭喜您,注册成功");
WebUtils.writeOut(resp,message);
}else{
message.setCode(-1);
message.setMessage("对不起,用户名已经存在");
WebUtils.writeOut(resp,message);
}
}
}
4、Ajax上传图片
function chooseImg(){
$("#icon").click();
}
function upload(){
//创建一个FormData对象用来存放文件
var fromData = new FormData();
var img = $("#icon")[0].files[0];
fromData.append("file",img);
$.ajax({
url:"/file/upload",
type:"post",
data:fromData,
contentType:false, //控制拼接格式
processData:false, //控制转字符串
cache:false,
dataType:"json",
success:function (data) {
if(data.code==1){
$("#img").attr("src","/file/getImg?fileName="+data.data[0])
}else{
alert("对不起上传失败");
}
}
})
@WebServlet("/file/upload")
public class Upload 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 {
ResponseMessage message = new ResponseMessage();
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
List<String> names = new ArrayList<>();
try {
//通过解析器解析req,返回的是一个List,每一个FileItem是一个文件
List<FileItem> items = servletFileUpload.parseRequest(req);
for (FileItem item : items) {
String oldName = item.getName();
//生成新的唯一的文件名
String newName = UUID.randomUUID().toString()+System.currentTimeMillis();
newName+= oldName.substring(oldName.lastIndexOf("."));
//根据新的文件名在文件服务器上创建一个新文件
FileOutputStream fos = new FileOutputStream("d:\\ceshi\\"+newName);
InputStream is = item.getInputStream();
byte[] bs = new byte[8192];
int len;
while ((len = is.read(bs)) != -1) {
fos.write(bs, 0, len);
}
fos.close();
names.add(newName);
}
message.setCode(1);
message.setMessage("上传完毕");
//将新的文件名的集合返回去
message.setData(names);
WebUtils.writeOut(resp,message);
return;
} catch (FileUploadException e) {
e.printStackTrace();
}
//如果上传文件出现了异常
message.setCode(-1);
message.setMessage("上传失败");
WebUtils.writeOut(resp,message);
}
}
网友评论