文件传输
XML前后台接受
dom4j 可以解析或者打包XML
1 创建文档对象
Document doc=DocumentHelper.createDocument()
返回一个Document对象
2 创建一个根节点
Element root = doc.addElement("root标签>");
3 在根节点下,创建子元素
Element newsEle=root.addElement("子标签");
Element title=newsEle.addElement("字标签中的内容");
4 在子元素中写入内容或者属性
title.addText("我是标题");
添加了属性
title.addAttribute("id","titleOne");
其他的同理
最后,调用文档的方法 doc.asXML();
返回一个字符串
在前台可以使用js脚本对传来的数据进行解析
例如
var str = "";
$(data).find(news).each(function(){
var title = $(this).children("title").text(); //获取每个news标签下的title内容
var content = $(this).children("content").text(); //获取每个news标签下的content内容
str = str+title+" "+content+"<br/>"
})
$("#div").html(str);
JSON后台接收
利用fastJson或者其他的网上组件包,可以简便的对从前端传入的json对象进行解析。
ajax中json的获取方法与链接一致,通过request.getParameter();来获取
从前台传入的json对象可能是 单个对象{[a,b,c,d,e]}或{k1:v1, k2:v2},也可能是对象数组( [obj1, obj2 obj3])
如果传递过来的是一个对象,那么采用 fastJSON.jar包中 JSON.parseObject(jsondata,class)
例如
Map<Stirng, String> map = JSON.parseObject(list, Map.class);
如果传递过来的是一个数组,那么使用List list = JSON.parseArray(jsondata);
解析不当将会出现错误
在java后台是date对象,经过JSON.parse() 方法后,前台得到的是秒
jQuery Pagination Ajax分页使用
Pagination插件是一款免费开源的jQuery插件其官网 http://paginationjs.com/index.html,在github上也开源了。在这个的首页上有许多的demo演示。接下来介绍如何使用这个插件,以及如何实现Ajax分页。
HTML部分,需要指定两个div,其id属性为下,得到的数据将放入数据容器中,分页按钮在分页容器中
<div id="data-container"></div>
<div id="pagination-container"></div>
一般的使用
如果不实现异步请求,那么需要获取所有需要分页的数据,然后会自动交给分页工具,根据设置的每页显示pageSize,自动计算页码等信息,需要传入显示的template,放置数据。
Pagination Ajax使用
$('#pagination-container').pagination({
dataSource: "servlet/ServletAsync?op=pagingNews", //异步请求的地址
locator:"data", //当返回对象是object时,不会直接丢给pagination处理,而是要经过这个定位数据位置,默认是整个数据data
totalNumber:total, //总记录数,异步请求时必须填写
showGoInput: true, //是否显示跳页输入框
showGoButton: true, //是否显示跳页按钮
pageSize:5, //每页显示个数
alias: {
pageNumber: 'curPage', //
pageSize: 'everyPage'
},
formatGoInput: "<input type='text' class='J-paginationjs-go-pagenumber' >",
// 每次翻页时触发的回调函数
callback: function(data, pagination ) { //data当前页的数据,pagination当前页的信息
var html = simpleTemplating(data); //显示数据的模板
$('#data-container').html(html); //添加到页面当中
}
});
//数据要放入的模板,例如我这里是放入到表格中,data为每次ajax获取的数据
function simpleTemplating(data) {
var html = "<table>";
var d = new Date();
$.each(data, function(index, item){
html += "<tr>";
html += "<td>"+ item.newsid+"</td>";
html += "<td>"+ item.newstypename+"</td>";
html += "<td>"+ item.title+"</td>";
d.setTime(item.newsTime);
html += "<td>"+ d.toLocaleDateString()+"</td>";
html += "</tr>";
});
html += "</table>";
return html;
}
未解决的一个小问题
Pagination插件要实现异步请求的话,必须知道总的记录数,意味着你必须要多请求一次。因此,当访问的数据量很大的时候,该插件的响应时间会有点长。
文件的上传和下载
使用jsp+servlet的方式(见慕课教程)
使用jsp+servlet实现文件的上传和下载的大体思路如下:
文件的上传
对于上传的文件,我们需要读取它,然后放置到一个临时文件内(为什么不直接存取呢?因为上传的流中除了我们想要的信息外,还有其他信息),获取上传的文件名,建立一个输出流,将临时文件中的内容写入到服务器下的文件中,然后删除文件。具体代码实现如下(在servlet中)
InputStream inp = request.getInputStream();
String tempFile = "D:/web/tempFile";
File temp = new File(tempFile);
if (!temp.exists()){
temp.createNewFile();
}
FileOutputStream fos = new FileOutputStream(temp);
byte[] bts = new byte[1024];
int n =0;
while(( n= inp.read(bts)) != -1 ){
fos.write(bts, 0, n);
}
fos.close();
inp.close();
RandomAccessFile ras = new RandomAccessFile(temp, "r");
ras.readLine();
//针对文件名含有中文时,进行的转码
String head = new String(ras.readLine().getBytes("ISO-8859-1"),"utf-8");
//文件名可能为“/xxxx”或者是 "xxxx",因此使用两种获取文件名的方式
int beginIndex = head.lastIndexOf("/")+1;
if (beginIndex==0){
beginIndex = head.lastIndexOf("=")+2;
}
int endIndex = head.lastIndexOf("\"");
//获取文件名
String fileName = head.substring(beginIndex, endIndex);
System.out.println(fileName);
//文件的开始位置在head下一行开始的“换行符” 结束位置在倒数第一个换行符
ras.seek(0);
long startPos =0L;
int j = 1;
// 文件的内容通过 firebug可以发现是从第四行开始的,以换行符开始
while((n=ras.readByte())!= -1 && j<=4){
if ( n == '\n' ){
startPos = ras.getFilePointer();
j++;
}
}
startPos = ras.getFilePointer() - 1;
//获取文件截止的位置
ras.seek(ras.length());
long endPos = ras.getFilePointer();
int k =1;
//内容结束时倒数第二行
while(endPos >=0 && k<=2){
endPos--;
ras.seek(endPos);
if( ras.readByte()== '\n'){
k++;
}
}
endPos = endPos -1;
//保存文件到我们的服务器路径下
String path = getServletContext().getRealPath("/")+"load";
File f = new File(path);
if (!f.exists()){
f.mkdir();
}
File saveFile = new File(path, fileName);
RandomAccessFile saveRas = new RandomAccessFile(saveFile, "rw");
//将指针放在内容开始的地方
ras.seek(startPos);
while(startPos<endPos){
saveRas.write(ras.readByte());
startPos=ras.getFilePointer();
}
saveRas.close();
ras.close();
temp.delete();//删除临时文件
文件的下载
首先我们需要从请求中获取要下载的文件名,然后找出在服务器上的绝对路径,创建出file对象,如果文件不存在,返回一个错误的信息,文件存在,设置response的编码格式和响应头,然后我们从服务器内读取文件,写入到servletOutputStream 中。然后关闭流。代码实现如下
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
/*获得请求的文件名*/
String fileName = request.getParameter("filename");
System.out.println(fileName);
/*得到在服务器下的存储路径*/
String path = getServletContext().getRealPath("/")+"load\\"+fileName;
System.out.println(path);
/*创建File对象*/
File f = new File(path);
if (f.exists()){
/*设置编码格式*/
response.setContentType("application/x-msdownload");
/*由于HTTP头部的默认编码为ISO-8859-1而我们上传文件于下载文件过程中,提取到的文件名都要通过HTTP头部。
所以我们需要在上传的时候对提取到的文件名进行转码为UTF-8,然后在下载时我们也要进行反向转码为ISO-8859-1.*/
String temp = new String(fileName.getBytes("utf-8"),"ISO-8859-1");
/*设置请求头,表明以附件的形式进行下载*/
response.setHeader("Content-Disposition", "attachment; filename=\""+temp+"\"");
System.out.println(response.getHeader("Content-Disposition"));
InputStream ins = new FileInputStream(f);
ServletOutputStream output = response.getOutputStream();
byte[] bts = new byte[1024];
int n=0;
while((n = ins.read(bts)) != -1 ){
output.write(bts, 0, n);
}
output.close();
ins.close();
}else {
System.out.println("文件不存在");
}
使用SmartUpload插件来进行下载和上传
上传的input控件必须要有name属性,其值可以是任意。
如果文件不存在,除了可以创建文件之外,也可以创建文件夹
String realPath=this.getServletContext().getRealPath("/")+"loads";RealPath
将会获得文件在服务器的绝对路径,如果你工程名为web 直接是 localhost:8080/web/
需要创建一个SmartUpload对象出来
并实例化
String filename = request.getParameter("filename");
SmartUpload up = new SmartUpload();
up.initialize(getServletConfig(), request, response);
up.upload();
up.save("/load/"); 设置你的保存路径
在数据库中存储的,应该是保存路径+文件名, 利用文件名寻找
通过点击文件的链接来实现下载文件
<a href="*servlet*?filename=xxxx">下载xxxx</a>
在后台的servlet中
String filename = request.getParameter("filename");
SmartUpload up = new SmartUpload();
up.initialize(getServletConfig(), request, response);
up.downloadFile("/load/"+filename); //"填写的是当前context下的文件夹和文件名"
up.setContentDisposition(null); //设置不再网页打开,而是以插件下载
JNDI与连接池
在tomcat下conf文件夹内context.xml文件下的context标签中设置如下设置(如果是在serve.xml中配置则是对于当前的项目有效)
<!-- JNDI -->
<Environment name="testJNDI" value="hello JNDI" type="java.lang.String" />
<!-- JNDI -->
<Resource
name="jdbc/news"
auth="Container" //应用管理者 Container 由tomcat容器 或者 Application web应用管理
type="javax.sql.DataSource"
maxActive="50" //最大活跃的链接数
maxIdle="10" //最大空闲链接
maxWait="10000" //最大等待时间
username="root"
password="123456"
driverClassName="com.mysql.jdbc.Driver" //数据库连接驱动
url="jdbc:mysql://127.0.0.1:3306/news?characterEncoding=utf-8"
/>
使用JNDI必须在服务器容器内使用,也就是说,在一般的java main方法是无法运行的。
Context context = new InitialContext(); /*javax.naming 包*/
DataSource ds =(DataSource) context.lookup("java:comp/env/jdbc/news"); /*Datasource java.sql包中*/
conn =ds.getConnection();
过滤器
过滤,顾名思义,对请求内容进行筛选,让符合一定规则的请求,继续执行,不符合的则挡在外面。
一个过滤器的产生和消亡需要经历4个阶段
实例、初始化(在服务器启动的时候)、过滤和销毁(在服务关闭的时候)。
如果存在多个过滤器,那么他们实例和初始化的顺序是随机的,与在web.xml中书写的顺序无关,书写顺序只与他们的触发顺序有关
使用服务器,需要再javaWeb工程下配置web.xml文件添加上的内容标签为
<filter>
<filter-name>过滤器名</filter-name>
<filter-class>实现类</filter-name>
</filter>
<filter-mapping>
<filter-name>过滤器名</filter-name>
<!-- 例如"/*"表示对所有文件进行过滤操作,包括图片和其他; "/dir/*"表示对某个文件夹下的所有文件过滤; "*.html"表示过滤HTML文件 -->
<url-pattern>要过滤的文件</url-pattern>
</filter-mapping>
这里需要解释一下过滤的意思。过滤其实是一种控制,比方说设置过滤的文件为a.html,那么所有访问a.html的请求,都必须要经过过滤器的审核,然后才真正的进入了a.html文件。
创建一个过滤器要求必须实现javax.servlet.Filter
接口,重写其中的init(); destroy(); 和 doFilter()方法,在doFilter方法中有3个参数,其中2个ServletRequest和ServletResponse是 servlet中 HttpServletRequest和HttpServletResponse的父类,因此可以使用其中的大部分方法,特定情况下,也是可以类型转换为子类对象。
过滤结束后,放行是通过FilterChain的doFilter()方法,可以将请求送入下一个过滤器,或者阻挡返回,或者传送到指定路径
doFilter(ServletRequest arg0, ServletResponse arg1)
过滤器链如果下一个没有过滤器了,那么chain就会送至目标url 而什么都不做则页面空白。
过滤器的url-pattern 无法实现同时对路径过滤和对文件类型过滤 比如 /admin/*.jsp 这样是不合法的,实现这个需求的方法是在过滤器中做操作
可以在filter标签中继续配置一个针对转发的标签
指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。用户可以设置多个子元素用来指定 Filter 对资源的多种调用方式进行拦截。
子元素可以设置的值及其意义
- REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。
- INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
- FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
- ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。