基于html+servlet实现的小型彩票选号系统的二次开发
一、系统的主要功能和特点
1.用html+servlet+css实现的登录页面
2.用servlet实现输入彩票数字,随机生成随机数进行对应
3.Jsp+html公布获奖情况
二次开发:添加了注册功能,利用txt储存用户信息
添加了显示中奖号码功能
原代码:
LoginServlet.java
`
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet("/LoginServlet ")
public class LoginServlet extends HttpServlet {
// static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
// static final String DB_URL = "jdbc:mysql://localhost:3306/java_final_user?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai";
// static final String USER = "root";
// static final String PASS = "lhxl1010";
private static final long serialVersionUID = 1L;
public LoginServlet() {
super();
// TODO Auto-generated constructor stub
}
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
}
public void destroy() {
// TODO Auto-generated method stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
//以下解决中文输出乱码问题
response.setContentType("text/html; charset=utf-8");
//让浏览器用utf-8来解析返回的数据
request.setCharacterEncoding("UTF-8");
//告诉servlet用UTF-8转码,而不是用默认的ISO8859
String username =request.getParameter("html_username");
String password =request.getParameter("html_password");
PrintWriter out=response.getWriter();
String filename = "F:\\user_data.txt"; //增加的代码
boolean isMatch = false; // 用于检测用户名和密码是否匹配
try {
// 将用户名和密码写入文件
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.contains("username:") && line.contains("password:")) {
String[] parts = line.split(":");
String storedUsername = parts[1].trim();
String storedPassword = parts[3].trim();
if (username.equals(storedUsername) && password.equals(storedPassword)) {
isMatch = true; // 如果匹配到已存在的用户名和密码,设置isNew为false
break; // 退出循环,不再继续检查其他行
} }
}
}
if (isMatch) { // 如果用户名和密码匹配,输出成功消息并重定向到login.html页面
out.print("<script language='javascript'>alert('登录成功');window.location.href='menu.html';</script>");
}
else { // 如果用户名已存在,输出失败消息
out.print("<script language='javascript'>alert('登录失败,用户名或密码错误');window.location.href='login.html';</script>");
}
}
catch (IOException e) {
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// doPost和doPost执行相同,他们不具有关联性。仅表明提交信息不敏感谁都可以处理
this.doGet(request, response);
}
}judge.java
package servletpackage;
import java.util.*;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
-
Servlet implementation class judge
*/
@WebServlet(asyncSupported = true, urlPatterns = { "/judge" })
public class judge extends HttpServlet {
private static final long serialVersionUID = 1L;/**
- @see HttpServlet#HttpServlet()
*/
public judge() {
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
doPost(request,response);
}
/**
-
@see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.setContentType("text/html;charset=utf-8");
Setcp = new TreeSet ();
PrintWriter out = response.getWriter();
try {
//产生随机数
Random rand = new Random();
while(cp.size()<7)
{
cp.add(rand.nextInt(30)+1);//生成[1,31)区间的随机整数
}
//接收表单数据(要类型转换)
String num1 = (String)request.getParameter("num1");
String num2 = (String)request.getParameter("num2");
String num3 = (String)request.getParameter("num3");
String num4 = (String)request.getParameter("num4");
String num5 = (String)request.getParameter("num5");
String num6 = (String)request.getParameter("num6");
String num7 = (String)request.getParameter("num7");
//数据处理
//表单填写不完整(输入不合法)
if(num1""||num2""||num3""||num4""||num5""||num6""||num7"") {
out.println("请将表格填写完整");
}
else {
TreeSeths = new TreeSet 7){();
hs.add(num1);hs.add(num2);hs.add(num3);hs.add(num4);hs.add(num5);hs.add(num6);hs.add(num7);
if(hs.size()<7)//输入的数据有相同的(输入不合法)
{
out.println("请输入七个不同的数!");
}
else//输入合法
{
//把String转回int
Integer inum1= Integer.parseInt(num1);
Integer inum2= Integer.parseInt(num2);
Integer inum3= Integer.parseInt(num3);
Integer inum4= Integer.parseInt(num4);
Integer inum5= Integer.parseInt(num5);
Integer inum6= Integer.parseInt(num6);
Integer inum7= Integer.parseInt(num7);
Integer[] cn = new Integer[7];
cn[0]=inum1;cn[1]=inum2;cn[2]=inum3;cn[3]=inum4;cn[4]=inum5;cn[5]=inum6;cn[6]=inum7;
//统计匹配(中奖)个数
int count = 0;
for(int i=0;i<7;i++){
if(cp.contains(cn[i]))
count++;
}
//输出处理
out.println("中奖号码是:");
out.print(cp.toString()+"
");//增加的代码
if(count
out.print("恭喜你中了一等奖
");
}
else if(count6){
request.setAttribute("cp", cp);
request.getRequestDispatcher("second.jsp").forward(request, response);
}
else if(count5){
request.setAttribute("cp", cp);
request.getRequestDispatcher("third.jsp").forward(request, response);} else{ request.setAttribute("cp", cp); request.getRequestDispatcher("none.jsp").forward(request, response); } } }
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
- @see HttpServlet#HttpServlet()
}
first.jsp
<%@ page language="java" contentType="text/html; UTF-8"
pageEncoding="UTF-8"%>
超级幸运一等奖!
中奖号码是: <%= request.getAttribute("cp") %> //增加的代码三等奖!
中奖号码是: <%= request.getAttribute("cp") %>//增加的代码三等奖!
中奖号码是: <%= request.getAttribute("cp") %>号码未中奖!
中奖号码是: <%= request.getAttribute("cp") %></body>
`
login.html
`
none.html
未中奖!
中奖号码为:${requestScope.cn}
<h1>请输入你决定的数字!</h1>
<form action="judge" name="init"method="post"><br>
<table>
<tr>
<td>第一个数: <input type="text" name="num1"/><br><br>
</tr>
<tr>
<td>第二个数: <input type="text" name="num2"/><br><br>
</tr>
<tr>
<td>第三个数: <input type="text" name="num3"/><br><br>
</tr>
<tr>
<td>第四个数: <input type="text" name="num4"/><br><br>
</tr>
<tr>
<td>第五个数: <input type="text" name="num5"/><br><br>
</tr>
<tr>
<td>第六个数: <input type="text" name="num6"/><br><br>
</tr>
<tr>
<td>第七个数: <input type="text" name="num7"/><br><br>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" name="submit" value="提交"/><br>
</tr>
</table>
</form>
</div>
</div>
</body>
`
login.css
`@charset "UTF-8";
/* 将所有HTML元素的边距、填充和边框设置为0,以清除默认样式 */
- {
margin: 0;
padding: 0;
border: 0;
}
/* 设置body和html元素的宽度和高度为100%,使它们填充整个视口 */
body,html{
width: 100%;
height: 100%;
}
/* 设置body元素的文本对齐方式为居中,并设置背景图像 /
body{
text-align: center; / 文本居中 /
background-image: url(css.jpg); / 设置背景图像 /
background-repeat: no-repeat; / 背景图像不重复 /
background-position: center top; / 背景图像居中并位于顶部 */
}
/* 定义登录框的样式 */
loginDiv {
width: 30%; /* 宽度为视口的30% /
height: 300px; / 高度为300像素 /
align-items: center; / 垂直居中内容 /
justify-content: center; / 水平居中内容 /
position: absolute; / 绝对定位 /
top: 32%; / 距离顶部的位置为视口的32% /
left: 37%; / 距离左边的位置为视口的37% /
background-color: rgba(75, 81, 95, 0.5); / 半透明的深灰色背景 /
box-shadow: rgba(52, 56, 66, 0.5); / 半透明的深色阴影 /
border-radius: 5px; / 圆角 */
}
/* 设置登录消息的样式 */
loginMsg {
text-align: center; /* 文本居中 /
margin: 15px auto; / 上下外边距为15像素,左右自动 /
font-size: 40px; / 字体大小为40像素 /
color: #fff; / 文本颜色为白色 /
padding-bottom: 10px; / 下边距为10像素 /
text-shadow: 4px 1px 1px #000; / 文本阴影效果 */
}
/* 设置标签的样式 /
label {
margin-top: 30px; / 上外边距为30像素 /
margin-left: 20%; / 左外边距为20% /
color: azure; / 文本颜色为浅蓝色 */
}
/* 设置span元素的样式 /
span {
font-size: large; / 字体大小为大号字体 /
display: inline-block; / 作为行内块元素显示 /
min-width: 80px; / 最小的宽度为80像素 */
}
/* 设置输入框的样式 /
input {
height: 30px; / 高度为30像素 /
width: 140px; / 宽度为140像素 /
border-radius: 5px; / 圆角 /
border-style: hidden; / 无边框样式 /
outline: none; / 无轮廓线 /
color: #f0edf3; / 文本颜色为浅黄色 /
background-color: rgba(216, 191, 216, 0.5); / 半透明的浅灰色背景 */
}
/* 设置标签内的输入框样式 /
label>input {
width: 250px; / 宽度为250像素 /
font-size: 16px; / 字体大小为16像素 /
margin: 10px auto; / 上外边距和下外边距为10像素,左右自动 /
padding-left: 15px; / 左内边距为15像素 */
}
/* 设置提交按钮的样式 */
subDiv {
text-align: center; /* 文本居中 /
margin: 10px auto; / 上外边距和下外边距为10像素,左右自动 /
line-height: 40px; / 行高为40像素 */
}
subDiv>input { /* 设置提交按钮的样式 */
text-align: center; /* 文本居中 /
margin: 10px auto; / 上外边距和下外边距为10像素,左右自动 /
line-height: 40px; / 行高为40像素 */
}
subDiv>input { /* 设置提交按钮的样式 */
font-size: large; /* 字体大小为大号字体 /
color: rgb(223, 223, 223); / 文本颜色为浅灰色 /
font-family: "黑体", serif; / 字体为黑体,如果不可用则使用默认的衬线字体 /
margin: 5px 10px; / 上下外边距为5像素,左右外边距为10像素 /
}
/ 设置链接的样式 */
subDiv>a {
/* text-decoration: none; / / 去掉默认的下划线 /
margin-top: 10px; / 上外边距为10像素 /
font-size: 18px; / 字体大小为18像素 /
font-family: "楷体", serif; / 字体为楷体,如果不可用则使用默认的衬线字体 /
color: rgba(223, 223, 223, 0.7); / 文本颜色为半透明的浅灰色 /
}
/ 设置表格的样式 /
table {
text-align: center; / 文本居中 /
margin: 10px auto; / 上外边距和下外边距为10像素,左右自动 /
line-height: 40px; / 行高为40像素 */
}其他的css代码类似不再贴出 增加的模块: register.html
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
/**
-
Servlet implementation class RegisterServlet
*/
public class RegisterServlet extends HttpServlet {
private static final long serialVersionUID = 1L;/**
- @see HttpServlet#HttpServlet()
*/
public RegisterServlet() {
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
response.getWriter().append("Served at: ").append(request.getContextPath());
response.setContentType("text/html");
PrintWriter out = response.getWriter();String username = request.getParameter("html_username");
String password = request.getParameter("html_password");
String filename = "F:\user_data.txt";
boolean isNew = true; // 用于检测用户名和密码是否匹配
try {
// 将用户名和密码写入文件(可选)
FileWriter writer = new FileWriter(filename, true); // 第二个参数true表示追加模式 在追加模式下,如果你想向一个已存在的文件写入内容,新的内容会被添加到文件的末尾,而不是覆盖文件中的现有内容。这与覆盖模式相反,在覆盖模式下,任何现有内容都会被新内容所替换。List<String> lines = new ArrayList<>(); try (BufferedReader reader = new BufferedReader(new FileReader(filename))) { String line; while ((line = reader.readLine()) != null) { if (line.contains("username:") && line.contains("password:")) { String[] parts = line.split(":"); String storedUsername = parts[1].trim(); String storedPassword = parts[3].trim(); if (username.equals(storedUsername) && password.equals(storedPassword)) { isNew = false; // 如果匹配到已存在的用户名和密码,设置isNew为false break; // 退出循环,不再继续检查其他行 } } } } // 默认认为用户名为新用户
- @see HttpServlet#HttpServlet()
// for (String line : lines) {
//
// }
if (isNew) { // 如果用户名为新用户,输出成功消息并重定向到login.html页面
writer.write("username: " + username + ":");
writer.write("password: " + password + ":\n");
writer.close();
out.print("<script language='javascript'>alert('注册成功,请登录');window.location.href='login.html';</script>");
// 如果成功,重定向到 login.html 页面
}
else { // 如果用户名已存在,输出失败消息
out.print("<script language='javascript'>alert('注册失败,用户名已存在');window.location.href='register.html';</script>");
}
}
catch (IOException e) {
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);
}
}
`
二、类的设计
三、程序流程
先运行login.html,进入登录界面,如果没有账号,则进行注册,跳转至register.html;如果有账号,则直接进行登录。注册时会匹配输入的用户名和已有用户名是否匹配,若匹配,则用户名已存在,注册失败。若没有相同的用户名,则注册成功,返回登录界面进行登录。
登录成功后进入小型彩票选号界面,输入七个不同的数字。提交后会显示是否获奖以及获奖号码。
四、程序纠错过程
1.配置数据库
一开始显示Install/Remove of the Service Denied,重新用管理员权限打开c命令提示符即可
显示mysql无法启动
按照网络上教程进行重新安装
但还是无法启动。
卸载后参考bilibili视频重新下载了安装包其他版本进行配置,配置成功
也能够进行数据增添
然而当时的我高兴得还是太早了。。。
成功配置sql环境只是第一步,更困难的还在后面——在eclipse里连接数据库
导入jar包暂且不提,编写了数据库测试代码,一开始无法连接,后来跟同学进行讨论,运行后是能连上的,放到LoginServlet里就连不上了。。。查了各种错误版本逐个尝试(包括并不限于版本问题导致的代码差异、jar包差异、重新下载重新配置)
还是不行
这一过程大概持续了很久,实在是无法解决了,虽然很遗憾但为了最终实现一个较完整的效果,还是选择及时止损,开始尝试另一种方法,用txt实现登陆注册。
2.在txt实现过程中,本来想用 for (String line : lines) 语句进行文件读取和比较的,但是运行结果与预期结果不符,在筛查错误后发现是程序根本就没进入for循环()
Html无法显示css样式:
解决方式:在html文件同级的地方建一个css文件夹存放css文件就可以了
对css文件进行修改后运行html,界面没有更新
解决方法:浏览器缓存了网页,修改网页
无法插入背景图片:
背景图片路径不对/新建一个css文件
五、程序运行截图
七、心得
二次开发一个小型彩票选号系统不仅仅是一个技术挑战,它更是一个深度学习的过程。通过这个项目,我深入地理解了Java Web开发的整个流程,从前端到后端,再到数据库的交互,每一个环节都让我有了更深入的体会。
在开发过程中,我首先面临的是环境配置的问题。虽然现在有许多的集成开发环境(IDE)可以帮助我们快速设置好开发环境,但在实际操作中,我还是遇到了许多问题,如JDK版本不匹配、设置不正确等。这些问题虽然繁琐,但也让我更加熟悉了开发环境的搭建过程。
数据存储是一个让我头疼的环节。最困难的是数据库的连接。为了存储彩票选号的数据,我需要与数据库进行交互。这其中涉及到了SQL语句的编写、数据库连接的设置等。在这个过程中,我深刻体会到了数据库对于一个应用的重要性,它不仅仅是一个数据存储的地方,更是前后端交互的桥梁。在数据库无法连接的情况下,我考虑使用TXT文件来存储彩票选号的数据。但TXT文件对于大规模的数据存储并不合适,它无法提供快速的数据检索和更新。相比之下,数据库提供了更加丰富的数据管理和查询功能,这也是让我感到最遗憾的地方。
在开发过程中,我还遇到了一些技术上的挑战。例如如何在页面中显示Servlet生成的随机数?
尽管一个小型彩票选号系统的过程是充满挑战的。同时,我深感自己的技术还有很大的提升空间,需要不断地学习和实践。我相信,只有不断地挑战自己,才能在技术上有所突破,才能不断地成长。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升