文章目录

  • 手写一个微型下载资源网站【Java实现用户注册、登陆、下载功能】
    • 一、技术栈
    • 二、流程分析图
      • 注册
      • 登陆
      • 下载
    • 三、案例实现效果
      • 首页
      • 注册
      • 登陆
      • 下载网主页
      • 壁纸下载
      • 书籍下载
      • 影视下载
    • 四、案例代码实现
      • 注意事项
      • 1、数据库设计
      • 2、项目结构
        • 1)src
        • 2)web
        • 3)工具包
        • 4)配置文件
          • jdbc.properties
          • mybatis-config.xml
          • log4j.properties
        • 5)web页面
          • index.jsp
          • register.jsp
          • login.jsp
          • success.html
          • books.jsp
          • images.jsp
      • 3、后端业务代码实现
        • 1)test测试连接数据库
        • 2)util工具
          • SessionFactoryUtil 工具类
          • Filter过滤器未登录拦截访问
          • Listener监听器统计网站在线人数
        • 3)pojo实体类
          • User类
          • Book类
        • 4)dao层
          • UserMapper映射接口
          • BookMapper映射接口
        • 5)service层
          • UserService业务处理
          • BookService业务处理
        • 6)web层
          • CheckCodeServlet(生成验证码)
          • RegisterServlet实现类
          • LoginServlet实现类
          • LogoutServlet实现类
          • DownloadImageServlet实现类
          • QueryBooksServlet实现类
          • DownloadBookServlet
          • DownloadMovieServlet

手写一个微型下载资源网站【Java实现用户注册、登陆、下载功能】

一、技术栈

语言:Java

Web:html + css + js +bootstrap

数据库:MySQL8.2

服务器:Tomcat

开发环境:JDK–1.8 、Servlet–3.0 、ntelliJ IDEA、Navicat-11

所需知识:javase、servlet、http、request、response、cookie、session、jsp+el+jstl、filter、listener

知识点详细总结链接:

01-HTML+CSS+JS【常用总结+案例练习】

02-JavaWeb开发【Tomcat服务器&Servlet接口&HTTP协议&HttpServletRequest&BeanUtils工具包封装请求数据&HttpServletResponse】

03-JavaWeb开发【最详细的Cookie&Session分析】

04-JavaWeb开发【JSP&EL&JSTL&MVC&Bootstrap前端框架】

05-JavaWeb的三大组件:小程序Servlet+过滤器Filter+监听器Listener

二、流程分析图

注册

登陆

下载

三、案例实现效果

页面没有太多美化修饰,具体以后端业务实现为主哦!

首页

注册

登陆

下载网主页

壁纸下载

书籍下载

影视下载

四、案例代码实现

注意事项

可先看,这些处理概念。后面开发时需要处理的细节。

一、将下载的文件放到WEB-INF下面,更安全,用户不会通过浏览器对其访问。-------------------------------------------------------------二、关于乱码问题:
首先要处理接收请求中文乱码问题:request.setCharacterEncoding("utf-8");
然后解决响应给浏览器的乱码问题:
//解决响应体乱码问题
response.setContentType("text/html;charset=utf-8");
说明:上述只是解决响应体乱码问题,不能解决响应头乱码问题,由于告诉浏览器以附件形式下载,使用的文件名在响应头中响应给浏览器,所以上述不能解决乱码问题。所以我们采用另外一种解决方案。方案:URLEncoder按照UTF-8的编码方式对filename文件名进行编码。//设置浏览器以附件形式下载//对文件名编码String encodeFilename = URLEncoder.encode(filename, "UTF-8");response.setHeader("Content-Disposition","attachment;filename="+encodeFilename);--------------------------------------------------------------三、关于下载编写Servlet处理文件下载逻辑
1. 获取当前项目中资源的真实路径;
String realPath = getServletContext().getRealPath("/WEB-INF/"+filename);
2. 获取文件的mimeType;
String mimeType =  getServletContext().getMimeType(fileName);--------------------------------------------------------------四、关于设置文件为附件的形式
对于response.setHeader("Content-Disposition","attachment;filename="+encodeFilename);
1.如果不加attachment关键字,则用户点击图片就可以直接在浏览器查看图片了,而我们的功能是下载。
所以要加attachment关键字,attachment表示附件的意思。2.如果不书写 filename ,那么下载的文件名字就是当前servlet的路径名字。3.【文件下载】两个响应头+流拷贝1. 设置响应头: Content-Disposition    // 告诉浏览器以附件的形式来处理文件;2. 设置响应头: response.setContentType(mimeType) // 告诉浏览器下载的文件的类型;3. 流拷贝:1. 将文件读取到流里边: FileInputStream fin = new FileInputStream(file);2. 将流写给浏览器:response.getOutputStream().write(arr,0,len);

1、数据库设计

create database user_managerment;
use user_managerment;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(20) NOT NULL,`password` varchar(32) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'zhangsan', '1234');
INSERT INTO `user` VALUES ('2', 'lisi', '1234');
INSERT INTO `user` VALUES ('3', 'wangwu', '1234');
INSERT INTO `user` VALUES ('4', 'zhaoliu', '1234');

2、项目结构

1)src

2)web

3)工具包

4)配置文件

jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/user_managerment\?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false
jdbc.username=root
jdbc.password=1234
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--加载外部的配置文件--><properties resource="jdbc.properties"/><!--别名--><typeAliases><package name="cn.itcast.sh.login.pojo"/></typeAliases><!--mybatis环境的配置一个核心配置文件,可以配置多个运行环境,default默认使用哪个运行环境--><environments default="development"><!--通常我们只需要配置一个就可以了, id是环境的名字 --><environment id="development"><!--事务管理器:由JDBC来管理--><!--事务管理器type的取值:1. JDBC:由JDBC进行事务的管理2. MANAGED:事务由容器来管理,后期学习Spring框架的时候,所有的事务由容器管理--><transactionManager type="JDBC"/><!--数据源的配置:mybatis自带的连接池--><!--数据源:1. POOLED:使用mybatis创建的连接池2. UNPOOLED:不使用连接池,每次自己创建连接3. JNDI:由服务器提供连接池的资源,我们通过JNDI指定的名字去访问服务器中资源。--><dataSource type="POOLED"><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><!--映射器--><mappers><!--加载其它的映射文件 注:注解开发是点号--><!--<package name="com.itheima.sh.dao"></package>--><!--加载其它的映射文件 xml形式包扫描方式加载mapper映射文件,说明:1. 要求mapper映射文件,与mapper接口要放在同一个目录2. 要求mapper映射文件的名称,与mapper接口的名称要一致--><package name="cn.itcast.sh.login.dao"/></mappers>
</configuration>
log4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=D:/IdeaProjects/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n### set log levels - for more verbose logging change 'info' to 'debug' ###log4j.rootLogger=debug, stdout,file
5)web页面
index.jsp
<!DOCTYPE html>
<html lang="en">
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width, initial-scale=1.0"><!-- 指定网页的字符集为utf-8--><meta charset="utf-8"><!--使用微软最新的浏览器Edge的内核来解析当前的HTML文件,最新的浏览器都支持 --><meta http-equiv="X-UA-Compatible" content="IE=edge"><!--响应式布局参数:viewport: 视口的参数width=device-width:默认的网页宽度是设备的宽度initial-scale=1: 初始的缩放比1:1--><meta name="viewport" content="width=device-width, initial-scale=1"><!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --><!-- 1. 导入bootstrap的全局css样式  --><link href="css/bootstrap.min.css" rel="stylesheet"><title>Beauty下载网</title>
</head>
<body>
<!--<div align="left">-->
<!--    <a href="register.jsp" class="btn btn-success">用户注册</a>-->
<!--    <a href="login.jsp" class="btn btn-primary">用户登陆</a>-->
<!--</div>--><h3 font-siz:200px align="center">Beauty下载网</h3>
<hr><div class="container"><!-- 默认是白色,navbar-inverse  表示黑色--><nav class="navbar navbar-inverse"><!-- container-fluid 表示占容器nav的100%--><div class="container-fluid"><!-- navbar-header表示指定商标和开关的样式,让它在手机上更好的显示--><div class="navbar-header"><!--开关按钮--><!--data-toggle="collapse" 表示点击按钮时可以折叠data-target 点击开关按钮时,可以找到id是bs-example-navbar-collapse-1下拉菜单而我们发现下面的下拉菜单的id正好是 bs-example-navbar-collapse-1
--><button type="button" class="navbar-toggle collapsed" data-toggle="collapse"data-target="#bs-example-navbar-collapse-1"><!--开关按钮中的白线--><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><!--navbar-brand 表示商标 类似于苹果网站的苹果标志,无论设备窗口怎么变化,商标都会存在--><a class="navbar-brand" href="#">Beauty</a></div><!-- 下拉菜单,表单等 navbar-collapse 表示可以折叠的所有的项--><div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"><ul class="nav navbar-nav"><li class="active"><span class="sr-only">(current)</span></a><a href="/register.jsp" class="dropdown-toggle" data-toggle="dropdown"role="button" aria-haspopup="true" aria-expanded="false">注册<!--向下箭头--></a></li><li class="dropdown"><a href="/login.jsp" class="dropdown-toggle" data-toggle="dropdown"role="button" aria-haspopup="true" aria-expanded="false">登陆<!--向下箭头--></a></li><li class="dropdown"><a href="/images.jsp" class="dropdown-toggle" data-toggle="dropdown"role="button" aria-haspopup="true" aria-expanded="false">壁纸<!--向下箭头--><span class="caret"></span></a><!--下拉项--><ul class="dropdown-menu"><li><a href="#">风景</a></li><li><a href="#">美女</a></li><!--divider表示一条线--></ul></li><li class="dropdown"><a href="/books.jsp" class="dropdown-toggle" data-toggle="dropdown"role="button" aria-haspopup="true" aria-expanded="false">书籍<!--向下箭头--><span class="caret"></span></a><!--下拉项--><ul class="dropdown-menu"><li><a href="#">编程</a></li><li><a href="#">名著</a></li><!--divider表示一条线--></ul></li></li><!--dropdown表示下拉菜单--><li class="dropdown"><a href="/movies.jsp" class="dropdown-toggle" data-toggle="dropdown"role="button" aria-haspopup="true" aria-expanded="false">影视<!--向下箭头--><span class="caret"></span></a><!--下拉项--><ul class="dropdown-menu"><li><a href="#">电影</a></li><li><a href="#">动漫</a></li><!--divider表示一条线--></ul></li></ul><!--navbar-right表示form表单位于右侧--><form class="navbar-form navbar-right"><div class="form-group"><input type="search" class="form-control" placeholder="关键字"></div><button type="submit" class="btn btn-default">搜索</button></form></div><!-- /.navbar-collapse --></div><!-- /.container-fluid --></nav>
</div><br><br><br><br><br><br><div align="center" style="font-size: 17px"><figure><div><a href="/login.jsp" target="_blank"><span class="face">登陆</span><span class="face">Login</span></a></div></figure><br><figure><div><a href="register.jsp" target="_blank"><span class="face">注册</span><span class="face">Register</span></a></div></figure><br><figure><div><a href="https://music.163.com/#/discover/toplist" target="_blank"><span class="face">在线音乐</span><span class="face">Music</span></a></div></figure><br><figure><div><a href="#" target="_blank"><span class="face">软件下载</span><span class="face">Software</span></a></div></figure><br><figure><div><a href="success.html" target="_blank"><span class="face">网站主页</span><span class="face">Homepage</span></a></div></figure><br><div style="color: green"><span class="face">网站当前在线</span><span class="face">${applicationScope.loginNumber}人</span></a></div></div><br><br>
<br><br>
<br><br>
<br><br>
<br><br><br><br><br>
<div class="footer" align="center" style="font-size: 16px"><div class="foot_link"><a href="#">关于作者</a><span>|</span><a href="#">联系作者</a><span>|</span><a href="#">招聘合作</a><span>|</span><a href="#">友情链接</a></div><p>CopyRight © 2021 上海菜鸟程序员研学中心 All Rights Reserved</p><p>电话:010-5211314 沪ICP备666888号</p>
</div><script src="js/canvas-nest.js"></script>
<!-- 2. 导入 jQuery 框架 -->
<script src="js/jquery-3.2.1.min.js"></script>
<!-- 3. 导入bootstrap框架 -->
<script src="js/bootstrap.min.js"></script>
</body>
</html>
register.jsp
<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>注册页面</title><link href="css/bootstrap.min.css" rel="stylesheet"><link href="css/login.css" rel="stylesheet"><script src="js/jquery.js"></script><script src="js/bootstrap.js"></script>
</head><%--Created by IntelliJ IDEA.User: cflDate: 2021/05/01Time: 15:32To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>注册账户</title><link href="css/bootstrap.min.css" rel="stylesheet"><link href="css/login.css" rel="stylesheet"><script src="js/jquery.js"></script><script src="js/bootstrap.js"></script>
</head>
<body>
<div align="left"><a href="index.jsp" class="btn btn-success">首页</a>
</div>
<div class="container text-center"><form class="form-signin" action="/registerServlet" method="post"><h3 class="form-signin-heading">注册</h3><input type="text"  name="username" class="form-control" placeholder="用户名" required autofocus><br><input type="password"  name="password" class="form-control" placeholder="密码" required><br><button class="btn btn-lg btn-primary btn-block" type="submit">注册</button></form><font color="red" size="2px">${requestScope.megRegister}</font>
</div>
</body>
</html><div class="container text-center"><form class="form-signin" action="/registerServlet" method="post"><h2 class="form-signin-heading">注册页面</h2><input type="text"  name="username" class="form-control" placeholder="用户名" required autofocus><br><input type="password"  name="password" class="form-control" placeholder="密码" required><br><br><button class="btn btn-lg btn-primary btn-block" type="submit">注册</button></form>
</div></body>
</html>
login.jsp
<%--Created by IntelliJ IDEA.User: cflDate: 2021/04/27Time: 23:24To change this template use File | Settings | File Templates.
--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>登录账户</title><link href="css/bootstrap.min.css" rel="stylesheet"><link href="css/login.css" rel="stylesheet"><script src="js/jquery.js"></script><script src="js/bootstrap.js"></script><style type="text/css">#cookie {font-size: 2px;}#code {border-collapse: collapse;}#code #codeImg {padding: 1px 8px;}</style></head>
<body>
<div align="left"><a href="index.jsp" class="btn btn-success">首页</a><a href="register.jsp" class="btn btn-info">注册</a>
</div>
<div class="container text-center"><form class="form-signin" action="${pageContext.request.contextPath}/loginServlet" method="post"><h3 class="form-signin-heading">登录</h3><input type="text" name="username" value="${cookie.username.value}" class="form-control" placeholder="用户名"required autofocus><br><input type="password" name="password" value="${cookie.password.value}" class="form-control" placeholder="密码"required><table id="code" align="left"><tr><td><input type="text" name="checkCode"class="form-control" placeholder="验证码" required></td><td id="codeImg"><!--页面一加载就向checkCodeServlet发送请求--><img src="/checkCodeServlet" alt="验证码"style="cursor: pointer" onclick="changeCheckCode(this);"></td></tr></table><div align="left"><table><tr><td><span id="cookie"><b>记住用户名密码:</b></span></td><td><input type="checkbox" name="checkbox"></td></tr></table></div><br><button class="btn btn-lg btn-primary btn-block" type="submit">登录</button></form><font color="red" size="2px">${requestScope.messageUser}</font><font color="red" size="2px">${requestScope.messageCode}</font>
</div><script type="text/javascript">function changeCheckCode(obj) {obj.src = "/checkCodeServlet?" + new Date().getTime();}
</script></body>
</html>
success.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags --><meta name="description" content=""><meta name="author" content="">
<!--    nk rel="icon" href="../../favicon.ico">--><title>Beauty下载网</title><!-- Bootstrap core CSS --><link href="css/bootstrap.min.css" rel="stylesheet"><link href="css/dashboard.css" rel="stylesheet">
</head><body>
<nav class="navbar navbar-inverse navbar-fixed-top"><div class="container-fluid"><div class="navbar-header"><button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a class="navbar-brand" href="#">Beauty下载网</a></div><div id="navbar" class="navbar-collapse collapse"><ul class="nav navbar-nav navbar-right"><li class="active"><a href="#">收藏<span class="sr-only">(current)</span></a></li><li><a href="#">设置</a></li><li><a href="#">帮助</a></li><li><a href="/LogoutServlet">退出</a></li></ul><form class="navbar-form navbar-right"><input type="text" class="form-control" placeholder="Search..."></form></div></div>
</nav><div class="container-fluid"><div class="row"><div class="col-sm-3 col-md-2 sidebar"><ul class="nav nav-sidebar"><li class="active"><a href="#">用户中心<span class="sr-only">(current)</span></a></li><li><a href="/images.jsp">壁纸下载</a></li><li><a href="/queryBooksServlet">书籍下载</a></li><li><a href="/movies.jsp">影视下载</a></li></ul></div><div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"><h3 class="page-header">个人信息</h3><div class="row placeholders"><div class="col-xs-6 col-sm-3 placeholder"><img src="img/demo.jpg" width="100" height="100" class="img-responsive" alt="Generic placeholder thumbnail"><h5>username</h5>
<!--                    <span class="text-muted">Something else</span>--></div></div><!--            <h2 class="sub-header">Section title</h2>--></div></div>
</div><script src="js/jquery.js"></script>
<script>window.jQuery || document.write('<script src="js/jquery.js"><\/script>')</script>
<script src="js/bootstrap.js"></script></body>
</html>
books.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--Created by IntelliJ IDEA.User: cflDate: 2021/04/30Time: 16:29To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><!--使用微软最新的浏览器Edge的内核来解析当前的HTML文件,最新的浏览器都支持 --><meta http-equiv="X-UA-Compatible" content="IE=edge"><!--响应式布局参数:viewport: 视口的参数width=device-width:默认的网页宽度是设备的宽度initial-scale=1: 初始的缩放比1:1--><meta name="viewport" content="width=device-width, initial-scale=1"><!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --><!-- 1. 导入bootstrap的全局css样式  --><link href="css/bootstrap.min.css" rel="stylesheet"><title>书籍网</title><style>tr{height: 40px;/*行文本居中*/text-align: center;}table{/*table表格在页面居中显示*/margin: auto;/*border-collapse 属性设置表格的边框是否被合并为一个单一的边框属性值是collapse:如果可能,边框会合并为一个单一的边框。会忽略 border-spacing 属性*/border-collapse: collapse;}</style>
</head>
<body>
<div align="left"><a href="success.html" class="btn btn-success">首页</a>
</div><table border="1px" cellspacing="0" width="600"><caption><h2>书籍列表</h2></caption><tr><th>编号</th><th>书籍名称</th><th>作者</th><th>价格</th></tr><%--使用jstl结合EL从后台queryAllServlet的reques域对象中取出数据--%><c:forEach items="${requestScope.bookList}" var="book"><tr><td>${book.id}</td><td>${book.name}</td><td>${book.author}</td><td>${book.price}</td></tr></c:forEach>
</table>
<div align="center"><h3>书籍下载</h3><a href="/downloadBookServlet?filename=红楼梦.txt">红楼梦</a><br><a href="/downloadBookServlet?filename=西游记.txt">西游记</a><br><a href="/downloadBookServlet?filename=JavaEE-SSH实战开发.txt">JavaEE-SSH实战开发</a><br><a href="/downloadBookServlet?filename=三国演义.txt">三国演义</a><br>
</div><!-- 2. 导入 jQuery 框架 -->
<script src="js/jquery-3.2.1.min.js"></script>
<!-- 3. 导入bootstrap框架 -->
<script src="js/bootstrap.min.js"></script>
</body>
</html>
images.jsp
<%--Created by IntelliJ IDEA.User: cflDate: 2021/05/02Time: 19:43To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><!--使用微软最新的浏览器Edge的内核来解析当前的HTML文件,最新的浏览器都支持 --><meta http-equiv="X-UA-Compatible" content="IE=edge"><!--响应式布局参数:viewport: 视口的参数width=device-width:默认的网页宽度是设备的宽度initial-scale=1: 初始的缩放比1:1--><meta name="viewport" content="width=device-width, initial-scale=1"><!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --><!-- 1. 导入bootstrap的全局css样式  --><link href="css/bootstrap.min.css" rel="stylesheet"><title>壁纸下载</title>
</head>
<body><div align="left"><a href="success.html" class="btn btn-success">首页</a>
</div><br><h4 class="sub-header">壁纸下载</h4>
<hr>
<div align="center"><a href="/downloadImageServlet?filename=刘亦菲.jpg">刘亦菲.jpg</a><br><a href="/downloadImageServlet?filename=壁纸.jpg">壁纸.jpg</a><br><a href="/downloadImageServlet?filename=小兔子.jpg">小兔子.jpg</a><br><a href="/downloadImageServlet?filename=01.jpg">01.jpg</a><br><a href="/downloadImageServlet?filename=02.txt">02.txt</a><br><a href="/downloadImageServlet?filename=03.zip">03.zip</a><br>
</div><!-- 2. 导入 jQuery 框架 -->
<script src="js/jquery-3.2.1.min.js"></script>
<!-- 3. 导入bootstrap框架 -->
<script src="js/bootstrap.min.js"></script>
</body>
</html>

movies.jsp

<%--Created by IntelliJ IDEA.User: cflDate: 2021/05/01Time: 18:22To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>影视</title>
</head>
<body>
<a href="success.html">首页</a>
<h2>尚在开发中。。。。。</h2>
</body>
</html>

3、后端业务代码实现

1)test测试连接数据库
public static void main(String[] args) {//获取sessionSqlSession sqlSession = SessionFactoryUtil.getSqlSession();//获取接口对象UserMapper mapper = sqlSession.getMapper(UserMapper.class);//调用方法查询数据List<User> list = mapper.queryTest();list.forEach(System.out::println);sqlSession.close();
}
2)util工具
SessionFactoryUtil 工具类
/***  会话工厂工具类1. 通过静态方法得到一个工厂对象2. 通过静态方法得到会话对象**/
public class SessionFactoryUtil {//声明一个工厂对象private static SqlSessionFactory factory;//在静态代码块中创建会话工厂static {SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();//得到输入流try(InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");) {factory = builder.build(inputStream);} catch (IOException e) {e.printStackTrace();}}/**静态方法得到会话工厂*/public static SqlSessionFactory getSessionFactory() {return factory;}/**得到会话对象*/public static SqlSession getSqlSession() {return factory.openSession();}}
Filter过滤器未登录拦截访问

LoginFilter

@WebFilter({"/success.html", "/books.jsp", "/movies.jsp", "/images.jsp"})
public class LoginFilter implements Filter {@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) resp;System.out.println("-----过滤登陆访问-----");User user = (User) request.getSession().getAttribute("user");if (user == null) {/*   request.getRequestDispatcher("/login.jsp").forward(request, response);*/response.sendRedirect("/login.jsp");}chain.doFilter(request, response);}@Overridepublic void init(FilterConfig config) throws ServletException {}
}
Listener监听器统计网站在线人数

InitNumberListener

@WebListener
public class InitNumberListener implements ServletContextListener,HttpSessionListener, HttpSessionAttributeListener {// Public constructor is required by servlet specpublic InitNumberListener() {}// -------------------------------------------------------// ServletContextListener implementation// -------------------------------------------------------public void contextInitialized(ServletContextEvent sce) {System.out.println("-----初始化上下文对象-----");ServletContext servletContext = sce.getServletContext();servletContext.setAttribute("loginNumber", 0);}public void contextDestroyed(ServletContextEvent sce) {}// -------------------------------------------------------// HttpSessionListener implementation// -------------------------------------------------------public void sessionCreated(HttpSessionEvent se) {/* Session is created. */}public void sessionDestroyed(HttpSessionEvent se) {/* Session is destroyed. */}// -------------------------------------------------------// HttpSessionAttributeListener implementation// -------------------------------------------------------public void attributeAdded(HttpSessionBindingEvent sbe) {}public void attributeRemoved(HttpSessionBindingEvent sbe) {}public void attributeReplaced(HttpSessionBindingEvent sbe) {/* This method is invoked when an attributeis replaced in a session.*/}
}

LoginNumChangeListener

package cn.itcast.sh.login.listener;import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.*;@WebListener
public class LoginNumChangeListener implements ServletContextListener,HttpSessionListener, HttpSessionAttributeListener {// Public constructor is required by servlet specpublic LoginNumChangeListener() {}// -------------------------------------------------------// ServletContextListener implementation// -------------------------------------------------------public void contextInitialized(ServletContextEvent sce) {}public void contextDestroyed(ServletContextEvent sce) {}// -------------------------------------------------------// HttpSessionListener implementation// -------------------------------------------------------public void sessionCreated(HttpSessionEvent se) {/* Session is created. */HttpSession session = se.getSession();ServletContext servletContext = session.getServletContext();Integer loginNumber = (Integer) servletContext.getAttribute("loginNumber");servletContext.setAttribute("loginNumber", loginNumber+1);}public void sessionDestroyed(HttpSessionEvent se) {/* Session is destroyed. */HttpSession session = se.getSession();ServletContext servletContext = session.getServletContext();Integer loginNumber = (Integer) servletContext.getAttribute("loginNumber");servletContext.setAttribute("loginNumber",loginNumber-1);}// -------------------------------------------------------// HttpSessionAttributeListener implementation// -------------------------------------------------------public void attributeAdded(HttpSessionBindingEvent sbe) {}public void attributeRemoved(HttpSessionBindingEvent sbe) {}public void attributeReplaced(HttpSessionBindingEvent sbe) {/* This method is invoked when an attributeis replaced in a session.*/}
}
3)pojo实体类
User类
public class User {private Integer id;private String username;private String password;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +'}';}
}
Book类
public class Book {private int id;    //编号private String name;  //书名private String author;  //作者private double price;  //价格//setter/getterpublic int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "Book{" +"id=" + id +", name='" + name + '\'' +", author='" + author + '\'' +", price=" + price +'}';}
}
4)dao层
UserMapper映射接口
public interface UserMapper {@Select("select * from user")List<User> queryTest();@Select("select * from user where username=#{username} and password=#{password}")User queryUserByUserNameAndPassword(User user);@Insert("insert into user values(null,#{username},#{password})")void register(User user);}
BookMapper映射接口
public interface BookMapper {@Select("select * from book")List<Book> queryAllBooks();
}
5)service层
UserService业务处理
public class UserService {// 注册业务逻辑处理public boolean register(User user){SqlSession sqlSession = null;try {sqlSession = SessionFactoryUtils.getSqlSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);User us = userMapper.queryUserByUserNameAndPassword(user);if(us == null){userMapper.register(user);sqlSession.commit();return true;}else {return false;}}finally {assert sqlSession != null;sqlSession.close();}}// 登陆业务逻辑处理public boolean login(User user) {//处理业务逻辑//4. 通过会话工厂得到会话对象SqlSession session = SessionFactoryUtils.getSqlSession();//5. 会话对象得到UserMapper接口的代理对象UserMapper userMapper = session.getMapper(UserMapper.class);//接口对象调用方法User loginUser = userMapper.queryUserByUserNameAndPassword(user);session.close();// 方式一
/*        if (null == loginUser) {return  false;}else {return  true;}*/// 方式二// return loginUser == null ? false : true;return  loginUser != null;}}
BookService业务处理
public class BookService {public List<Book> queryAllBooks(){SqlSession sqlSession = SessionFactoryUtils.getSqlSession();BookMapper mapper = sqlSession.getMapper(BookMapper.class);List<Book> booksList = mapper.queryAllBooks();sqlSession.close();return booksList;}
}
6)web层
CheckCodeServlet(生成验证码)
@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("----请求验证码----");/*说明:验证码是一张图片,而这个图片中的内容是使用代码生成的。分析和步骤:1)创建一个可以存放图片的缓冲区BufferedImage作为画布;2)通过画布获取到针对这个画布的画笔;3)修改画布的背景颜色为白色;4)设置画布的边框,画边框的时候需要注意下,如果这里写画布的宽width和高height ,就会超出画布就会看不见,所以width和height 分别-1;5)创建一个获取随机数的对象;6)给画布上写数据;7)给画布上画干扰线;8)需要把画布中的内容响应给浏览器;ImageIO.write(bi,"JPG",response.getOutputStream());*///定义画布的宽和高int width=120;int height=30;//创建一个可以存放图片的缓冲区,作为画布//BufferedImage.TYPE_INT_RGB 表示生成图片的类型BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);//通过画布获取到针对这个画布的画笔Graphics g = bi.getGraphics();//修改画布的背景颜色  每次使用画笔的时候都得给画笔指定颜色g.setColor(Color.WHITE);//填充画布g.fillRect(0, 0, width, height);//设置画布的边框//给画笔指定颜色g.setColor(Color.RED);//给画布画边框 如果这里写width height 就会超过画布,因为边框也会占一个像素,所以这里宽和高都需要-1g.drawRect(0, 0, width-1, height-1);//创建一个获取随机数的对象Random r = new Random();//给画布上画干扰线//循环控制画多条线for(int i=1;i<=3;i++){//设置画笔的颜色g.setColor(new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255)));//向画布上画干扰线//drawLine(x1, y1, x2, y2) 这里四个参数是因为两个点画成一条线g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));}//定义数据准备向画布中写数据String data="abcdefghigklmnpqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ123456789";//创建字符串缓冲区StringBuilder sb = new StringBuilder();//循环控制画四个字符for (int i = 1; i <=4; i++) {//设置画笔的颜色 Color.BLUE这里的颜色固定了,只能是蓝色,我们可以让颜色随机变化
//          g.setColor(Color.BLUE);g.setColor(new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255)));//设置字体  Font.ITALIC表示斜体g.setFont(new Font("宋体", Font.ITALIC, 20));//给画布上写内容 20表示从x轴的位置开始书写 25表示y轴位置开始书写
//          g.drawString("哈哈哈哈", 20, 25);/** data.charAt()表示根据函数的参数进行查找字符* data.length()表示字符串的长度* r.nextInt()表示生成随机数,但是随机数的范围在0~data字符串的长度*/String str = data.charAt(r.nextInt(data.length())) + "";g.drawString(str, 20*i, 25);//将验证码内容拼接到字符串缓冲区中sb.append(str);}//  验证码保存到session中request.getSession().setAttribute("serverCheckCode",sb.toString());//将生成的验证码图片响应给浏览器ImageIO.write(bi,"JPG",response.getOutputStream());}}
RegisterServlet实现类
@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("---开始注册---");//解决请求乱码request.setCharacterEncoding("UTF-8");//获取用户名String username = request.getParameter("username");System.out.println(username);//获取密码String password = request.getParameter("password");System.out.println(password);//创建业务层对象UserService userService = new UserService();//使用业务层对象调用方法注册User user = new User();user.setUsername(username);user.setPassword(password);boolean boo = userService.register(user);//对boo结果进行判断if (boo) {//注册成功,跳转到登录页面,不需要携带数据response.sendRedirect("/login.html");} else {//注册失败,跳转到注册失败页面或者输出一句话
//            System.out.println("注册失败");response.sendRedirect("/register.html");}}
}
LoginServlet实现类
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("登陆校验请求来了-------");System.out.println(request.getMethod());// 解码请求数据request.setCharacterEncoding("utf-8");// 获取用户输入的 用户名和密码String username = request.getParameter("username");String password = request.getParameter("password");if(username == null && password == null){response.setContentType("text/html;charset=utf-8");response.getWriter().println("<h2>请登录后再进入本网站!<h2>");}// 进行验证码校验String checkCode = request.getParameter("checkCode");  // 获取用户输入的验证码System.out.println(checkCode);String serCode = (String) request.getSession().getAttribute("serverCheckCode"); // 获取服务器随机生成的验证码System.out.println(serCode);// 判断浏览器 验证码 与 服务器生成的验证码是否 相匹配 -》true 进行 用户验证if(checkCode.equalsIgnoreCase(serCode)){// 创建用户实体类User user = new User();user.setUsername(username);user.setPassword(password);// 调用用户名密码校验服务 进行校验UserService userService = new UserService();boolean loginResult = userService.login(user);String resultStr = loginResult ? "用户登陆成功!" : "用户登陆失败!";request.setAttribute("message", resultStr);// 结果为true 用户存在 判断cookie 进入网站首页// 否则 用户不存在 进入注册页面if(loginResult){// 判断用户是否记住cookieString check = request.getParameter("checkbox");System.out.println(check);if("on".equals(check)){Cookie cookieUserName = new Cookie("username", username);Cookie cookiePassword = new Cookie("password", password);response.addCookie(cookieUserName);response.addCookie(cookiePassword);}/*request.getRequestDispatcher("/success.html").forward(request,response);*/response.sendRedirect("/success.html");}else {/* request.getRequestDispatcher("/error.html").forward(request,response);*/System.out.println(request.getAttribute("message"));request.getRequestDispatcher("/loginErrorServlet").forward(request,response);}}else {request.getRequestDispatcher("/login.html").forward(request,response);}}
}
LogoutServlet实现类
@WebServlet("/LogoutServlet")
public class LogoutServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("销毁session对象。。。。");HttpSession session = request.getSession();Cookie cookieUsername = new Cookie("username", "");Cookie cookiePwd = new Cookie("password", "");//2.设置cookie的存活时间是0cookieUsername.setMaxAge(0);cookiePwd.setMaxAge(0);//3.设置cookie的有效路径和原来的有效路径一致cookieUsername.setPath("/");cookiePwd.setPath("/");//4.响应给浏览器response.addCookie(cookieUsername);response.addCookie(cookiePwd);// 销毁sessionString username = request.getParameter("username");session.invalidate();System.out.println(username+"用户退出。。。。");response.sendRedirect("/index.jsp");}
}
DownloadImageServlet实现类

@WebServlet("/downloadImageServlet")
public class DownloadImageServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {/** String getRealPath(String path)* 返回资源文件在服务器文件系统上的真实路径(文件的绝对路径)* getMimeType(fileName)获取服务器中文件类型*ServletContext servletContext = getServletContext();System.out.println(servletContext);String mimeType = servletContext.getMimeType("壁纸.jpg");System.out.println(mimeType); // image/jpegString realPath = servletContext.getRealPath("WEB-INF/壁纸.jpg");*/System.out.println("---------开始接收客户端【下载文件】--------------");// 1. 获取客户端下载的文件名String filename = request.getParameter("filename");System.out.println("filename:"+filename);// 2. 获取servletContext上文对象ServletContext servletContext = getServletContext();// 3. 获取文件的真实路径String realPath = servletContext.getRealPath("WEB-INF/"+filename);System.out.println("realPath:"+realPath);// 4. 创建下载文件的File对象File file = new File(realPath);System.out.println("文件对象:"+file);// 5. 判断文件是否存在if(file.exists()){// 6. 存在,开始下载  把项目文件写入到浏览器通道 获取2个头 + 2 个流 【核心】// 2个响应头 信息// 获取 响应的 【文件类型】String mimeType = servletContext.getMimeType(filename);System.out.println("文件传输类型mimeType:"+mimeType); // image/jpeg// 设置 响应的【浏览器文件类型】response.setContentType(mimeType);// 设置 浏览器以 【附件形式进行下载】, 如果文件名包含中文字符,首先进行编码String encodeFilename = URLEncoder.encode(filename, "UTF-8");response.setHeader("Content-Disposition","attachment;filename="+encodeFilename);// 2个流【本地输入流】 【响应输出流】// 创建字节输入流对象 -> 关联服务器文件 读取文件FileInputStream fis = new FileInputStream(file);// 获取响应对象的 输出流,向浏览器写入ServletOutputStream os = response.getOutputStream();// 7. 读取并写入文件数据 -》 给浏览器做出响应byte[] buf = new byte[1024];int len = 0;while ((len=fis.read(buf))!= -1){os.write(buf, 0, len);}// 8. 释放资源fis.close();os.close();System.out.println("传送资源结束");}else {System.out.println(filename+"不存在");}}
}
QueryBooksServlet实现类
@WebServlet("/queryBooksServlet")
public class QueryBooksServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {BookService bookService = new BookService();List<Book> books = bookService.queryAllBooks();request.setAttribute("bookList", books);request.getRequestDispatcher("/books.jsp").forward(request,response);}
}

下面两个请求处理可自行设计呀!

DownloadBookServlet
@WebServlet("/downloadBookServlet")
public class DownloadBookServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
DownloadMovieServlet
@WebServlet("/downloadMovieServlet")
public class DownloadMovieServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}

读到此处的小哥哥小姐姐们留个赞吧!加油
ღ( ´・ᴗ・` )比心

用Java手写一个微型下载资源网站相关推荐

  1. Java 手写一个SQL分页

    Java手写一个类似PageHelper的分页SQL 目前分页插件众所周知的莫过于和mybatis完美融合的PageHelper了,简单两行代码就实现了sql分页,配合PageInfo类,将数据总数量 ...

  2. java手写一个分页的方法_java web手写实现分页功能

    现在很多流行的框架,都可以很快的把分页效果做出来,但是作为一名程序员你必须得知道手写分页的流程: 场景效果: 一.分页的思路 首先我们得知道写分页代码的思路,保持思路清晰,才能行云流水的去写代码,其实 ...

  3. 用 Java 手写一个植物大战僵尸简易版!

    点击上方"终端研发部",选择"星标" 回复"资源",领取全网最火的Java核心知识总结~ 公众号后台回复"学习",获取作 ...

  4. 使用 JAVA 手写一个录屏GUI程序

    使用JAVAFX模块写的GUI程序,供学习使用. 先上一下动态效果图展示,下面分别是主界面和菜单界面,实现的功能有转GIF(需要用到ffmpeg),压缩视频,定时录屏等. 代码部分 public fi ...

  5. Java 手写一个简单计算器(1)

    用java的awt和swing实现了界面, 结构比较简单,用GridLayout布局实现 文本框+3行按钮+3行按钮: 按钮用字符串数组和for循环 后两个用JPanel存放 然后加到框架中即可 由于 ...

  6. 手写一个栈 java,数据结构|用java自己手写实现一个栈

    javaDEMO 本网站记录了最全的各种JavaDEMO ,保证下载,复制就是可用的,包括基础的, 集合的, spring的, Mybatis的等等各种,助力你从菜鸟到大牛,记得收藏哦~~ https ...

  7. 第二季:5公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解?请手写一个自旋锁【Java面试题】

    第二季:5值传递和引用传递[Java面试题] 前言 推荐 值传递 说明 题目 24 TransferValue醒脑小练习 第二季:5公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解?请手写一个自 ...

  8. 【干货】JDK动态代理的实现原理以及如何手写一个JDK动态代理

    动态代理 代理模式是设计模式中非常重要的一种类型,而设计模式又是编程中非常重要的知识点,特别是在业务系统的重构中,更是有举足轻重的地位.代理模式从类型上来说,可以分为静态代理和动态代理两种类型. 在解 ...

  9. 肝一波 ~ 手写一个简易版的Mybatis,带你深入领略它的魅力!

    零.准备工作 <dependencies><dependency><groupId>mysql</groupId><artifactId>m ...

最新文章

  1. SpringBoot系列二:搭建自己的第一个SpringBoot程序
  2. spring boot 传递 List参数
  3. 结构体对齐,#pragma pack
  4. 达索系统“体验时代中的制造业”大型活动探索工业数字化转型
  5. aspose.cells html excel导出,C#使用Aspose.Cells导出Excel简单实现
  6. java更改背景_java – 使用jquery更改menue的背景颜色
  7. cas引出的ABA问题?如何解决?- 理解原子引用、时间戳(版本号)原子引用
  8. hashmap为什么是2的倍数_HashMap源码解析(jdk1.8)
  9. python try 打印错误_python try语句如何打印错误行(含execfile)-- 转
  10. 热门城市地铁svg矢量图
  11. div 设置a4大小_如何在A4纸张尺寸页面中制作HTML页面?
  12. 如何培养卓越的执行力
  13. macbook air 安装win7双系统
  14. Python-实验4
  15. 思维方式-《终身成长》书中的精髓:决定人与人之间巨大差距的,是你的思维模式。
  16. Base64与Gzip编解码插件
  17. 深入理解CAS算法原理
  18. 手机蓝牙连接小票机/打印机,输入PIN码后确定键不亮的解决办法
  19. 微信小程序实战练习(仿五洲到家微信版)
  20. 美团CEO王兴的互联网思维

热门文章

  1. 联想在bios中怎么设置U盘启动
  2. 病态矩阵-ill condition
  3. 88页(5万字)XXX县30MWp光伏发电项目可行性报告
  4. mysql5.625_小米A1现身跑分数据库:骁龙625 运行Android原生系统
  5. iOS 用UIPanGestureRecognizer实现单手指点击拖动缩放
  6. 十二星座的美丽传说——星座查询api接口
  7. 开关电源之电感设计 (转)http://www.cnblogs.com/gmh915/archive/2009/09/30/1576988.html
  8. ALOS PRISM传感器数据文件的说明
  9. 常用端口号与对应的服务以及端口关闭
  10. Git分布式版本控制系统