Servlet 教程,servlet 在线

2101Servlet 文件上传

对于一般的文件直接用 a 标签的话,如下代码所示。由于浏览器可以解析jpg和txt文件,故不会直接下载而是在其他网页打开:

<a href="/IT/download/1.gif" rel="nofollow">下载图片</a>
<a href="/IT/download/day10.doc" rel="nofollow">下载文档</a>
<a href="/IT/download/day10.txt" rel="nofollow">下载笔记</a>

如果想要完成直接下载的目的,可以通过Servlet进行操作,做了一个简单的html页面

<a href="/IT/download?name=1.gif" rel="nofollow">下载图片1</a>
<a href="/IT/download?name=day10.doc" rel="nofollow">下载文档1</a>
<a href="/IT/download?name=day10.txt" rel="nofollow">下载笔记1</a>

我为download注册了一个servlet,xml描写如下:

<servlet>
    <servlet-name>DownloadServlet</servlet-name>
    <servlet-class>com.response.download.DownloadServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>DownloadServlet</servlet-name>
    <url-pattern>/download</url-pattern>
</servlet-mapping>

由于我的请求方式是get方式,所以只需在DownloadServlet这个类中重写doGet方法,代码实现如下:

public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
    //获取文件名
    String filename=request.getParameter("name");
    //防止读取name名乱码
    filename=new String(filename.getBytes("iso-8859-1"),"utf-8");
    //在控制台打印文件名
    System.out.println("文件名:"+filename);
    
     //设置文件MIME类型  
    response.setContentType(getServletContext().getMimeType(filename));  
    //设置Content-Disposition  
    response.setHeader("Content-Disposition", "attachment;filename="+filename);
    
    //获取要下载的文件绝对路径,我的文件都放到WebRoot/download目录下
    ServletContext context=this.getServletContext();
    String fullFileName=context.getRealPath("/download/"+filename);
    
    //输入流为项目文件,输出流指向浏览器
    InputStream is=new FileInputStream(fullFileName);
    ServletOutputStream os =response.getOutputStream();
    
    /*
     * 设置缓冲区
     * is.read(b)当文件读完时返回-1
     */
    int len=-1;
    byte[] b=new byte[1024];
    while((len=is.read(b))!=-1){
        os.write(b,0,len);
    }
    //关闭流
    is.close();
    os.close();
    
}

2100Servlet 数据库访问

由于更新的 MySQL8.0,所以本网站提供的 jar 包:mysql-connector-java-5.1.39-bin.jar 就不能用了,连接时会报:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server

这个异常。

需要重新下载,下载地址 https://dev.mysql.com/downloads/file/?id=484819,暂时我下载到的是 mysql-connector-java-8.0.15 替换这个 jar 包后,又出现异常 java.sql.SQLException: The server time zone value,只需在数据库地址后边添加 serverTimezone=UTC 即可,例如:

DB_URL = "jdbc:mysql://localhost:3306/servlet_db?serverTimezone=UTC";

还有注册 jdbc 的驱动也换了。

注册 JDBC 驱动器:

Class.forName("com.mysql.cj.jdbc.Driver");

2099Servlet 数据库访问

进行数据库插入操作的时候使用 PreparedStatement 更好,好处如下:

  • 1.PreparedStatement可以写动态参数化的查询;
  • 2.PreparedStatement比 Statement 更快;
  • 3.PreparedStatement可以防止SQL注入式攻击

实例:

//编写预处理 SQL 语句
String sql= "INSERT INTO websites1 VALUES(?,?,?,?,?)";

//实例化 PreparedStatement
ps = conn.prepareStatement(sql);

//传入参数,这里的参数来自于一个带有表单的jsp文件,很容易实现
ps.setString(1, request.getParameter("id"));
ps.setString(2, request.getParameter("name"));
ps.setString(3, request.getParameter("url"));
ps.setString(4, request.getParameter("alexa"));
ps.setString(5, request.getParameter("country"));

//执行数据库更新操作,不需要SQL语句
ps.executeUpdate();
sql = "SELECT id, name, url FROM websites1";
ps = conn.prepareStatement(sql);

//获取查询结果
ResultSet rs = ps.executeQuery();

2098Servlet 编写过滤器

过滤器中我们可以根据 doFilte() 方法中的 request 对象获取表单参数信息,例如我们可以获取到请求的用户名和密码进行逻辑处理,也可以通过 response 对用户做出回应。比如如果验证用户名不正确,禁止用户访问 web 资源,并且向浏览器输出提示,告诉用户用户名或者密码不正确等等;

public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {

    //获取请求信息(测试时可以通过get方式在URL中添加name)
    //http://localhost:8080/servlet_demo/helloword?name=123
    String name = req.getParameter("name");

    // 过滤器核心代码逻辑
    System.out.println("过滤器获取请求参数:"+name);
    System.out.println("第二个过滤器执行--网站名称:www.facesoho.com");

    if("123".equals(name)){
        // 把请求传回过滤链
        chain.doFilter(req, resp);
    }else{
        //设置返回内容类型
        resp.setContentType("text/html;charset=GBK");

        //在页面输出响应信息
        PrintWriter out = resp.getWriter();
        out.print("<b>name不正确,请求被拦截,不能访问web资源</b>");
        System.out.println("name不正确,请求被拦截,不能访问web资源");
    }
}

2097Servlet 表单数据

request.getParameterValues(String name) 是获得如 checkbox 类(名字相同,但值有多个)的数据,接收数组变量 ,如 checkobx 类型。

request.getParameter(String name) 是获得相应名的数据,如果有重复的名,则返回第一个的值,接收一般变量 ,如 text 类型。