今天文章较长,因为包含了几个案例,请耐心看。 Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。 使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。 Java Servlet 通常情况下与使用 CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。但是相比于 CGI,Servlet 有以下几点优势: Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程: 现在让我们详细讨论生命周期的方法。 Servlet的调 源于视频 Servlet 过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息。 可以将一个或多个 Servlet 过滤器附加到一个 Servlet 或一组 Servlet。Servlet 过滤器也可以附加到 JavaServer Pages (JSP) 文件和 HTML 页面。调用 Servlet 前调用所有附加的 Servlet 过滤器。 Servlet 过滤器是可用于 Servlet 编程的 Java 类,可以实现以下目的: 例如:统一字符编码,字符的压缩,加密,实施安全控制等; 与过滤器有关的有三个包:Filter FilterChain和FilterConfig; 版本二: IOUtils ok 今天的回顾就这么多了,我们紧接着看下关于javaweb的一些有关的面试题吧。Servlet
Servlet生命周期
Servlet调用过程
Servlet过滤器与监听器
Filter:所有过滤器都必须实现这个接口;
生命周期:web应用加载后立即创建这个web应用的所有过滤器,创建后是驻留在内存中init();过滤器初始化,容器会创建实例后调用这个方法
FilterConfig:代表web.xml中对filter的配置信息
获取servletContext对象
获取初始信息
FilterChain:doFilter();用于调用过滤器链中的下一个过滤器,如果是最后一个则将请求提交给处理程序或响应到客户端上;filterChain代表一个连对象,一个资源可以用多个过滤器进行拦截,拦截顺序和filtermapping的顺序决定链的最后一各节点就是访问的资源;
FilterConfig:用于过滤器初始化阶段提供过滤器的名字,初始化参数,servlet上下文的信息;
String getFilterName();返回web.xml文件定义的名称
ServletContext getServletContext()方法,返回调用者所处的Servlet的上下文
String getInitParameter(String name):返回配置过滤器名是name的初始值;‘
Enumeration getgetInitParameterNames()以Enumeration形式返回过滤器所有初始化参数的名称
出现servlet3.0后在eclipes中就不需要配置web.xml了
如何进行创建出filter中的参数,写在web.xml中是不能实现的:
范式:创建filter过滤器,然后在其中的参数列表中选择是否创建参数,然后在改下对应的url-parttern参数
让他对应你的jsp文件就可以解决这个问题;
@WebFilter(
urlPatterns = { "/jsp/index.jsp" },
initParams = {
@WebInitParam(name = "count", value = "5000")
})
用filterConfig来获取属性的值是多少
filterConfig.getInitParameter(String name);
@WebFilter(asyncSupported = true, description = "filterdemo", urlPatterns = { "/*" })
在myeclipse中就必须在web.xml逐一配置出来
有:
<filter>
<filter-name>Filter1</filter-name>
<filter-class>cn.itcast.filter.Filter1</filter-class>
</filter>
<!-- 配置过滤器去拦截哪个资源 -->
<filter-mapping>
<filter-name>Filter1</filter-name>
<url-pattern>/hello.jsp</url-pattern>
<dispatcher>REQUEST</dispatcher>--用来配置以哪种方式对资源的访问(request/forward/include/error)
可以配置多个dispatcher如果不配置默认为request请求
</filter-mapping>
@WebFilter(asyncSupported = true, description = "filterdemo", urlPatterns = { "/demo1Filr" })
public class Demo1Filter implements Filter {
/**
* Default constructor.
*/
public Demo1Filter() {
// TODO Auto-generated constructor stub
}
/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
System.out.println("filter销毁了");
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
// place your code here
System.out.println("demo1前");
// pass the request along the filter chain
//意思是执行下一个节点可以为过滤器可以为资源
chain.doFilter(request, response);
System.out.println("demo1后");
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
System.out.println("filter创建了");
}
}
Servlert经典实例
文件上传
/**
* Servlet implementation class UploaddisckServlet
*/
@WebServlet("/UploaddisckServlet")
@MultipartConfig
public class UploaddisckServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public UploaddisckServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//1.上传文件
String upload=this.getServletContext().getRealPath("WEB-INF/upload");
String temp=this.getServletContext().getRealPath("WEB_INF/temp");
//创建工厂设置缓冲大小和穿就缓冲区路径
DiskFileItemFactory factory=new DiskFileItemFactory();
factory.setSizeThreshold(1024*100);
factory.setRepository(new File(temp));
//2.生产文件上传核心类
ServletFileUpload fileUpload=new ServletFileUpload(factory);
//设置编码
fileUpload.setHeaderEncoding("UTF-8");
//设置文件大小的上传限制
fileUpload.setFileSizeMax(1024*1024*10);
fileUpload.setSizeMax(1024*1024*100);
//检查当前是项目是否为上传文件
//if (fileUpload.isMultipartContent(request)) {
//throw new RuntimeException("请用正确的表单上传");
//}
//解析request
//3.利用文件上传核心类来解析request
try {
List<FileItem> list=fileUpload.parseRequest(request);
Map<String,String> map=new HashMap<>();
//循环遍历
for(FileItem item :list){
if (item.isFormField()) {
//普通的字段获得的是一个表单
String name=item.getFieldName();
String value=item.getString("utf-8");
map.put(name, value);
System.out.println(name+":"+value);
}else{
//当前一个文件上传项
String filename=item.getName();//文件名
//设置一个独一无二的文件名
String uuidfilename=UUID.randomUUID().toString()+"_"+filename;
map.put("realname", filename);
map.put("uuidname",uuidfilename);
map.put("ip", request.getRemoteAddr());
String savepath="/WEB-INF/upload";
//转换为hash值
int hash=uuidfilename.hashCode();
//转化为hash字符串
String hashstr=Integer.toHexString(hash);
char[] hss=hashstr.toCharArray();
for(char c:hss){
upload+="/"+c;
savepath+="/"+c;
}
new File(upload).mkdirs();
map.put("savepath", savepath);
InputStream inputStream=item.getInputStream();
OutputStream outputStream=new FileOutputStream(new File(upload,uuidfilename));
IOUtils.In2Out(inputStream, outputStream);
IOUtils.close(inputStream, outputStream);
//删除临时文件
item.delete();
}
}
//像数据库中插入
Resource resource=new Resource();
BeanUtils.populate(resource, map);
String sql="insert into netdisk values(null,?,?,?,?,null,?)";
QueryRunner runner=new QueryRunner(DaoUtils.getSource());
runner.update(sql,resource.getUuidname(),resource.getRealname(),resource.getSavepath(),resource.getIp(),resource.getDescription() );
//3.重定向回主页
response.sendRedirect(request.getContextPath()+"/disk/index.jsp");
} catch (FileUploadException | IllegalAccessException | InvocationTargetException | SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
/**
* Servlet implementation class UploadServlet
*/
@WebServlet(description = "文件上传", urlPatterns = { "/UploadServlet" })
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpSep=rvlet()
*/
public UploadServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//通过工厂类来实现
DiskFileItemFactory factory=new DiskFileItemFactory();
//设置缓冲区大小
factory.setSizeThreshold(100*1024);
//设置临时文件夹
factory.setRepository(new File(this.getServletContext().getRealPath("WEB-INF/temp")));
//2.生产文件上传核心类
ServletFileUpload fileUpload=new ServletFileUpload(factory);
try {
//判断是否为真正的表单上传文件
//if (fileUpload.isMultipartContent(request)) {
//throw new RuntimeException("请用正确的表单上传");
//}
//设置文件大小的上传限制
fileUpload.setFileSizeMax(1024*1024*10);
fileUpload.setSizeMax(1024*1024*100);
//设置编码
fileUpload.setHeaderEncoding("UTF-8");
//设置上传监听进度条:
fileUpload.setProgressListener(new ProgressListener() {
//
Long beginTime = System.currentTimeMillis();
//已经读了,总共多少 ,读到第几个了
@Override
public void update(long pBytesRead, long pContentLength, int pItems) {
// TODO Auto-generated method stub
//转换为kb
//double br=pBytesRead*1.0/1024;
//double cl=pContentLength*1.0/1024;
//为了保留字节用以下方法
BigDecimal br = new BigDecimal(pBytesRead).divide(new BigDecimal(1024),2,BigDecimal.ROUND_HALF_UP);
BigDecimal cl = new BigDecimal(pContentLength).divide(new BigDecimal(1024),2,BigDecimal.ROUND_HALF_UP);
System.out.print("当前读取的是第"+pItems+"个上传项,总大小"+cl+"KB,已经读取"+br+"KB");
//剩余字节数
BigDecimal ll = cl.subtract(br);
System.out.print("剩余"+ll+"KB");
//上传百分比
BigDecimal per = br.multiply(new BigDecimal(100)).divide(cl,2,BigDecimal.ROUND_HALF_UP);
System.out.print("已经完成"+per+"%");
//上传用时
Long nowTime = System.currentTimeMillis();
Long useTime = (nowTime - beginTime)/1000;
System.out.print("已经用时"+useTime+"秒");
//上传速度
BigDecimal speed = new BigDecimal(0);
if(useTime!=0){
//四舍五入模式向“最近邻居”转弯,除非两个邻居都是等距的,在这种情况下是圆括弧的。
speed = br.divide(new BigDecimal(useTime),2,BigDecimal.ROUND_HALF_UP);
}
System.out.print("上传速度为"+speed+"KB/S");
//大致剩余时间
BigDecimal ltime = new BigDecimal(0);
if(!speed.equals(new BigDecimal(0))){
//返回一个 BigDecimal ,其值为 (this / divisor) ,其比例为指定。
ltime = ll.divide(speed,0,BigDecimal.ROUND_HALF_UP);
}
System.out.print("大致剩余时间为"+ltime+"秒");
System.out.println();
}
});
//3.利用文件上传核心类来解析request
List<FileItem> list=fileUpload.parseRequest(request);
//循环遍历
for(FileItem item :list){
if (item.isFormField()) {
//普通的字段获得的是一个表单??
String name=item.getFieldName();
String value=item.getString("utf-8");
System.out.println(name+":"+value);
}else{
//当前一个文件上传项
String filename=item.getName();//文件名
//设置一个独一无二的文件名
String uuidfilename=UUID.randomUUID().toString()+"_"+filename;
//转换为hash值
int hash=uuidfilename.hashCode();
//转化为hash字符串
String hashstr=Integer.toHexString(hash);
char[] hss=hashstr.toCharArray();
String path=this.getServletContext().getRealPath("upload");
for(char c:hss){
path+="/"+c;
}
new File(path).mkdirs();
InputStream inputStream=item.getInputStream();
OutputStream outputStream=new FileOutputStream(new File(path,uuidfilename));
IOUtils.In2Out(inputStream, outputStream);
IOUtils.close(inputStream, outputStream);
//删除临时文件
item.delete();
}
}
} catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException();
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
public class IOUtils {
private IOUtils() {
}
public static void In2Out(InputStream in,OutputStream out) throws IOException{
byte [] bs = new byte[1024];
int i = 0;
while((i=in.read(bs))!=-1){
out.write(bs,0,i);
}
}
public static void close(InputStream in,OutputStream out){
if(in!=null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}finally{
in = null;
}
}
if(out!=null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}finally{
out = null;
}
}
}
}
自动登录拦截器
package com.itheima.filter;
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import com.itheima.domain.User;
import com.itheima.util.DaoUtils;
/**
* Servlet Filter implementation class AutologinFilter
*/
@WebFilter(
description = "自动登录过滤器",
urlPatterns = { "/*" },
initParams = {
@WebInitParam(name = "encode", value = "utf-8", description = "编码过滤")
})
public class AutologinFilter implements Filter {
/**
* Default constructor.
*/
public AutologinFilter() {
// TODO Auto-generated constructor stub
}
/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
// place your code here
//1.只有未登录的才能自动登录
HttpServletRequest req=(HttpServletRequest)request;
HttpServletResponse rsp=(HttpServletResponse)response;
if (req.getSession(false)==null|| req.getSession().getAttribute("user")==null) {
//2.只有带自动登录的的cookie才能自动登录
Cookie[]cs=req.getCookies();
Cookie findC=null;
if (cs!=null) {
for(Cookie c:cs) {
if ("autologin".equals(c.getName())) {
findC=c;
break;
}
}
}
if (findC!=null) {
//3.自动登录cookie中保存的用户名密码正确才能登录
String name=findC.getValue().split(":")[0];
String password=findC.getValue().split(":")[1];
User user=null;
String sql="select *from user where name=?and password=?";
//数据库的操作
try {
QueryRunner runner=new QueryRunner(DaoUtils.getSource());
user=runner.query(sql,new BeanHandler<User>(User.class),name,password);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (user!=null) {
req.getSession().setAttribute("user", user);
}
}
}
// pass the request along the filter chain
chain.doFilter(request, response);
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
全站乱码过滤器
package com.itheima.filter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* Servlet Filter implementation class EncodingFilter
*/
@WebFilter(description = "全站乱码过滤器", urlPatterns = { "/*" },
initParams = {
@WebInitParam(name ="encode", value = "UTF-8")
})
public class EncodingFilter implements Filter {
private FilterConfig config=null;
private String encode=null;
/**
* Default constructor.
*/
public EncodingFilter() {
// TODO Auto-generated constructor stub
}
/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
// place your code here
//处理get请求的乱码
response.setCharacterEncoding(encode);
response.setContentType("text/html;charset="+encode);
//处理post请求乱码
//request.setCharacterEncoding(encode);
// pass the request along the filter chain
chain.doFilter(new MyHttpServletRequest((HttpServletRequest)request), response);
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
this.config=fConfig;
//获取参数看参数是哪一个然后把他设置给新的编码方式
encode=config.getInitParameter(encode)==null?"utf-8":config.getInitParameter(encode);
}
//装饰:写一个类实现被装饰的一个接口在构造方法传入被装饰者,不想改造的方法调用原有的方法,想改造
//的自己来写逻辑
class MyHttpServletRequest extends HttpServletRequestWrapper{
private HttpServletRequest request=null;
private boolean isNotEncode=true;
public MyHttpServletRequest(HttpServletRequest request) {
super(request);
// TODO Auto-generated constructor stub
this.request=request;
}
@Override
public String getParameter(String name) {
// TODO Auto-generated method stub
return getParameterValues(name)==null?null:getParameterValues(name)[0];
}
@Override
public Map<String, String[]> getParameterMap() {
// TODO Auto-generated method stub
try {
//post提交处理方式
if (request.getMethod().equalsIgnoreCase("post")) {
request.setCharacterEncoding(encode);
return request.getParameterMap();
}else if (request.getMethod().equalsIgnoreCase("get")) {
//get处理方式
Map<String, String[]> map=request.getParameterMap();
if (isNotEncode) {
for(Map.Entry<String, String[]> entry:map.entrySet()){
String[] vsString=entry.getValue();
for(int i=0;i<vsString.length;i++){
vsString[i]=new String(vsString[i].getBytes("iso8859-1"),encode);
}
}
isNotEncode=false;
}
return map;
}else{
return super.getParameterMap();
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException();
}
}
@Override
public String[] getParameterValues(String name) {
// TODO Auto-generated method stub
return getParameterMap().get(name);
}
}
}
邮件发送
public class MailUtils {
//email:邮件发给谁 subject:主题 emailMsg:邮件的内容
public static void sendMail(String email, String subject, String emailMsg)
throws AddressException, MessagingException {
// 1.创建一个程序与邮件服务器会话对象 Session
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "SMTP");//发邮件的协议
props.setProperty("mail.host", "localhost");//发送邮件的服务器地址
props.setProperty("mail.smtp.auth", "true");// 指定验证为true
// 创建验证器
Authenticator auth = new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("tom", "12345");//发邮件的账号的验证
}
};
Session session = Session.getInstance(props, auth);
// 2.创建一个Message,它相当于是邮件内容
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("[email protected]")); // 设置发送者
message.setRecipient(RecipientType.TO, new InternetAddress(email)); // 设置发送方式与接收者
message.setSubject(subject);//邮件的主题
message.setContent(emailMsg, "text/html;charset=utf-8");
// 3.创建 Transport用于将邮件发送
Transport.send(message);
}
}
(1) javax.mail.Properties类
JavaMail需要Properties来创建一个session对象。它将寻找字符串"mail.smtp.host",属性值就是发送邮件的主机.
用法:
Properties props = new Properties (); //Properties props = System.getProperties();
props.put("mail.smtp.host", "smtp.163.com");//可以换上你的smtp主机名。
(2) javax.mail.Session类
这个Session类代表JavaMail 中的一个邮件session. 每一个基于 JavaMail的应用程序至少有一个session但是可以有任意多的session。 在这个例子中, Session对象需要知道用来处理邮件的SMTP 服务器。
用法:
Session sendMailSession = Session.getInstance(props, null); //不须认证
(3) javax.mail.Transport类
邮件是既可以被发送也可以被受到。JavaMail使用了两个不同的类来完成这两个功能:Transport 和Store. Transport 是用来发送信息的,而Store用来收邮件。在这发送邮件我们只需要用到Transport对象。
用法:
Transport transport = sendMailSession.getTransport("smtp");
用JavaMail Session对象的getTransport 方法来初始化Transport。传过去的字符串申明了对象所要使用的协议,如"smtp"。这将为我们省了很多时间。因为JavaMail以经内置了很多协议的实现方法。
注意: JavaMail并不是绝对支持每一个协议,目前支持IMAP、 SMTP和 POP3.
(4) javax.mail.MimeMessage类
Message对象将存储我们实际发送的电子邮件信息,Message对象被作为一个MimeMessage对象来创建并且需要知道应当选择哪一个JavaMail session。
用法:
Message newMessage = new MimeMessage(sendMailSession);
(5) javax.mail.InternetAddress类
一旦您创建了 Session 和 Message,并将内容填入消息后,就可以用Address确定信件地址了。和 Message 一样,Address 也是个抽象类。您用的是Javax.mail.internet.InternetAddress 类.
用法:
InternetAddress from=new InternetAddress("[email protected]"); //收件人邮箱地址
(6) javax.mail.Store类
Store类实现特定邮件协议上的读、写、监视、查找等操作。通过Javax.mail.Store类可以访问Javax.mail.Folder类。
用法:
Store store=s.getSorte("pop3"); //s为一个邮件会话
store.connect(popserver,username,password);//通过你提供的popserver地址(邮箱服务器),用户名和密码登录你的邮箱
(7) javax.mail.Folder类
Folder类用于分级组织邮件,并提供照Javax.mail.Message格式访问email的能力。
用法:
Folder folder=store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);
(8) javax.mail.Internet.MimeMultipart
一般保存电子邮件内容的容器是Multipart抽象类,它定义了增加和删除及获得电子邮件不同部分内容的方法.由于Multipart是抽象类,我们必须为它使用一个具体的子类,JavaMail API提供javax.mail.Internet.MimeMultpart类来使用MimeMessage对象.
用法:
MimeMultipart multipart=new MimeMultipart();
注:我们使用MimeMultipart对象的一个方法是addBodyPart(),它在我们的电子邮件内容里添加BodyPart(BodyPart类在下面紧接着要介绍)对象.消息可以有很多部分,一个BodyPart可以代表一个部分.
(9) javax.mail.Internet.MimeBodyPart类
MimeBodyPart是BodyPart具体用于mimeMessage的一个子类.
MimeBodyPart对象代表一个MimeMessage对象内容的一部分.每个MimeBodyPart被认为有两部分:
⊙一个MIME类型
⊙匹配这个类型的内容
用法:
MimeBodyPart mdp=new MimeBodyPart();
String text="Hello JavaMail!";
//定义MIME类型为text/plain,并设置MimeBodyPart的内容.
mdp.setContent(text,"text/plain");
(10) javax.activation.DataHandler类(包含在JAF中)
JavaMail API不限制信息只为文本,任何形式的信息都可能作茧自缚MimeMessage的一部分.除了文本信息,作为文件附件包含在电子邮件信息的一部分是很普遍的.JavaMail API通过使用DataHandler对象,提供一个允许我们包含非文本BodyPart对象的简便方法.
用法:
DataHandler dh=new DataHandler(text,type);
mdp.setDatahandler(dh); //mdp是一个MimeBodyPart对象
(11) javax.activation.FileDataSource类(包含在JAF中)
一个FileDataSource对象可以表示本地文件和服务器可以直接访问的资源.一个本地文件可以通过创建一个新的MimeBodyPart对象附在一个mimeMessage对象上.
用法:
MimeMultipart mm=new MimeMultipart();
MimeBodyPart mdp=new MimeBodyPart();
FileDataSource fds=new FileDataSource("c:/exam.txt");
mdp.setDataHandler(new DataHandler(fds)); //设置数据源
mm.addBodyPart(mdp); //为当前消息MimeMultipart对象增加MimeBodyPart
(12) javax.activation.URLDataSource类(包含在JAF中)
远程资源,URL不会指向它们,由一个URLDataSource对象表示.一个远程资源可以通过创建一个新mimeBodyPart对象附在一个mimeMessage对象上(同FileDataSource差不多).
文件下载
package com.leo.crazy;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
/**
*下载
*download()方法负责按如下步骤来实现多线程下载。
(1)创建URL对象。
(2)获取指定URL对象所指向资源的大小(通过getContentLength()方法获得),此处用到了URLConnection类,该类代表Java应用程序和URL之间的通信链接。后面还有关于URLConnection更详细的介绍。
(3)在本地磁盘上创建一个与网络资源具有相同大小的空文件。
(4)计算每个线程应该下载网络资源的哪个部分(从哪个字节开始,到哪个字节结束)。
(5)依次创建、启动多个线程来下载网络资源的指定部分。
* @author leoi555
*@date 2018年10月20日
*/
public class DownUtil {
// 定义下载资源的路径
private String path;
// 指定所下载的文件的保存位置
private String targetFile;
// 定义需要使用多少个线程下载资源
private int threadNum;
// 定义下载的线程对象
private DownThread[] threads;
// 定义下载的文件的总大小
private int fileSize;
public DownUtil(String path, String targetFile, int threadNum)
{
this.path=path;
this.threadNum=threadNum;
// 初始化threads数组
threads=new DownThread[threadNum];
this.targetFile=targetFile;
}
public void download() throws Exception
{
URL url=new URL(path);
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5*1000);
conn.setRequestMethod("GET");
conn.setRequestProperty(
"Accept",
"image/gif, image/jpeg, image/pjpeg, image/pjpeg, "
+ "application/x-shockwave-flash, application/xaml+xml, "
+ "application/vnd.ms-xpsdocument, application/x-ms-xbap, "
+ "application/x-ms-application, application/vnd.ms-excel, "
+ "application/vnd.ms-powerpoint, application/msword, */*");
conn.setRequestProperty("Accept-Language", "zh-CN");
conn.setRequestProperty("Charset", "UTF-8");
conn.setRequestProperty("Connection", "Keep-Alive");
// 得到文件大小
fileSize=conn.getContentLength();
conn.disconnect();
int currentPartSize=fileSize / threadNum + 1;
RandomAccessFile file=new RandomAccessFile(targetFile, "rw");
// 设置本地文件的大小
file.setLength(fileSize);
file.close();
for (int i=0; i < threadNum; i++)
{
// 计算每个线程下载的开始位置
int startPos=i*currentPartSize;
// 每个线程使用一个RandomAccessFile进行下载
RandomAccessFile currentPart=new RandomAccessFile(targetFile,
"rw");
// 定位该线程的下载位置
currentPart.seek(startPos);
// 创建下载线程
threads[i]=new DownThread(startPos, currentPartSize,
currentPart);
// 启动下载线程
threads[i].start();
}
}
// 获取下载的完成百分比
public double getCompleteRate()
{
// 统计多个线程已经下载的总大小
int sumSize=0;
for (int i=0; i < threadNum; i++)
{
sumSize +=threads[i].length;
}
// 返回已经完成的百分比
return sumSize*1.0 / fileSize;
}
private class DownThread extends Thread
{
// 当前线程的下载位置
private int startPos;
// 定义当前线程负责下载的文件大小
private int currentPartSize;
// 当前线程需要下载的文件块
private RandomAccessFile currentPart;
// 定义该线程已下载的字节数
public int length;
public DownThread(int startPos, int currentPartSize,
RandomAccessFile currentPart)
{
this.startPos=startPos;
this.currentPartSize=currentPartSize;
this.currentPart=currentPart;
}
public void run()
{
try
{
URL url=new URL(path);
HttpURLConnection conn=(HttpURLConnection)url
.openConnection();
conn.setConnectTimeout(5*1000);
conn.setRequestMethod("GET");
conn.setRequestProperty(
"Accept",
"image/gif, image/jpeg, image/pjpeg, image/pjpeg, "
+ "application/x-shockwave-flash, application/xaml+xml, "
+ "application/vnd.ms-xpsdocument, application/x-ms-xbap, "
+ "application/x-ms-application, application/vnd.ms-excel, "
+ "application/vnd.ms-powerpoint, application/msword, */*");
conn.setRequestProperty("Accept-Language", "zh-CN");
conn.setRequestProperty("Charset", "UTF-8");
InputStream inStream=conn.getInputStream();
// 跳过startPos个字节,表明该线程只下载自己负责的那部分文件
inStream.skip(this.startPos);
byte[] buffer=new byte[1024];
int hasRead=0;
// 读取网络数据,并写入本地文件
while (length < currentPartSize
&& (hasRead=inStream.read(buffer)) !=-1)
{
currentPart.write(buffer, 0, hasRead);
// 累计该线程下载的总大小
length +=hasRead;
}
currentPart.close();
inStream.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}