一、作业目的
1.掌握软件开发的基本流程
2.掌握常用的软件开发方式和工具。
二、作业内容
设计一个包含登录界面的计算器软件,该软件可以实现第一次作业中的全部功能,同时使用数据库可以保存用户的历史计算记录和时间。
三、实现的功能
1.计算器的实现
2.登录功能的实现
3.进行加减乘除运算并用数据库对这些数据进行保存
在对数据库的操作上用mybatis取代了传统的jdbc链接数据库和sql语句的操作.
四、流程图

五、功能界面展示
用户登录页面

计算器页面


数据库页面


六、代码部分
SaveResultServlet类
package com.lzufe.controller;
import com.lzufe.entity.vo.MessageModel;
import com.lzufe.service.UserService;
import com.lzufe.entity.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "SaveResultServlet", urlPatterns = {"/save"})
public class SaveResultServlet extends HttpServlet {
private UserService userService = new UserService();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 处理GET请求的逻辑,或者留空
System.out.println("Received GET request to /SaveResultServlet");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
// 获取计算结果参数
String calculatorExpression = request.getParameter("result");
// session 用于存储已登录的用户信息
User loggedInUser = (User) request.getSession().getAttribute("user");
// 检查 calculatorExpression 是否为 null
if (calculatorExpression != null) {
try {
// 调用 UserService 的方法保存计算结果
MessageModel saveResultModel = userService.saveCalculatorResult(loggedInUser.getUserName(), calculatorExpression);
// ...
} catch (Exception e) {
e.printStackTrace();
// 处理其他异常
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write("{\"error\": \"Internal Server Error\"}");
}
} else {
// 如果 calculatorExpression 为 null,可以返回一个错误响应
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.getWriter().write("{\"error\": \"calculatorExpression is null\"}");
}
} catch (Exception e) {
e.printStackTrace(); // 将异常信息打印到控制台
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write("{\"error\": \"Internal Server Error\"}");
}
}
}
UserServlet类
package com.lzufe.controller; import com.lzufe.entity.vo.MessageModel; import com.lzufe.service.UserService; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/login") public class UserServlet extends HttpServlet { //实例化UserService对象 private UserService userService = new UserService(); /** * 用户登录 * @param request * @param response * @throws ServletException * @throws IOException */ @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.接受客户端的请求(接受参数,姓名,密码) String uname = request.getParameter("uname"); String upwd = request.getParameter("upwd"); //2.调用service层的方法,返回消息模型对象 MessageModel messageModel = userService.userLogin(uname,upwd); //3.判断消息模型的状态码 if(messageModel.getCode()==1) { //成功 request.getSession().setAttribute("user",messageModel.getObject()); response.sendRedirect("index.jsp"); } else{ //失败 //将消息模型对象设置到request作用域中,请求转发跳转到login.jsp request.setAttribute("messageModel",messageModel); request.getRequestDispatcher("login.jsp").forward(request,response); } } }
MessageModel类
package com.lzufe.entity.vo; /** * 消息模型对象(数据响应) * 状态码 * 1=成功 2=失败 * 提示信息 * 字符串 * 回显数据 * object对象 */ public class MessageModel { private Integer code = 1;//状态码,1=成功 2=失败 private String msg;//提示信息 private Object object;//回显对象(基本数据类型,字符串类型,list,map等) private boolean operationSuccess; // 新增属性,表示数据库操作是否成功 public boolean isOperationSuccess() { return operationSuccess; } public void setOperationSuccess(boolean operationSuccess) { this.operationSuccess = operationSuccess; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public Object getObject() { return object; } public void setObject(Object object) { this.object = object; } }
CalculatorResult类
package com.lzufe.entity; public class CalculatorResult { String uname; String result;// 新增用户名字段 public CalculatorResult(String uname, String result) { this.result = result; this.uname = uname; } public String getResult() { return result; } public void setResult(String result) { this.result = result; } public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } }
User类
package com.lzufe.entity; /** * User实体类 */ public class User { private String userName;//用户姓名 private String pwd;//用户密码 public User( String userName, String pwd) { this.userName = userName; this.pwd = pwd; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } }
CalculatorResultMapper接口类
package com.lzufe.mapper; import com.lzufe.entity.CalculatorResult; public interface CalculatorResultMapper { void saveResult(CalculatorResult result); }
CalculatorResultMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lzufe.mapper.CalculatorResultMapper">
<insert id="saveResult" parameterType="com.lzufe.entity.CalculatorResult">
INSERT INTO calculator_results (result, uname) VALUES (#{result}, #{uname})
</insert>
</mapper>
UserMapper接口类
package com.lzufe.mapper; import com.lzufe.entity.User; /** * 用户接口类 */ public interface UserMapper { public User queryUserByName(String username); public void addUser(User user); }
UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lzufe.mapper.UserMapper">
<select id="queryUserByName" parameterType="String" resultType="com.lzufe.entity.User">
select * from tb_user where username = #{username}
</select>
</mapper>
CalculatorService类
package com.lzufe.service; import com.lzufe.entity.CalculatorResult; import com.lzufe.entity.vo.MessageModel; import com.lzufe.mapper.CalculatorResultMapper; import com.lzufe.util.GetSqlSession; import com.lzufe.util.StringUtil; import org.apache.ibatis.session.SqlSession; public class CalculatorService { /** * 保存计算结果 * * @param uname 用户名 * @param result 计算结果 * @return */ public MessageModel saveCalculatorResult(String uname, String result) { MessageModel messageModel = new MessageModel(); // 参数的非空判断 if (StringUtil.isEmpty(uname) || result == null) { messageModel.setCode(0); messageModel.setMsg("用户名和计算结果不能为空"); return messageModel; } // 创建 CalculatorResult 对象 CalculatorResult calculatorResult = new CalculatorResult(uname,result); calculatorResult.setUname(uname); calculatorResult.setResult(result); // 保存计算结果到数据库 try (SqlSession session = GetSqlSession.createSqlSession()) { CalculatorResultMapper resultMapper = session.getMapper(CalculatorResultMapper.class); resultMapper.saveResult(calculatorResult); session.commit(); messageModel.setOperationSuccess(true); messageModel.setObject(calculatorResult); } catch (Exception e) { e.printStackTrace(); messageModel.setCode(0); messageModel.setMsg("保存计算结果时发生错误"); messageModel.setOperationSuccess(false); // 记录日志 // Logger.getLogger(CalculatorService.class.getName()).log(Level.SEVERE, null, e); } return messageModel; } }
UserService类
package com.lzufe.service; import com.lzufe.entity.User; import com.lzufe.entity.vo.MessageModel; import com.lzufe.mapper.UserMapper; import com.lzufe.util.GetSqlSession; import com.lzufe.util.StringUtil; import org.apache.ibatis.session.SqlSession; /** * 业务逻辑 */ public class UserService { /** * 用户登录 * @param uname * @param upwd * @return */ public MessageModel userLogin(String uname, String upwd) { MessageModel messageModel = new MessageModel(); //回显数据 // User u = new User(); // u.setUserName(uname); // u.setPwd(upwd); // messageModel.setObject(u); //1.参数的非空判断 if (StringUtil.isEmpty(uname) ||StringUtil.isEmpty(upwd)) { messageModel.setCode(0); messageModel.setMsg("用户姓名和密码不能为空"); return messageModel; } //2.调用dao层的查询方法,通过用户名查询用户对象 SqlSession session = GetSqlSession.createSqlSession(); UserMapper userMapper = session.getMapper(UserMapper.class); User user = userMapper.queryUserByName(uname); //3.判断用户对象是否为空 if(user ==null) { messageModel.setCode(0); messageModel.setMsg("用户不存在"); return messageModel; } //4.比较密码 if (!upwd.equals(user.getPwd())) { System.out.println(user.getPwd()); messageModel.setCode(0); messageModel.setMsg("用户密码不正确"); return messageModel; } //5.登录成功,将用户信息设置到消息模型中 messageModel.setObject(user); return messageModel; } private CalculatorService calculatorService = new CalculatorService(); public MessageModel saveCalculatorResult(String uname, String result) { return calculatorService.saveCalculatorResult(uname, result); } }
GetSqlSession类(工具类)
package com.lzufe.util; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.apache.ibatis.io.Resources; import java.io.IOException; import java.io.InputStream; public class GetSqlSession { public static SqlSession createSqlSession() { SqlSessionFactory sqlSessionFactory =null; InputStream input = null; SqlSession session = null; try { //获得mybatis的环境配置文件 String resource = "mybatis-config.xml"; //以流的方式获取resource(mybatis的环境配置文件) input = Resources.getResourceAsStream(resource); //创建会话工厂 sqlSessionFactory = new SqlSessionFactoryBuilder().build(input); //通过工厂得到SqlSession session = sqlSessionFactory.openSession(); return session; }catch (IOException e) { e.printStackTrace(); return null; } } public static void main(String[] args) { System.out.println(createSqlSession()); } }
StringUtil(工具类)
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户登录</title>
<style>
body {
font-family: 'Arial', sans-serif;
background-color: #f4f4f4;
text-align: center;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
form {
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
input {
width: 100%;
padding: 10px;
margin-bottom: 10px;
box-sizing: border-box;
}
#msg {
font-size: 14px;
color: red;
margin-bottom: 10px;
display: block;
}
button {
background-color: #4caf50;
color: #fff;
border: none;
padding: 10px 20px;
cursor: pointer;
border-radius: 4px;
font-size: 16px;
}
button:hover {
background-color: #45a049;
}
button + button {
margin-left: 10px;
}
</style>
</head>
<body>
<form action="login" method="post" id="loginForm">
<h2>用户登录</h2>
<label for="uname">姓名:</label>
<input type="text" name="uname" id="uname" value="${messageModel.object.userName}"><br>
<label for="upwd">密码:</label>
<input type="password" name="upwd" id="upwd" value="${messageModel.object.pwd}"><br>
<span id="msg">${messageModel.msg}</span><br>
<button type="button" id="loginBtn">登录</button>
<button type="button" id="regiterBtn" >注册</button>
</form>
<%-- 引入 jQuery 的 js 文件 --%>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
$("#loginBtn").click(function () {
// 获取用户姓名和密码
var uname = $("#uname").val();
var upwd = $("#upwd").val();
if (isEmpty(uname)) {
$("#msg").html("用户姓名不可为空");
return;
}
if (isEmpty(upwd)) {
$("#msg").html("用户密码不可为空");
return;
}
$("#loginForm").submit();
});
/**
* 判断字符串是否为空,
* 如果为空,返回 true,否则返回 false
* @param str
* @returns {boolean}
*/
function isEmpty(str) {
return str == null || str.trim() === "";
}
</script>
</body>
</html>
index.jsp(计算器)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>简单计算器</title>
<style>
html, body {
height: 100%;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
}
.calculator {
width: 400px;
border: 2px solid #3498db;
text-align: center;
background-color: #ecf0f1;
border-radius: 10px;
}
.result {
height: 100px;
background: #e74c3c;
line-height: 100px;
font-size: 48px;
color: white;
text-align: right;
font-weight: bold;
}
.buttons {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 5px;
justify-content: flex-end; /* 将按钮容器右对齐 */
}
button {
height: 80px;
font-size: 36px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.operators {
color: #3498db;
font-weight: bold;
}
.equal {
background-color: #2ecc71;
color: white;
font-weight: bold;
}
.Dot {
font-size: 24px;
color: #3498db;
font-weight: bold;
}
.number {
font-size: 20px;
}
</style>
<head>
<body>
<div class="calculator">
<div class="result">0</div>
<div class="buttons">
<button class="AC">AC</button>
<button>+/-</button>
<button>%</button>
<button class="operators">/</button>
<button class="number">7</button>
<button class="number">8</button>
<button class="number">9</button>
<button class="operators">*</button>
<button class="number">4</button>
<button class="number">5</button>
<button class="number">6</button>
<button class="operators">-</button>
<button class="number">1</button>
<button class="number">2</button>
<button class="number">3</button>
<button class="operators">+</button>
<button class="number" style="flex: 2;">0</button>
<button class="Dot">.</button>
<button class="equal" style="width: 100%;" id="equalBtn">=</button>
</div>
</div>
<script>
// 选择所有数字和运算符按钮
let numbers = document.querySelectorAll('.number');
let operators = document.querySelectorAll('.operators');
let result = document.querySelector('.result');
let AC = document.querySelector('.AC');
let Dot = document.querySelector('.Dot');
let equal = document.querySelector('.equal');
let isDot = true;
let displays = "";
// 遍历数字按钮并添加点击事件处理程序
numbers.forEach(function (number) {
number.onclick = function () {
displays += this.innerHTML;
result.innerHTML = displays;
};
});
// 遍历运算符按钮并添加点击事件处理程序
operators.forEach(function (operator) {
operator.onclick = function () {
displays += this.innerHTML;
result.innerHTML = displays;
isDot = true;
};
});
// AC 按钮点击事件处理程序
AC.onclick = function () {
displays = "";
result.innerHTML = '0';
};
// 小数点按钮点击事件处理程序
Dot.onclick = function () {
if (displays == "") {
displays += '0.';
} else if (isDot) {
displays += '.';
isDot = false;
}
result.innerHTML = displays;
};
equal.onclick = function () {
// 发送AJAX请求
let xhr = new XMLHttpRequest();
xhr.open("POST", "/lp/save", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// 将计算结果作为参数发送
xhr.send("result=" + encodeURIComponent(displays));
// 处理服务器响应
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log("Success:", xhr.responseText);
} else {
console.error("Error:", xhr.status, xhr.statusText, xhr.responseText);
}
}
};
// 更新显示结果
displays = eval(displays);
result.innerHTML = displays;
};
</script>
</script>
</body>
链接数据库时所用到的配置和数据库的设置
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="mysql.properties"/> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <package name="com.lzufe.mapper"/> </mappers> </configuration>
mysql.properties
driver= com.mysql.cj.jdbc.Driver url = jdbc:mysql://127.0.0.1:3306/java_test?serverTimezone=UTC&useSSL=false&characterEncoding=UTF-8 username = root password = 123456