玖叶教程网

前端编程开发入门

Web时代-Servlet

Servlet

今天文章较长,因为包含了几个案例,请耐心看。

Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。

使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。

Java Servlet 通常情况下与使用 CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。但是相比于 CGI,Servlet 有以下几点优势:

  • 性能明显更好。
  • Servlet 在 Web 服务器的地址在空间内执行。这样它就没有必要再创建一个单独的进程来处理每个客户端请求。
  • Servlet 是独立于平台的,因为它们是用 Java 编写的。
  • 服务器上的 Java 安全管理器执行了一系列限制,以保护服务器计算机上的资源。因此,Servlet 是可信的。
  • Java 类库的全部功能对 Servlet 来说都是可用的。它可以通过 sockets 和 RMI 机制与 applets、数据库或其他软件进行交互。

Servlet生命周期

Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:

  • Servlet 初始化后调用 init () 方法。
  • Servlet 调用 service() 方法来处理客户端的请求。
  • Servlet 销毁前调用 destroy() 方法。
  • 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

现在让我们详细讨论生命周期的方法。

Servlet调用过程

Servlet的调

源于视频

Servlet过滤器与监听器

Servlet 过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息。

可以将一个或多个 Servlet 过滤器附加到一个 Servlet 或一组 Servlet。Servlet 过滤器也可以附加到 JavaServer Pages (JSP) 文件和 HTML 页面。调用 Servlet 前调用所有附加的 Servlet 过滤器。

Servlet 过滤器是可用于 Servlet 编程的 Java 类,可以实现以下目的:

  • 在客户端的请求访问后端资源之前,拦截这些请求。
  • 在服务器的响应发送回客户端之前,处理这些响应。

例如:统一字符编码,字符的压缩,加密,实施安全控制等;

与过滤器有关的有三个包:Filter FilterChain和FilterConfig;

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);
    }
}

IOUtils

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();
                    }
              }
        }
}

ok 今天的回顾就这么多了,我们紧接着看下关于javaweb的一些有关的面试题吧。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言