JSP+Servlet制作简易计算器

目录
一、前言
二、前端
1. 完整jsp代码
2. 代码解读
三、后端
1. 栈的设计
2. 处理请求的Servlet
3. web.xml文件
四、完整代码下载
五、总结


 在此之前没有基础的小伙伴可以看看我以前的文章,这样可以很好的理解这节讲的内容。👇👇👇

JSON&AjaxJSON&Ajax
Servlet的入门Servlet的入门

一、前言

 在做这个计算器之前,网上看了一下制作的计算器。发现都是实现最基本的运算,也没有混合运算。页面也做得。。。不尽如人意,所以决定自己做一个(可能也不是很好,大佬勿喷~~🙏)。
 我们这里所制作的计算器,可以实现最基本的加减乘除、模运算。也可以进行混合运算,但缺点就是:只能做整数运算,对于小数运算可能会报语法错误除法运算的结果也是整数(去除小数部分)。效果如下:👇

在这里插入图片描述

📌项目结构
在这里插入图片描述

📌相关依赖的下载

📥jquery-3.6.0.min.js
📥gson-2.2.4.jar
📥servlet-api.jar

二、前端

 我们前端页面做了一些美化,使用的是Bootstrap5框架

1. 完整jsp代码

<%--
  Created by IntelliJ IDEA.
  User: Long
  Date: 2022/11/9
  Time: 20:23
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>计算器</title>
    <!-- 新 Bootstrap5 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/css/bootstrap.min.css">
    <!--  popper.min.js 用于弹窗、提示、下拉菜单 -->
    <script src="https://cdn.staticfile.org/popper.js/2.9.3/umd/popper.min.js"></script>
    <!-- 最新的 Bootstrap5 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.min.js"></script>
    <script type="text/javascript" src="./script/jquery-3.6.0.min.js"></script>
    <script type="text/javascript">
      $(function () {
        var $input = $("input[class='form-control']");
        $("button").click(
            function (e) {
              $input.val($input.val()+e.target.value);
        })
        $("#button-addon2").click(
            function () {
              $("input[class='form-control']").val("");
            }
        )
        $("#operation").click(
            function () {
              $.post(
                      "/calculator/calServlet",
                      {
                        data: $input.val().trim()
                      },
                      function (data) {
                        var regExp = new RegExp('error');
                        if (regExp.test(data)){
                          alert("语法错误");
                          $("input[class='form-control']").val("");
                        }else {
                          $("input[class='form-control']").val(data);
                        }
                      },
                      "json"
              )
            }
        )
      })
    </script>
    <style>
      button {
        width: 50px;
        height: 50px;
      }
    </style>
  </head>
  <body>
    <div class="container" style="padding: 300px 500px;">
      <div class="card" style="width: 18rem;">
        <ul class="list-group" style="text-align: center">
          <li class="list-group-item">
            <div class="input-group mb-3">
              <input type="text" class="form-control" aria-describedby="button-addon2">
              <button class="btn btn-outline-secondary" type="button" id="button-addon2">C</button>
            </div>
          </li>
          <li class="list-group-item">
            <button type="button" class="btn btn-outline-primary" value="0">0</button>
            <button type="button" class="btn btn-outline-primary" value="1">1</button>
            <button type="button" class="btn btn-outline-primary" value="2">2</button>
            <button type="button" class="btn btn-outline-primary" value="3">3</button>
          </li>
          <li class="list-group-item">
            <button type="button" class="btn btn-outline-primary" value="4">4</button>
            <button type="button" class="btn btn-outline-primary" value="5">5</button>
            <button type="button" class="btn btn-outline-primary" value="6">6</button>
            <button type="button" class="btn btn-outline-primary" value="7">7</button>
          </li>
          <li class="list-group-item">
            <button type="button" class="btn btn-outline-primary" value="8">8</button>
            <button type="button" class="btn btn-outline-primary" value="9">9</button>
            <button type="button" class="btn btn-outline-primary" value="+">+</button>
            <button type="button" class="btn btn-outline-primary" value="-">-</button>
          </li>
          <li class="list-group-item">
            <button type="button" class="btn btn-outline-primary" value="*">*</button>
            <button type="button" class="btn btn-outline-primary" value="/">/</button>
            <button type="button" class="btn btn-outline-primary" value="%">%</button>
            <input style="height: 50px;width: 50px" type="button" class="btn btn-outline-primary" value="=" id="operation"/>
          </li>
        </ul>
      </div>
    </div>
  </body>
</html>

2. 代码解读

📌输入框获取按钮值

$("button").click(
  function (e) {
      $input.val($input.val()+e.target.value);
})

👆 当鼠标点击按钮的时候,获取该按键的值(除了=建),将其添加到输入框中去。

📌清除输入框内容

$("#button-addon2").click(
 	function () {
      $("input[class='form-control']").val("");
    }
)

👆 当鼠标点击按钮C的时候,清除输入框中内容。
如下图:👇

在这里插入图片描述
📌发送输入框内容,用于运算

$("#operation").click(
 function () {
     $.post(
           "/calculator/calServlet",
            {
              data: $input.val().trim()
            },
            function (data) {
              var regExp = new RegExp('error');
              if (regExp.test(data)){
                alert("语法错误");
                $("input[class='form-control']").val("");
              }else {
                $("input[class='form-control']").val(data);
              }
            },
            "json"
     )
   }
)

👆 当鼠标点击按钮=的时候,发送Ajax请求。
这里我们利用回调函数,来将后端运算后的结果(json格式)显示到输入框。

三、后端

 后端我们用了栈的中缀表达式,来处理前端发送来的运算式

1. 栈的设计

package com.jl;
/**
 * @author Long
 * @date 2022/11/10
 * @CSDN https://blog.csdn.net/qq_35947021
 **/
public class ArrayStack{
	private int maxsize;
	private int top = -1;
	private int[] stack;
	public ArrayStack(int maxsize) {
		this.maxsize = maxsize;
		this.stack = new int[maxsize];
	}
	
	// 判断是栈是否为空
	public Boolean isEmpty() {
		if (top==-1) {
			return true;
		}else {
			return false;
		}
	}
	// 判断是否满栈
	public  Boolean isFull() {
		if (top==this.maxsize-1) {
			return true;
		}else{
			return false;
		}
	}
	
	// 判断优先级
	public int priority(int oper) {
		if (oper == '*' || oper == '/'||oper=='%') {
			return 1;
		}
		else if (oper == '+' || oper == '-') {
			return 0;
		}
		else {
			return -1; // 假定目前的表达式只有 +, - , * , /
		}
	}
	
	// 入栈
	
	public void push(int num) {
		if (!isFull()) {
			top++;
			stack[top] = num;
		}
	}
	// 出栈
	public int pop() {
		if (!isEmpty()) {
			int value = stack[top];
			top--;
			return value;
		}else{
			throw new RuntimeException();
		}
	}
	
	// 查看栈顶元素
	public int check()
	{
		return stack[top];
	}
	
	// 判断是否为操作符
	public Boolean isOper(char ch) {
		if (ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='%') {
			return true;
		}else{
			return false;
		}
	}

	// 计算结果
	public int cal(int num1, int num2, int oper) {
		int res = 0; // res 用于存放计算的结果
		switch (oper) {
		case '+':
			res = num1 + num2;
			break;
		case '-':
			res = num2 - num1;
			break;
		case '*':
			res = num1 * num2;
			break;
		case '/':
			if (num1==0) {
				throw new ArithmeticException();
			}else {
				res = num2 / num1;
			}	
			break;
		case '%':
			res = num2 % num1;
			break;
		default:
			break;
		}
		return res;
	}

}

2. 处理请求的Servlet

package com.jl;

/**
 * @author Long
 * @date 2022/11/10
 * @CSDN https://blog.csdn.net/qq_35947021
 **/
import com.google.gson.Gson;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CalServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response){

        try {
            execute(request, response);
        } catch (Exception e) {
            try {
                response.getWriter().write(new Gson().toJson("error"));
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
            e.printStackTrace();
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    private void execute(HttpServletRequest request, HttpServletResponse response){
        String expression = request.getParameter("data");
        ArrayStack numStack = null;
        ArrayStack operStack = null;
        numStack = new ArrayStack(5);
        operStack = new ArrayStack(5);
        int index=0; /*遍历表达式的索引*/
        int num1;
        int num2;
        char ch;	/*存放每次扫描到的字符*/
        int r;		/*接收运算之后的结果*/
        int oper;	/*接收扫描到的操作符*/
        String joint=""; /*用来拼接多位数字*/
        while (true) {
            ch = expression.charAt(index);
            if (operStack.isOper(ch)) {
                // 如果是操作符
                if (!operStack.isEmpty()) {
                    // 操作符栈不为空
                    // 判断当前操作符与栈顶操作符的优先级
                    if (operStack.priority(ch)<=operStack.priority(operStack.check())) {
                        num1 = numStack.pop();
                        num2 = numStack.pop();
                        oper = operStack.pop();
                        if (oper=='/'&&num1==0) {
                            throw new RuntimeException();
                        }else{
                            r = operStack.cal(num1, num2, oper);
                            numStack.push(r);
                            operStack.push(ch);
                        }
                    }else {
                        operStack.push(ch);
                    }
                }else{
                    // 操作符栈为空
                    operStack.push(ch);
                }
            }else {
                // 如果是数字
                joint+=ch;
                if (index==expression.length()-1) {
                    numStack.push(Integer.parseInt(joint));
                }else{
                    if (operStack.isOper(expression.charAt(index+1))) {
                        numStack.push(Integer.parseInt(joint));
                        joint="";
                    }
                }

            }

            index++;
            if (index>=expression.length()) {
                break;
            }

        }
        while(true){
            if (operStack.isEmpty()) {
                break;
            }
            num1 = numStack.pop();
            num2 = numStack.pop();
            oper = operStack.pop();
            if (oper=='/'&&num1==0) {
                throw new RuntimeException();
            }else{
                r = operStack.cal(num1, num2, oper);
                numStack.push(r);
            }
        }
        Gson gson = new Gson();
        try {
            response.getWriter().write(gson.toJson(numStack.pop()));
        } catch (IOException e) {
            throw new RuntimeException();
        }
    }
}

👆我们这里在处理请求,调用execute()的时候,采用的是中缀表达式
 当有输入语法有错误的时候,我这里采用的策略是:抛异常,在调用execute()的时候捕获异常,向前端发送error字符串(json格式的)。前端根据这个信息弹出警告弹窗
 我们的运算结果是放到栈里的:运算完之后运算结果会在栈顶,最后我们出栈就可以拿到运算结果。我们将后端的运算结果,通过response响应对象返回给前端(json格式),前端将其显示在输入框
它的基本概念小伙伴可以自行去了解。后边有时间我可能会写一篇🖊

3. web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>CalServlet</servlet-name>
        <servlet-class>com.jl.CalServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CalServlet</servlet-name>
        <url-pattern>/calServlet</url-pattern>
    </servlet-mapping>
</web-app>

四、完整代码下载

📥完整代码下载地址

五、总结

 以上就是简易计算器制作的全部内容,里边涉及到了栈·的中缀表达式。只要是为大家提供了一个思路,一个程序的实现多种多样。还是希望大家对一个问题提供多种解决方案,这样才能拓宽自己的思路。
 如果文章有描述不正确或者错误的地方,还望指正。您可以留言📫或者私信我。🙏

最后希望大家多多 关注+点赞+收藏^_^,你们的鼓励是我不断前进的动力!!!
感谢感谢~~~🙏🙏🙏

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艺术留白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值