上一篇讲了ServletContent、ServletCOnfig、HTTPSession、request、response几个对象的生命周期、作用范围和一些用法。今天通过一个小项目运用这些知识。简单的注册登录,文件的上传和下载。


大致思路:

  注册登录和文件上传和下载
        注册成功后跳转到登录界面,登陆成功后跳转到主界面,主界面有上传和下载功能。
    本次注册登录不用数据库,注册成功后放到一个map集合中,key值为账号,value值为密码。
    注册成功把当前用户信息放入map集合并且使用ServletContent对象保存。

一:准备阶段

  先在WebContent目录下创建几个html页面。

  注册页面 register.html :

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>注册</title>
  6. </head>
  7. <body>
  8. <br><br><br>
  9. <!-- action代表form表单提交给那个servlet处理
  10. method指定提交方式:get代表把参数拼接在url后面
  11. post代表把参数放在http请求体中
  12. -->
  13. <form action="register" method="post">
  14. <div align="center">
  15. <span>账号</span><input type="text" name="username">
  16. <br>
  17. <span>密码</span><input type="password" name="pw">
  18. <div align="center">
  19. <input type="submit" value="注册"/>
  20. </div>
  21. </div>
  22. </form>
  23. </body>
  24. </html>

    登录界面login.html:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>登录</title>
  6. </head>
  7. <body>
  8. <br><br><br>
  9. <form action="login" method="post">
  10. <div align="center">
  11. <span>账号</span><input type="text" name="username">
  12. <br>
  13. <span>密码</span><input type="password" name="pw">
  14. <br>
  15. <div align="center">
  16. <input type="submit" value="登陆"/>
  17. </div>
  18. </div>
  19. </form>
  20. </body>
  21. </html>

 注册失败提示页面registerError.html:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>注册错误提示</title>
  6. </head>
  7. <body>
  8. <div align="center">
  9. <h1>账号重复</h1>
  10. <br>
  11. <a href="register.html">跳转到注册界面</a>
  12. </div>
  13. </body>
  14. </html>

  登录失败提示页面loginError.html:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>登录错误提示</title>
  6. </head>
  7. <body>
  8. <div align="center">
  9. <h1>账号密码错误</h1>
  10. <br>
  11. <a href="login.html">跳转到登录界面</a>
  12. </div>
  13.  
  14. </body>
  15. </html>

  功能页面success.html:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>主界面</title>
  6. </head>
  7. <body>
  8. <div align="center">
  9. <!-- enctype这个属性管理的是表单的MIME编码。共有三个值可选:
  10. 1、application/x-www-form-urlencoded
  11. 2、multipart/form-data
  12. 3、text/plain
  13. 文件上传值需要指定multipart/form-data
  14. -->
  15. <h1>文件上传</h1>
  16. <form action="upload" method="post" enctype="multipart/form-data">
  17. <input type="text" name="username" />
                <br>
                <input type="file" name="MyImage" />
                <br>
                <input type="submit" value="上传" />
  18. </form>
  19. </div>
  20.  
  21. <br><br>
  22. <div align="center">
  23. <!--
  24. 指定几个文件提供下载
            等后面学了jsp,el表达式和jstl和新标签库可以拓展项目
            通过ServletContent对象调用getResourcePaths("/download")可以获得
            该目录下的所有内容。【/download/文件名】,然后利用这几个技术动态的资源列举出来
            供下载。
  25. -->
  26. <h1>文件下载</h1>
  27. <a href="download?fileName=1.jpg">1.jpg</a>
  28. <br>
  29. <a href="download?fileName=movie.wmv">moviemwmv</a>
  30. </div>
  31.  
  32. </body>
  33. </html>

  文件长传和下载在webContent目录下创建两个文件夹upload和download,在download文件夹下放几个资源供下载。

  准备阶段完成后就可以开始着手写servlet。

二:编写注册和登录的servlet

  注册和登录的servlet代码【注意:需要把<url-pattern>...</url-pattern>首字母改成小写和html页面对应】:

    

  1. package com.briup.servlet.function;
  2.  
  3. import java.io.IOException;
  4. import java.util.HashMap;
  5. import java.util.Map;
  6. import java.util.Set;
  7.  
  8. import javax.servlet.ServletException;
  9. import javax.servlet.http.HttpServlet;
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletResponse;
  12.  
  13. /**
  14. * Servlet implementation class Register
  15. * 注册
  16. */
  17. public class Register extends HttpServlet {
  18. private static final long serialVersionUID = 1L;
  19.  
  20. public Register() {
  21. super();
  22. }
  23.  
  24. @Override
  25. public void init() throws ServletException {
  26. //创建一个Map集合,然后通过ServletContent对象存进去
  27. Map<String,String> map = new HashMap<String,String>();
  28. this.getServletContext().setAttribute("map", map);
  29. }
  30.  
  31. @SuppressWarnings("unchecked")
  32. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  33. throws ServletException, IOException {
  34. //获取注册的账号和密码
  35. String name = request.getParameter("username");
  36. String pw = request.getParameter("pw");
  37.  
  38. //和map集合对比【不对账号密码格式做验证】
  39. Map<String,String> map = (Map<String, String>)
  40. this.getServletContext().getAttribute("map");
  41. if(map.isEmpty()) {
  42. map.put(name, pw);
  43. //客户端重定向到登录界面
  44. response.sendRedirect("login.html");
  45. } else {
  46. Set<String> key = map.keySet();
  47. //注册只需要对比账号,密码重复无所谓
  48. for(String s : key) {
  49. if(s.equals(name)) {
  50. //重定向到注册错误页面
  51. response.sendRedirect("registerError.html");
  52. } else {
  53. map.put(name, pw);
  54. //客户端重定向到登录界面
  55. response.sendRedirect("login.html");
  56. }
  57. }
  58. }
  59. }
  60.  
  61. protected void doPost(HttpServletRequest request, HttpServletResponse response)
  62. throws ServletException, IOException {
  63. doGet(request, response);
  64. }
  65.  
  66. }
  1. package com.briup.servlet.function;
  2.  
  3. import java.io.IOException;
  4. import java.util.Map;
  5. import java.util.Set;
  6.  
  7. import javax.servlet.ServletException;
  8. import javax.servlet.http.HttpServlet;
  9. import javax.servlet.http.HttpServletRequest;
  10. import javax.servlet.http.HttpServletResponse;
  11.  
  12. /**
  13. * Servlet implementation class Login
  14. * 登录Servlet
  15. */
  16. public class Login extends HttpServlet {
  17. private static final long serialVersionUID = 1L;
  18.  
  19. public Login() {
  20. super();
  21. }
  22.  
  23. @SuppressWarnings("unchecked")
  24. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  25. throws ServletException, IOException {
  26. //获取账号密码
  27. String name = request.getParameter("username");
  28. String pw = request.getParameter("pw");
  29.  
  30. //获取map集合
  31. Map<String,String> map = (Map<String, String>)
  32. this.getServletContext().getAttribute("map");
  33. if(map.isEmpty()) {
  34. //服务器内部跳转到错误界面
  35. request.getRequestDispatcher("loginError.html").forward(request, response);
  36. } else {
  37. Set<String> keySet = map.keySet();
  38. for(String s : keySet) {
  39. if(s.equals(name) && map.get(s).equals(pw)) {
  40. /*
  41. * 注意:执行到服务器内部跳转语句或客服端重定向不会中止函数的执行
  42. * 和return在函数的作用不一样
  43. * 会继续执行下去如果跳转语句和重定向后面还有语句
  44. */
  45. //System.out.println(s + "," + map.get(s));
  46. //response.sendRedirect("success.html");
  47. request.getRequestDispatcher("success.html").forward(request, response);
  48. //需要显式的加上return
  49. return;
  50. }
  51. }
  52. //System.out.println("......");
  53. //如果代码执行到这里说明账号或密码不对
  54. //response.sendRedirect("loginError.html");
  55. request.getRequestDispatcher("loginError.html").forward(request, response);
  56. }
  57. }
  58.  
  59. protected void doPost(HttpServletRequest request, HttpServletResponse response)
  60. throws ServletException, IOException {
  61. // TODO Auto-generated method stub
  62. doGet(request, response);
  63. }
  64.  
  65. }

三:文件的下载

  文件的下载和客户端重定向有点类似,向浏览器发送数据,但是要告诉浏览器这是文件下载要保存下来而不是当做html页面解析。

response有个方法:getWriter():PrintWriter;获得一个字符输出流,该输出流可以向客户端输出数据。文件下载是否可以通过其写到页面?

  传输文件一般用字节流,有个类似的方法getOutputStream()可以获得字节流,通过该字节流向浏览器发送数据。

response.setContentType("text/html;charset=utf-8")设置发给浏览器的是html页面【默认】,那么文件下载需要设置为那个?application/x-download。

需要注意的是:我们需要获取下载文件的绝对路径,项目会被部署到tomcat安装目录下的webapp目录下,而在src的源代码则在 "项目名/WEB-INF/classes"下,

使用相对路径就会出错。

Dowload.java代码:

  1. package com.briup.servlet.function;
  2.  
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. import java.io.IOException;
  6. import java.net.URLEncoder;
  7.  
  8. import javax.servlet.ServletException;
  9. import javax.servlet.ServletOutputStream;
  10. import javax.servlet.http.HttpServlet;
  11. import javax.servlet.http.HttpServletRequest;
  12. import javax.servlet.http.HttpServletResponse;
  13.  
  14. /**
  15. * Servlet implementation class Download
  16. * 文件下载
  17. */
  18. public class Download extends HttpServlet {
  19. private static final long serialVersionUID = 1L;
  20.  
  21. //把下载目录配置在web.xml中作为参数
  22. private String path;
  23.  
  24. @Override
  25. public void init() throws ServletException {
  26. path = this.getServletConfig().getInitParameter("path");
  27. }
  28.  
  29. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  30. throws ServletException, IOException {
  31. // 获得用户需要下载文件的名字
  32. String fileName = request.getParameter("fileName");
  33.  
  34. // 下载文件所在目录的绝对路径
  35. String realPath = getServletContext().getRealPath(path);
  36.  
  37. // 设置为下载application/x-download
  38. response.setContentType("application/x-download");
  39.  
  40. // 下载文件时显示的文件保存名称
  41. String fileDisplay = "cnblogs_"+fileName;
  42. // 中文编码转换
  43. fileDisplay = URLEncoder.encode(fileDisplay, "UTF-8");
  44.  
  45. //设置响应头部信息
  46. response.addHeader("Content-Disposition", "attachment;filename="+fileDisplay);
  47. try {
  48. ServletOutputStream out = response.getOutputStream();
  49. File file = new File(realPath,fileName);
  50. FileInputStream in = new FileInputStream(file);
  51. byte[] b = new byte[1024];
  52. int len = -1;
  53. while ((len = in.read(b)) != -1) {
  54. out.write(b, 0, len);
  55. }
  56. out.flush();
  57. in.close();
  58. out.close();
  59. } catch (Exception e) {
  60. e.printStackTrace();
  61. }
  62. }
  63.  
  64. protected void doPost(HttpServletRequest request, HttpServletResponse response)
  65. throws ServletException, IOException {
  66. // TODO Auto-generated method stub
  67. doGet(request, response);
  68. }
  69.  
  70. }

在web.xml中servlet的配置:

  1. <servlet>
  2. <description></description>
  3. <display-name>Download</display-name>
  4. <servlet-name>Download</servlet-name>
  5. <servlet-class>com.briup.servlet.function.Download</servlet-class>
  6. <init-param>
  7. <param-name>path</param-name>
  8. <param-value>/download</param-value>
  9. </init-param>
  10. </servlet>
  11. <servlet-mapping>
  12. <servlet-name>Download</servlet-name>
  13. <url-pattern>/download</url-pattern>
  14. </servlet-mapping>

  有时候会出现中文乱码,由于没有约定好。可以通过requst.setEncoding(编码)来解析浏览器发送过来的数据,通过

response.setEnconding(编码)告诉浏览器以那种编码解析服务器发送过来的数据。如果有多个servlet需要设置编码,每个都这样设置会显得麻烦,有时候会忘记。

这时候过滤器就可以起到很好的作用。

  

  过滤器,顾名思义,就是过滤掉一些东西。在web中过滤器像一个中介一样在浏览器和服务器中间做一些工作,对web管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。比如:不登录就不允许你访问主界面,实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

  实现javax.servlet.Filter接口的类就是过滤器。和Servlet一样Filter的创建和销毁也是由WEB服务器负责。不过与Servlet区别的是,它是1>在应用启动的时候就进行装载Filter类(与Servlet的load-on-startup配置效果相同)。2>容器创建好Filter对象实例后,调用init()方法。接着被Web容器保存进应用级的集合容器中去了等待着,用户访问资源。3>当用户访问的资源正好被Filter的url-pattern拦截时,容器会取出Filter类调用doFilter方法,下次或多次访问被拦截的资源时,Web容器会直接取出指定Filter对象实例调用doFilter方法(Filter对象常驻留Web容器了)。4>当应用服务被停止或重新装载了,则会执行Filter的destroy方法,Filter对象销毁。

这次我们使用Filter做个编码过滤器,代码:

  1. package com.briup.servlet.filter;
  2.  
  3. import java.io.IOException;
  4. import javax.servlet.Filter;
  5. import javax.servlet.FilterChain;
  6. import javax.servlet.FilterConfig;
  7. import javax.servlet.ServletException;
  8. import javax.servlet.ServletRequest;
  9. import javax.servlet.ServletResponse;
  10.  
  11. /**
  12. * Servlet Filter implementation class EncodingFilter
  13. */
  14. public class EncodingFilter implements Filter {
  15.  
  16. private String encoding;
  17.  
  18. public EncodingFilter() {
  19. // TODO Auto-generated constructor stub
  20. }
  21.  
  22. public void destroy() {
  23. // TODO Auto-generated method stub
  24. }
  25.  
  26. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  27. throws IOException, ServletException {
  28. //设置编码格式【只对post方式有效】;
  29. request.setCharacterEncoding(encoding);
  30. response.setCharacterEncoding(encoding);
  31. //放行;
  32. chain.doFilter(request, response);
  33. }
  34.  
  35. public void init(FilterConfig fConfig) throws ServletException {
  36. //我们把编码设置在web.xml中,如果需要改编码在配置文件中更改而不需要更改代码
  37. encoding = fConfig.getInitParameter("encoding");
  38. }
  39.  
  40. }

web.xml配置:

  1. <filter>
  2. <display-name>EncodingFilter</display-name>
  3. <filter-name>EncodingFilter</filter-name>
  4. <filter-class>com.briup.servlet.filter.EncodingFilter</filter-class>
  5. </filter>
  6. <filter-mapping>
  7. <filter-name>EncodingFilter</filter-name>
  8. <!-- "*"通配符代表拦截所有请求 -->
  9. <url-pattern>/*</url-pattern>
  10. </filter-mapping>

运行项目看效果:

 

四:文件的上传

  网上有许多的上传组件,common-fileupload组件是apache的一个开源项目之一,用该组件可实现一次上传一个或多个文件,并可限制文件大小。

该组件需要用到两个jar包,我用的是commons-fileupload-1.2.2.jar,commons-io-2.0.1.jar。到网上下载这两个jar包然后放到WEB-INF/lib目录下【该目录可以放本项目用到的jar包,会自动构建,和tomcat服务器下的lib目录相似,不过后者的作用范围更大,添加进服务器的项目都可以使用里面的jar包】。

源码:

  

  1. package com.briup.servlet.function;
  2.  
  3. import java.io.File;
  4. import java.io.IOException;
  5. import java.util.List;
  6.  
  7. import javax.servlet.ServletException;
  8. import javax.servlet.http.HttpServlet;
  9. import javax.servlet.http.HttpServletRequest;
  10. import javax.servlet.http.HttpServletResponse;
  11.  
  12. import org.apache.commons.fileupload.FileItem;
  13. import org.apache.commons.fileupload.disk.DiskFileItemFactory;
  14. import org.apache.commons.fileupload.servlet.ServletFileUpload;
  15.  
  16. /**
  17. * Servlet implementation class Upload
  18. */
  19. public class Upload extends HttpServlet {
  20. private static final long serialVersionUID = 1L;
  21.  
  22. private String path;
  23.  
  24. public Upload() {
  25. super();
  26. }
  27.  
  28. @Override
  29. public void init() throws ServletException {
  30. path = this.getServletConfig().getInitParameter("path");
  31. }
  32.  
  33. @SuppressWarnings("unchecked")
  34. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  35. throws ServletException, IOException {
  36.  
  37. // 获得上传目录的绝对路径
  38. String realpath = this.getServletContext().getRealPath(path);
  39. System.out.println(path);
  40.  
  41. try {
  42. // 构造一个文件上传处理对象
  43. DiskFileItemFactory factory = new DiskFileItemFactory();
  44. ServletFileUpload upLoad = new ServletFileUpload(factory);
  45.  
  46. // 获得表单中提交内容
  47. List<FileItem> list = upLoad.parseRequest(request);
  48.  
  49. for (FileItem fileItem : list) {
  50. // fileItem.isFormField()返回true表示是普通的表单组件
  51. // fileItem.isFormField()返回false表示是上传
  52.  
  53. // 代表普通的输入框,获取内容方式不同以往
  54. if (fileItem.isFormField()) {
  55. // getName()方法返回的是文件名字 普通表单组件有文件 返回NULL
  56. String FieldName = fileItem.getFieldName();
  57. String Content = fileItem.getString("UTF-8");
  58. // 为了后面可以把普通参数从request中拿出来
  59. request.setAttribute(FieldName, Content);
  60. } else {
  61. // 取得上传文件的名字
  62. String fileName = fileItem.getName();
  63. // 避免文件名字重复
  64. fileName = System.currentTimeMillis() + fileName;
  65. File file = new File(realpath, fileName);
  66. // 把上传文件进行指定目录
  67. fileItem.write(file);
  68. }
  69. }
  70. System.out.println("request.getAttribute(\"username\") = " + request.getAttribute("username"));
  71.  
  72. } catch (Exception e) {
  73. e.printStackTrace();
  74. }
  75. }
  76.  
  77. protected void doPost(HttpServletRequest request, HttpServletResponse response)
  78. throws ServletException, IOException {
  79. doGet(request, response);
  80. }
  81.  
  82. }

web.xml中该servlet的配置:

  1. <servlet>
  2. <description></description>
  3. <display-name>Upload</display-name>
  4. <servlet-name>Upload</servlet-name>
  5. <servlet-class>com.briup.servlet.function.Upload</servlet-class>
  6. <init-param>
  7. <param-name>path</param-name>
  8. <param-value>/upload</param-value>
  9. </init-param>
  10. </servlet>
  11. <servlet-mapping>
  12. <servlet-name>Upload</servlet-name>
  13. <url-pattern>/upload</url-pattern>
  14. </servlet-mapping>

效果浏览:

java web(四):request、response一些用法和文件的上传和下载的更多相关文章

  1. 初学Java Web(7)——文件的上传和下载

    文件上传 文件上传前的准备 在表单中必须有一个上传的控件 <input type="file" name="testImg"/> 因为 GET 方式 ...

  2. 【温故知新】Java web 开发(三)Form表单与上传下载文件

    简介:在一和二的基础之上,这次来记录下如何在页面提交表单数据,以及文件的上传和下载整个流程,请求也不仅限于GET了,也有POST了. 1. 为了方便,在 webapp 下直接新建一个 index.ht ...

  3. Java中文件的上传与下载

    文件的上传与下载主要用到两种方法: 1.方法一:commons-fileupload.jar  commons-io.jar apache的commons-fileupload实现文件上传,下载 [u ...

  4. java实现文件的上传和下载

    1. servlet 如何实现文件的上传和下载? 1.1上传文件 参考自:http://blog.csdn.net/hzc543806053/article/details/7524491 通过前台选 ...

  5. java 文件的上传和下载

    主要介绍使用 smartupload.jar 包中的方法对文件的上传和下载.上传时文件是存放在服务器中,我用的是tamcat. 首先建立一个servlet 类,对文件的操作 package com.d ...

  6. java实现ftp文件的上传与下载

    最近在做ftp文件的上传与下载,基于此,整理了一下资料.本来想采用java自带的方法,可是看了一下jdk1.6与1.7的实现方法有点区别,于是采用了Apache下的框架实现的... 1.首先引用3个包 ...

  7. java客户端文件的上传和下载

    java客户端文件的上传和下载 //上传 public JTable upload(String id){ JTable table=new JTable(); System.out.println( ...

  8. .net web开发——文件的上传和下载

    以ASP.NET Core WebAPI 作后端 API ,用 Vue 构建前端页面,用 Axios 从前端访问后端 API ,包括文件的上传和下载. 准备文件上传的API #region 文件上传  ...

  9. Java Web之文件的上传及下载

    一.文件的上传 1. 简介 > 将一个客户端的本地的文件发送到服务器中保存. > 上传文件是通过流的形式将文件发送给服务器. 2.表单的设置 1.向服务器上传一个文件时,表单要使用post ...

随机推荐

  1. 认识jQuery

    JQ的优势 轻量级. 强大的选择器 出色的DOM操作的封装 可靠的事件处理机制 完善的Ajax 不污染顶级变量 出色的浏览器兼容性 链式操作 隐式迭代 行为层与结构层分离 丰富的插件支持 完善的文档 ...

  2. 界面控件DevExpress发布v18.2.7,新版全新出发|附下载

    DevExpress Universal Subscription(又名DevExpress宇宙版或DXperience Universal Suite)是全球使用广泛的.NET用户界面控件套包,De ...

  3. python的列表生成式

    列表生成式 列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式. 举个例子,要生成list [1, 2, 3, 4, 5, 6, 7, ...

  4. error: `cout' was not declared in this scope

    原因:C++ 1998 要求cout and endl被调用使用'std::cout'和'std::endl'格式,或using namespace std; 修改后:#include<iost ...

  5. 自学python之路(day2)

    1. 格式化输出 %表示占位符 ,s表示字符串 ,d表示数字,%s就是代表字符串占位符,%d,是数字占位符 示例1:输入用户的姓名.性别.年龄.爱好的通用模板 name = input("请 ...

  6. zookeeper 启动 zookeeper_server.pid: Permission denied

    在启动zookeeper的时候 报错 没有权限 以为是 zookeeper 没有权限 然后 chmod -R 777 zookeeper/ 之后还是不行. 后来 才发现 原来是我 /tmp/zooke ...

  7. 基于Java Instrument的Agent实现

    使用 Instrumentation,使得开发者可以构建一个独立于应用程序的代理程序(Agent),用来监测和协助运行在 JVM 上的程序,甚至能够替换和修改某些类的定义.有了这样的功能,开发者就可以 ...

  8. openSUSE安装Qt5

    找了很多资料发现没一个好用又简单的. 终于在wiki.qt.io上找到了一个! 安装方法如下: 1下载安装包,我建议最好下载离线包.下载链接http://download.qt.io/archive/ ...

  9. 3.14 unittest之skip

    3.14 unittest之skip 前言当测试用例写完后,有些模块有改动时候,会影响到部分用例的执行,这个时候我们希望暂时跳过这些用例.或者前面某个功能运行失败了,后面的几个用例是依赖于这个功能的用 ...

  10. 将lvm逻辑卷分出一部分

    今天公司磁盘报警,查看磁盘发现挂载的/aa空间还很多,而/ee 空间不足,现将/aa上的lvm分出一部分空间.加到/ee上 注:首先要 df  -T  -h 开一下磁盘格式如果是xfs格式的lvm  ...