一、数据库介绍:
1、account:帐务信息表
2、admin_info:管理员信息表
3、admin_role:管理员角色信息表
4、cost:资费信息表
5、privilege_info:权限信息表
6、role_info:角色信息表
7、role_privilege:角色权限表
8、service:业务信息表
二、项目结构及功能介绍:
2-1 项目结构:
2-2 功能介绍:
1、登录模块(login.jsp):
通过输入账号、密码、以及验证码可进行系统登录功能。
2、主页(pages/index.jsp):
项目主页,含有所有功能模块菜单。
3、角色管理(role/role_list.jsp):
角色管理页,可对表中各角色进行操作。
4、管理员(admin/admin_list.jsp):
管理员页,可对管理员角色进行功能操作。
5、资费管理(fee/fee_list):
资费管理页。可对用户资费信息进行操作。
6、账务账号(account/account_list.jsp):
账务账号页。可对用户账务信息进行操作。
7、业务账号(service/service_list.jsp):
业务账号页。可对用户业务信息进行操作。
8、账单管理(bill/bill_list.jsp):
账单管理页。可对用户账单信息进行操作。
9、报表(report/report_list.jsp)
报表管理页。可对账号的报表信息进行操作。
10、个人信息(user/user_info.jsp)
个人信息管理页。可对当前登录用户信息进行查看及操作。
11、个人信息---修改密码(user/user_modi_pwd.jsp)
个人信息的密码管理页。可对当前登录用户的密码进行操作。
三、SSM项目配置文件(必须):
1、pom.xml需要引入的项目坐标依赖:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.ssm.netctoss</groupId> <artifactId>netctoss</artifactId> <version>1.0-SNAPSHOT</version> <name>netctoss</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <!--junit的依赖jar包--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> <scope>test</scope> </dependency> <!-- servlet依赖 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!-- jsp依赖 --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2.1-b03</version> <scope>provided</scope> </dependency> <!-- jstl --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- jackson依赖 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.11.0</version> </dependency> <!-- springmvc依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.5.RELEASE</version> </dependency> <!--mybatis的依赖jar包--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.5</version> </dependency> <!--mysql的依赖jar包--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.31</version> </dependency> <!-- druid连接池依赖 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.12</version> </dependency> <!-- spring事务依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.5.RELEASE</version> </dependency> <!-- 参考版本对应 http://www.mybatis.org/spring/ --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.3</version> </dependency> <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.2.0</version> </dependency> <!-- commons 文件上传jar --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> </dependencies> </project>
2、JDBC连接池配置文件:jdbc.properties
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/ssm_db?serverTimezone=Asia/Shanghai&useTimezone=true&useSSL=false jdbc.username=root jdbc.password=root
3、Mybatis的配置文件:mybatis-config.xml
因为关于Mybatis的其它配置代码,因为在后文的spring-ioc.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> <plugins> <!-- 配置 PageHelper 分页插件 --> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <property name="helperDialect" value="mysql"/> <property name="reasonable" value="true"/> <property name="supportMethodsArguments" value="true"/> <property name="params" value="pageNum=pageHelperStart;pageSize=pageHelperRows;"/> </plugin> </plugins> </configuration>
4、spring的配置文件:spring-ioc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!--开启注解扫描,比如扫描Dao,Service--> <context:component-scan base-package="com.ssm.netctoss"/> <!--配置加载jdbc.properties文件--> <context:property-placeholder location="classpath:jdbc.properties"/> <!--配置druid的连接池: 使用了spring容器来代替了mybatis的核心配置文件的数据源--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver}"></property> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!--配置SqlSessionFactory的bean--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!--绑定数据源--> <property name="dataSource" ref="dataSource"></property> <!--加载mybatis的核心配置文件--> <property name="configLocation" value="classpath:mybatis-config.xml"></property> <!--配置加载各个pojo对应的XXXXMapper.xml 代替的是mybatis核心配置文件里的mapper设置--> <property name="mapperLocations" value="classpath:com/ssm/netctoss/mapper/*.xml"/> <property name="typeAliasesPackage" value="com.ssm.netctoss.pojo"/> </bean> <!--配置可以扫描mapper/dao接口的类型--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> <property name="basePackage" value="com.ssm.netctoss.mapper"></property> </bean> </beans>
5、springMVC的配置文件:spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--开启SpringMVC的注解: 简化处理器映射器和处理器适配器的bean注册,以及JSON数据的传递--> <mvc:annotation-driven/> <!--静态资源的访问通过配置--> <mvc:default-servlet-handler/> <!--视图解析器的配置--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"/> <property name="suffix" value=".jsp" /> </bean> </beans>
6、整合 spring + springMVC的配置文件:mainConfig.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--整合ioc 和 mvc的两个配置文件--> <import resource="classpath:spring-ioc.xml"/> <import resource="classpath:spring-mvc.xml"/> </beans>
四、项目模块开发步骤:
(用service模块举例,其它模块的步骤相同)
1、数据库对应的实体类:XXX.java
(Service.java)
package com.ssm.netctoss.pojo; import java.sql.Timestamp; import java.util.Objects; public class Service { private Integer serviceId; // 业务ID private Integer accountId; // 账户ID private String unixHost; // UNIX主机地址 private String osUsername; // 操作系统用户名 private String loginPasswd; // 登录密码 private String status; // 服务状态。0:是暂停,1是开通,2是删除 private Timestamp createDate; // 创建日期 private Timestamp pauseDate; // 暂停日期 private Timestamp closeDate; // 关闭日期 private Integer costId; // 资费ID private String idcardNo; // 身份证号 private String name; // 构造函数 public Service() {} public Service(Integer serviceId, Integer accountId, String unixHost, String osUsername, String loginPasswd, String status, Timestamp createDate, Timestamp pauseDate, Timestamp closeDate, Integer costId, String idcardNo, String name) { this.serviceId = serviceId; this.accountId = accountId; this.unixHost = unixHost; this.osUsername = osUsername; this.loginPasswd = loginPasswd; this.status = status; this.createDate = createDate; this.pauseDate = pauseDate; this.closeDate = closeDate; this.costId = costId; this.idcardNo = idcardNo; this.name = name; } // Getter和Setter方法 public Integer getServiceId() { return serviceId; } public void setServiceId(Integer serviceId) { this.serviceId = serviceId; } public Integer getAccountId() { return accountId; } public void setAccountId(Integer accountId) { this.accountId = accountId; } public String getUnixHost() { return unixHost; } public void setUnixHost(String unixHost) { this.unixHost = unixHost; } public String getOsUsername() { return osUsername; } public void setOsUsername(String osUsername) { this.osUsername = osUsername; } public String getLoginPasswd() { return loginPasswd; } public void setLoginPasswd(String loginPasswd) { this.loginPasswd = loginPasswd; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public Timestamp getCreateDate() { return createDate; } public void setCreateDate(Timestamp createDate) { this.createDate = createDate; } public Timestamp getPauseDate() { return pauseDate; } public void setPauseDate(Timestamp pauseDate) { this.pauseDate = pauseDate; } public Timestamp getCloseDate() { return closeDate; } public void setCloseDate(Timestamp closeDate) { this.closeDate = closeDate; } public Integer getCostId() { return costId; } public void setCostId(Integer costId) { this.costId = costId; } public String getIdcardNo() { return idcardNo; } public void setIdcardNo(String idcardNo) { this.idcardNo = idcardNo; } public String getName() { return name; } public void setName(String name) { this.name = name; } // 重写equals和hashCode @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Service)) return false; Service service = (Service) o; return Objects.equals(serviceId, service.serviceId) && Objects.equals(accountId, service.accountId) && Objects.equals(unixHost, service.unixHost) && Objects.equals(osUsername, service.osUsername) && Objects.equals(loginPasswd, service.loginPasswd) && Objects.equals(status, service.status) && Objects.equals(createDate, service.createDate) && Objects.equals(pauseDate, service.pauseDate) && Objects.equals(closeDate, service.closeDate) && Objects.equals(costId, service.costId) && Objects.equals(idcardNo, service.idcardNo) && Objects.equals(name, service.name); } @Override public int hashCode() { return Objects.hash(serviceId, accountId, unixHost, osUsername, loginPasswd, status, createDate, pauseDate, closeDate, costId, idcardNo, name); } // 重写toString @Override public String toString() { return "Service{" + "serviceId=" + serviceId + ", accountId=" + accountId + ", unixHost='" + unixHost + '\'' + ", osUsername='" + osUsername + '\'' + ", loginPasswd='" + loginPasswd + '\'' + ", status='" + status + '\'' + ", createDate=" + createDate + ", pauseDate=" + pauseDate + ", closeDate=" + closeDate + ", costId=" + costId + ", idcardNo='" + idcardNo + '\'' + ", name='" + name + '\'' + '}'; } }
2、实体类对应的Service接口:XXXService.java
(ServiceService.java)
package com.ssm.netctoss.service; import com.github.pagehelper.PageInfo; import com.ssm.netctoss.pojo.SearchCondition; import com.ssm.netctoss.pojo.Service; public interface ServiceService { /** * 分页并按条件查询服务列表 * @param condition 搜索条件 * @param pageNum 页码 * @return PageInfo<Service> */ PageInfo<Service> findByPageAndCondition(SearchCondition condition, Integer pageNum); /** * 添加新的服务 * @param service 服务对象 */ void addService(Service service); /** * 根据服务ID查找服务 * @param serviceId 服务ID * @return Service */ Service findByServiceId(Integer serviceId); /** * 更新服务信息 * @param service 服务对象 */ void updateService(Service service); /** * 删除服务(逻辑删除) * @param serviceId 服务ID */ void deleteService(Integer serviceId); /** * 改变服务状态 * @param serviceId 服务ID * @param status 新状态 * @return 是否成功 */ boolean changeStatus(Integer serviceId, String status); }
3、每个Service接口对应的实现类Impl:XXXServiceImpl.java
(ServiceServiceImpl.java)
package com.ssm.netctoss.service.impl; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.ssm.netctoss.mapper.ServiceMapper; import com.ssm.netctoss.pojo.SearchCondition; import com.ssm.netctoss.pojo.Service; import com.ssm.netctoss.service.ServiceService; import javax.annotation.Resource; import java.util.List; @org.springframework.stereotype.Service public class ServiceServiceImpl implements ServiceService { private int pageSize = 5; // 每页显示的数量 private int navigatePages = 5; // 导航栏显示页码数量 @Resource private ServiceMapper serviceMapper; @Override public PageInfo<Service> findByPageAndCondition(SearchCondition condition, Integer pageNum) { PageHelper.startPage(pageNum, pageSize); // 启用分页 List<Service> services = serviceMapper.findByPageAndCondition(condition); // 查询符合条件的服务列表 PageInfo<Service> pageInfo = new PageInfo<>(services, navigatePages); // 创建分页信息对象 return pageInfo; } @Override public void addService(Service service) { serviceMapper.addService(service); // 调用Mapper层插入新的服务 } @Override public Service findByServiceId(Integer serviceId) { return serviceMapper.findByServiceId(serviceId); // 调用Mapper层根据ID查找服务 } @Override public void updateService(Service service) { serviceMapper.updateService(service); // 调用Mapper层更新服务信息 } @Override public void deleteService(Integer serviceId) { serviceMapper.deleteService(serviceId); // 调用Mapper层逻辑删除服务 } @Override public boolean changeStatus(Integer serviceId, String status) { int result = serviceMapper.changeStatus(serviceId, status); // 调用Mapper层更新服务状态 return result > 0; } }
4、每个实体类对应的Mapper接口:XXXMapper.java
(ServiceMapper.java)
package com.ssm.netctoss.mapper; import com.ssm.netctoss.pojo.SearchCondition; import com.ssm.netctoss.pojo.Service; import org.apache.ibatis.annotations.Param; import java.util.List; public interface ServiceMapper { /** * 分页并按条件查询服务列表 * @param condition 搜索条件 * @return List<Service> 服务列表 */ List<Service> findByPageAndCondition(SearchCondition condition); /** * 添加新的服务 * @param service 服务对象 */ void addService(Service service); /** * 根据服务ID查找服务 * @param serviceId 服务ID * @return Service */ Service findByServiceId(Integer serviceId); /** * 更新服务信息 * @param service 服务对象 */ void updateService(Service service); /** * 逻辑删除服务 * @param serviceId 服务ID */ void deleteService(Integer serviceId); /** * 改变服务状态 * @param serviceId 服务ID * @param status 新状态 * @return 受影响的行数 */ int changeStatus(@Param("serviceId") Integer serviceId, @Param("status") String status); }
5、每个实体类对应的Mapper.xml配置文件:XXXMapper.xml
(ServiceMapper.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.ssm.netctoss.mapper.ServiceMapper"> <!-- 结果映射 --> <resultMap id="serviceMap" type="Service"> <id column="service_id" property="serviceId" /> <result column="account_id" property="accountId" /> <result column="unix_host" property="unixHost" /> <result column="os_username" property="osUsername" /> <result column="login_passwd" property="loginPasswd" /> <result column="status" property="status" /> <result column="create_date" property="createDate" /> <result column="pause_date" property="pauseDate" /> <result column="close_date" property="closeDate" /> <result column="cost_id" property="costId" /> <result column="idcard_no" property="idcardNo" /> <result column="name" property="name" /> </resultMap> <!-- 根据条件和分页查询服务 --> <select id="findByPageAndCondition" parameterType="SearchCondition" resultMap="serviceMap"> SELECT s.*, a.idcard_no, c.name FROM service s JOIN account a ON s.account_id = a.account_id JOIN cost c ON s.cost_id = c.cost_id <where> <if test="osUsername != null and osUsername != '' "> AND s.os_username = #{osUsername} </if> <if test="unixHost != null and unixHost != '' "> AND s.unix_host = #{unixHost} </if> <if test="idcardNo != null and idcardNo != '' "> AND a.idcard_no = #{idcardNo} </if> <if test="status != null and status != '-1' "> AND s.status = #{status} </if> </where> ORDER BY s.service_id </select> <!-- 添加新服务 --> <insert id="addService" parameterType="Service"> INSERT INTO service (account_id, unix_host, os_username, login_passwd, status, create_date, cost_id) VALUES (#{accountId}, #{unixHost}, #{osUsername}, #{loginPasswd}, #{status}, #{createDate}, #{costId}) </insert> <!-- 根据serviceId查询服务 --> <select id="findByServiceId" parameterType="int" resultMap="serviceMap"> SELECT s.*, a.idcard_no, c.name FROM service s JOIN account a ON s.account_id = a.account_id JOIN cost c ON s.cost_id = c.cost_id WHERE s.service_id = #{serviceId} </select> <!-- 更新服务信息 --> <update id="updateService" parameterType="Service"> UPDATE service SET account_id = #{accountId}, unix_host = #{unixHost}, os_username = #{osUsername}, login_passwd = #{loginPasswd}, status = #{status}, create_date = #{createDate}, pause_date = #{pauseDate}, close_date = #{closeDate}, cost_id = #{costId} WHERE service_id = #{serviceId} </update> <!-- 逻辑删除服务(设置状态为关闭) --> <update id="deleteService" parameterType="int"> UPDATE service SET status = '2' WHERE service_id = #{serviceId} </update> <!-- 改变服务状态 --> <update id="changeStatus" parameterType="map"> UPDATE service SET status = #{status} WHERE service_id = #{serviceId} </update> </mapper>
6、XXX模块对应的前端 jsp 主界面:
(service_list.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>电信资费管理系统</title> <link type="text/css" rel="stylesheet" media="all" href="../statics/styles/global.css" /> <link type="text/css" rel="stylesheet" media="all" href="../statics/styles/global_color.css" /> <script src="${pageContext.request.contextPath}/statics/js/services.js"></script> <script language="javascript" type="text/javascript"> //显示角色详细信息 function showDetail(flag, a) { var detailDiv = a.parentNode.getElementsByTagName("div")[0]; if (flag) { detailDiv.style.display = "block"; } else detailDiv.style.display = "none"; } //删除 function deleteAccount(serviceId) { var r = window.confirm("确定要删除此业务账号吗?删除后将不能恢复。"); if (r) { // 发送请求到 delete 端点,设置 serviceId window.location.href = 'delete?serviceId=' + serviceId; } } //开通或暂停 function setState(serviceId, newStatus) { var action = newStatus === '1' ? "开通" : "暂停"; var confirmMsg = "确定要" + action + "此业务账号吗?"; var r = window.confirm(confirmMsg); if (r) { // 发送请求到 changeStatus 端点,设置状态 window.location.href = 'changeStatus?serviceId=' + serviceId + '&status=' + newStatus; } } //分页搜索 function searchService(page) { document.getElementById("pageNum").value = page; document.getElementById("myForm").submit(); } </script> </head> <body> <!--Logo区域开始--> <div id="header"> <img src="../statics/images/logo.png" alt="logo" class="left"/> <a href="#">[退出]</a> </div> <!--Logo区域结束--> <!-- 导航区域开始 --> <jsp:include page="../nav.jsp" /> <!-- 导航区域结束 --> <!--主要区域开始--> <div id="main"> <form action="searchService" method="post" id="myForm"> <!--查询--> <div class="search_add"> <input type="hidden" id="pageNum" name="pageNum" value="${pageInfo.pageNum}" /> <div>OS 账号:<input type="text" name="osUsername" value="${condition.osUsername}" class="width100 text_search" /></div> <div>服务器 IP:<input type="text" name="unixHost" value="${condition.unixHost}" class="width100 text_search" /></div> <div>身份证:<input type="text" name="idcardNo" value="${condition.idcardNo}" class="text_search" /></div> <div>状态: <select class="select_search" name="status"> <option value="-1" <c:if test="${condition.status == '-1'}">selected</c:if> >全部</option> <option value="1" <c:if test="${condition.status == '1'}">selected</c:if> >开通</option> <option value="0" <c:if test="${condition.status == '0'}">selected</c:if> >暂停</option> <option value="2" <c:if test="${condition.status == '2'}">selected</c:if> >删除</option> </select> </div> <div><input type="button" value="搜索" class="btn_search" id="searchBtn" οnclick="searchService(1)" /></div> <input type="button" value="增加" class="btn_add" οnclick="location.href='toAdd';" /> </div> <!--删除的操作提示--> <div id="operate_result_info" class="operate_success" style="display: none;"> <img src="../statics/images/close.png" οnclick="this.parentNode.style.display='none';" /> 操作成功! </div> <!--数据区域:用表格展示数据--> <div id="data"> <table id="datalist"> <tr> <th class="width50">业务ID</th> <th class="width70">账务账号ID</th> <th class="width150">身份证</th> <th class="width70">姓名</th> <th>OS 账号</th> <th class="width50">状态</th> <th class="width100">服务器 IP</th> <th class="width100">资费</th> <th class="width200">操作</th> </tr> <c:forEach items="${pageInfo.list}" var="service"> <tr> <td><a href="service_detail.jsp" title="查看明细">${service.serviceId}</a></td> <td>${service.accountId}</td> <td>${service.idcardNo}</td> <td>高哈哈</td> <td>${service.osUsername}</td> <td> <c:choose> <c:when test="${service.status == '0'}">暂停</c:when> <c:when test="${service.status == '1'}">开通</c:when> <c:when test="${service.status == '2'}">删除</c:when> <c:otherwise>未知状态</c:otherwise> </c:choose> </td> <td>${service.unixHost}</td> <td> <a class="summary" οnmοuseοver="showDetail(true,this);" οnmοuseοut="showDetail(false,this);">包 20 小时</a> <!--浮动的详细信息--> <div class="detail_info" style="display: none;"> 20小时,24.5 元,超出部分 0.03元/分钟 </div> </td> <td class="td_modi"> <c:choose> <c:when test="${service.status == '1'}"> <input type="button" value="暂停" class="btn_pause" οnclick="setState(${service.serviceId}, '0');" /> </c:when> <c:otherwise> <input type="button" value="开通" class="btn_start" οnclick="setState(${service.serviceId}, '1');" /> </c:otherwise> </c:choose> <input type="button" value="修改" class="btn_modify" οnclick="location.href='modify?serviceId=${service.serviceId}';" /> <input type="button" value="删除" class="btn_delete" οnclick="deleteAccount(${service.serviceId});" /> </td> </tr> </c:forEach> </table> <p>业务说明:<br /> 1、创建即开通,记载创建时间;<br /> 2、暂停后,记载暂停时间;<br /> 3、重新开通后,删除暂停时间;<br /> 4、删除后,记载删除时间,标示为删除,不能再开通、修改、删除;<br /> 5、业务账号不设计修改密码功能,由用户自服务功能实现;<br /> 6、暂停和删除状态的账务账号下属的业务账号不能被开通。 </p> </div> <!--分页--> <div id="pages"> <a href="javascript:searchService(1)">首页</a> <!-- 上一页 --> <c:choose> <c:when test="${pageInfo.pageNum > 1}"> <a href="javascript:searchService(${pageInfo.pageNum - 1})">上一页</a> </c:when> <c:otherwise> <a href="#" class="disabled">上一页</a> </c:otherwise> </c:choose> <!-- 中间页码动态生成 --> <c:forEach begin="${pageInfo.navigateFirstPage}" end="${pageInfo.navigateLastPage}" var="nav"> <c:choose> <c:when test="${pageInfo.pageNum == nav}"> <a href="#" class="current_page">${nav}</a> <!-- 当前页 --> </c:when> <c:otherwise> <a href="javascript:searchService(${nav})" class="page_link">${nav}</a> </c:otherwise> </c:choose> </c:forEach> <!-- 下一页 --> <c:choose> <c:when test="${pageInfo.pageNum < pageInfo.pages}"> <a href="javascript:searchService(${pageInfo.pageNum + 1})">下一页</a> </c:when> <c:otherwise> <a href="#" class="disabled">下一页</a> </c:otherwise> </c:choose> <!-- 末页 --> <a href="javascript:searchService(${pageInfo.pages})">末页</a> </div> </form> </div> <!--主要区域结束--> <div id="footer"> <span>[Copyright © 1996-2024 NET Corporation, All Rights Reserved]</span> <br /> <span>版权所有(C) Company NET</span> </div> <!-- 显示操作结果提示 --> <c:if test="${param.operation == 'changeStatus' && param.result == 'success'}"> <script type="text/javascript"> document.getElementById("operate_result_info").style.display = "block"; document.getElementById("operate_result_info").innerHTML = '<img src="../statics/images/close.png" οnclick="this.parentNode.style.display=\'none\';" />状态更新成功!'; </script> </c:if> <c:if test="${param.operation == 'changeStatus' && param.result == 'error'}"> <script type="text/javascript"> document.getElementById("operate_result_info").style.display = "block"; document.getElementById("operate_result_info").innerHTML = '<img src="../statics/images/close.png" οnclick="this.parentNode.style.display=\'none\';" />状态更新失败,请重试!'; </script> </c:if> </body> </html>
7、XXX前端 jsp 主界面中对应的添加(add)功能:
(service_add.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>电信资费管理系统</title> <link type="text/css" rel="stylesheet" media="all" href="../statics/styles/global.css" /> <link type="text/css" rel="stylesheet" media="all" href="../statics/styles/global_color.css" /> <script language="javascript" type="text/javascript"> //保存成功的提示信息 function showResult() { showResultDiv(true); window.setTimeout("showResultDiv(false);", 3000); } function showResultDiv(flag) { var divResult = document.getElementById("save_result_info"); if (flag) divResult.style.display = "block"; else divResult.style.display = "none"; } //自动查询账务账号 function searchAccounts(txtObj) { //document.getElementById("a1").innerHTML = txtObj.value; } </script> </head> <body> <!--Logo区域开始--> <div id="header"> <img src="../statics/images/logo.png" alt="logo" class="left"/> <a href="#">[退出]</a> </div> <!--Logo区域结束--> <!-- 导航区域开始 --> <jsp:include page="../nav.jsp" /> <!-- 导航区域结束 --> <!--主要区域开始--> <div id="main"> <!--保存操作的提示信息--> <div id="save_result_info" class="save_fail">保存失败!192.168.0.23服务器上已经开通过 OS 账号 “mary”。</div> <form action="add" method="post" class="main_form"> <!--内容项--> <div class="text_info clearfix"><span>身份证:</span></div> <div class="input_info"> <input type="text" name="idcardNo" class="width180" required /> <input type="button" value="查询账务账号" class="btn_search_large" /> <span class="required">*</span> <div class="validate_msg_short">没有此身份证号,请重新录入。</div> </div> <div class="text_info clearfix"><span>账务账号:</span></div> <div class="input_info"> <input type="text" name="accountId" οnkeyup="searchAccounts(this);" required /> <span class="required">*</span> <div class="validate_msg_long">没有此账务账号,请重新录入。</div> </div> <div class="text_info clearfix"><span>资费类型:</span></div> <div class="input_info"> <select name="costId" required> <option value="1">包 20 小时</option> <option value="2">包 40 小时</option> <option value="3">包 60 小时</option> <option value="4">包月</option> </select> </div> <div class="text_info clearfix"><span>服务器 IP:</span></div> <div class="input_info"> <input type="text" name="unixHost" required /> <span class="required">*</span> <div class="validate_msg_long">15 长度,符合IP的地址规范</div> </div> <div class="text_info clearfix"><span>登录 OS 账号:</span></div> <div class="input_info"> <input type="text" name="osUsername" required /> <span class="required">*</span> <div class="validate_msg_long">8长度以内的字母、数字和下划线的组合</div> </div> <div class="text_info clearfix"><span>密码:</span></div> <div class="input_info"> <input type="password" name="loginPasswd" required /> <span class="required">*</span> <div class="validate_msg_long">30长度以内的字母、数字和下划线的组合</div> </div> <div class="text_info clearfix"><span>重复密码:</span></div> <div class="input_info"> <input type="password" name="confirmPasswd" required /> <span class="required">*</span> <div class="validate_msg_long">两次密码必须相同</div> </div> <!--操作按钮--> <div class="button_info clearfix"> <input type="submit" value="保存" class="btn_save" /> <input type="button" value="取消" class="btn_save" /> </div> </form> </div> <!--主要区域结束--> <div id="footer"> <span>[Copyright © 1996-2024 NET Corporation, All Rights Reserved]</span> <br /> <span>版权所有(C) Company NET</span> </div> </body> </html>
8、XXX前端 jsp 主界面中对应的修改(modi)功能:
(service_modi.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>电信资费管理系统 - 修改服务</title> <link type="text/css" rel="stylesheet" media="all" href="../statics/styles/global.css" /> <link type="text/css" rel="stylesheet" media="all" href="../statics/styles/global_color.css" /> <script src="${pageContext.request.contextPath}/statics/js/services.js"></script> <script language="javascript" type="text/javascript"> // 其他 JavaScript 代码 </script> </head> <body> <!--Logo区域开始--> <div id="header"> <img src="../statics/images/logo.png" alt="logo" class="left"/> <a href="#">[退出]</a> </div> <!--Logo区域结束--> <!-- 导航区域开始 --> <jsp:include page="../nav.jsp" /> <!-- 导航区域结束 --> <!--主要区域开始--> <div id="main"> <form action="saveModify" method="post" id="myForm"> <!--修改表单内容--> <div class="form_section"> <!--业务账号ID--> <div class="text_info clearfix"><span>业务账号ID:</span></div> <div class="input_info"> <input type="hidden" name="serviceId" value="${service.serviceId}" /> <input type="hidden" name="accountId" value="${service.accountId}" /> <!-- 如果不需要修改 accountId,使用只读文本框 --> <input type="text" value="${service.accountId}" readonly class="readonly" /> </div> <!-- UNIX 主机地址 --> <div class="text_info clearfix"><span>UNIX 主机地址:</span></div> <div class="input_info"> <input type="hidden" name="unixHost" value="${service.unixHost}" /> <input type="text" value="${service.unixHost}" readonly class="readonly" /> </div> <!--OS 账号--> <div class="text_info clearfix"><span>OS 账号:</span></div> <div class="input_info"> <input type="text" name="osUsername" value="${service.osUsername}" class="text_input" /> </div> <!--登录密码--> <div class="text_info clearfix"><span>登录密码:</span></div> <div class="input_info"> <input type="password" name="loginPasswd" value="${service.loginPasswd}" class="text_input" /> </div> <!--状态--> <div class="text_info clearfix"><span>状态:</span></div> <div class="input_info"> <select name="status" class="text_input"> <option value="1" <c:if test="${service.status == '1'}">selected</c:if>>开通</option> <option value="0" <c:if test="${service.status == '0'}">selected</c:if>>暂停</option> <option value="2" <c:if test="${service.status == '2'}">selected</c:if>>删除</option> </select> </div> <!--创建时间--> <div class="text_info clearfix"> <span>创建时间:</span> </div> <div class="input_info"> <input type="text" name="createDate" value="<fmt:formatDate value='${service.createDate}' pattern='yyyy-MM-dd HH:mm:ss' />" readonly class="readonly" /> </div> <!--暂停时间--> <div class="text_info clearfix"><span>暂停时间:</span></div> <div class="input_info"> <input type="text" name="pauseDate" value="<fmt:formatDate value='${service.pauseDate}' pattern='yyyy-MM-dd HH:mm:ss' />" class="text_input" /> </div> <!--关闭时间--> <div class="text_info clearfix"><span>关闭时间:</span></div> <div class="input_info"> <input type="text" name="closeDate" value="<fmt:formatDate value='${service.closeDate}' pattern='yyyy-MM-dd HH:mm:ss' />" class="text_input" /> </div> <!--资费ID--> <div class="text_info clearfix"><span>资费ID:</span></div> <div class="input_info"> <input type="text" name="costId" value="${service.costId}" class="text_input" /> </div> <!--提交按钮--> <div class="form_actions"> <input type="submit" value="保存" class="btn_save" /> <input type="button" value="取消" class="btn_save btn_cancel" οnclick="location.href='searchService';" /> </div> </div> </form> </div> <!--主要区域结束--> <div id="footer"> <span>[Copyright © 1996-2024 NET Corporation, All Rights Reserved]</span> <br /> <span>版权所有(C) Company NET</span> </div> </body> </html>
9、XXX前端 jsp 主界面中对应的查找(detail)功能:
(service_detail.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>电信资费管理系统</title> <link type="text/css" rel="stylesheet" media="all" href="../statics/styles/global.css" /> <link type="text/css" rel="stylesheet" media="all" href="../statics/styles/global_color.css" /> </head> <body> <!--Logo区域开始--> <div id="header"> <img src="../statics/images/logo.png" alt="logo" class="left"/> <a href="#">[退出]</a> </div> <!--Logo区域结束--> <!-- 导航区域开始 --> <jsp:include page="../nav.jsp" /> <!-- 导航区域结束 --> <!--主要区域开始--> <div id="main"> <form action="" method="" class="main_form"> <!--必填项--> <div class="text_info clearfix"><span>业务账号ID:</span></div> <div class="input_info"> <input type="text" value="${service.id}" readonly class="readonly" /> </div> <div class="text_info clearfix"><span>账务账号ID:</span></div> <div class="input_info"> <input type="text" value="${service.accountId}" readonly class="readonly" /> </div> <div class="text_info clearfix"><span>客户姓名:</span></div> <div class="input_info"> <input type="text" readonly class="readonly" value="${service.customerName}" /> </div> <div class="text_info clearfix"><span>身份证号码:</span></div> <div class="input_info"> <input type="text" readonly class="readonly" value="${service.idCard}" /> </div> <div class="text_info clearfix"><span>服务器 IP:</span></div> <div class="input_info"> <input type="text" value="${service.unixHost}" readonly class="readonly" /> </div> <div class="text_info clearfix"><span>OS 账号:</span></div> <div class="input_info"> <input type="text" value="${service.osUsername}" readonly class="readonly" /> </div> <div class="text_info clearfix"><span>状态:</span></div> <div class="input_info"> <select disabled> <option value="active" ${service.status == 'active' ? 'selected' : ''}>开通</option> <option value="paused" ${service.status == 'paused' ? 'selected' : ''}>暂停</option> <option value="deleted" ${service.status == 'deleted' ? 'selected' : ''}>删除</option> </select> </div> <div class="text_info clearfix"><span>开通时间:</span></div> <div class="input_info"> <input type="text" value="${service.startTime}" readonly class="readonly" /> </div> <div class="text_info clearfix"><span>资费 ID:</span></div> <div class="input_info"> <input type="text" value="${service.costId}" class="readonly" readonly /> </div> <div class="text_info clearfix"><span>资费名称:</span></div> <div class="input_info"> <input type="text" value="${service.costName}" readonly class="width200 readonly" /> </div> <div class="text_info clearfix"><span>资费说明:</span></div> <div class="input_info_high"> <textarea class="width300 height70 readonly" readonly>${service.costDescription}</textarea> </div> <!--操作按钮--> <div class="button_info clearfix"> <input type="button" value="返回" class="btn_save" οnclick="location.href='service_list.jsp';" /> </div> </form> </div> <!--主要区域结束--> <div id="footer"> <span>[Copyright © 1996-2024 NET Corporation, All Rights Reserved]</span> <br /> <span>版权所有(C) Company NET</span> </div> </body> </html>
10、每个模块对应的Controller文件:XXXController.java
(ServiceConrtoller.java)
package com.ssm.netctoss.controller; import com.github.pagehelper.PageInfo; import com.ssm.netctoss.pojo.SearchCondition; import com.ssm.netctoss.pojo.Service; import com.ssm.netctoss.service.ServiceService; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import java.sql.Timestamp; @Controller @RequestMapping("/service") public class ServiceController { @Resource private ServiceService serviceService; /** * 查询所有或按条件搜索服务 */ @RequestMapping("searchService") public String findByPageAndCondition(SearchCondition condition, Integer pageNum, Model model) { if (pageNum == null) { pageNum = 1; } PageInfo<Service> pageInfo = serviceService.findByPageAndCondition(condition, pageNum); System.out.println(pageInfo); model.addAttribute("pageInfo", pageInfo); // 将查询条件字段再次绑定到model, 进行回显设置。 model.addAttribute("condition", condition); return "service/service_list"; } /** * 显示添加服务页面 * URL示例: /service/toAdd */ @RequestMapping("toAdd") public String toAddPage() { return "service/service_add"; // 返回添加页面视图 } /** * 处理添加服务的请求 * URL示例: /service/add */ @RequestMapping(value = "add", method = RequestMethod.POST) public ModelAndView addService(Service service, ModelAndView mav) { // 设置默认状态和创建时间等信息 service.setStatus("1"); // 假设1表示启用 service.setCreateDate(new Timestamp(System.currentTimeMillis())); // 调用服务层添加服务 serviceService.addService(service); // 设置返回视图,重定向到列表页面 mav.setViewName("redirect:/service/searchService"); return mav; } /** * 显示修改服务页面 * URL示例: /service/modify?serviceId=1 */ @RequestMapping("modify") public ModelAndView modifyService(@RequestParam("serviceId") Integer serviceId, ModelAndView mav) { System.out.println("Received serviceId: " + serviceId); // 日志输出 Service service = serviceService.findByServiceId(serviceId); if (service == null) { mav.setViewName("error"); mav.addObject("message", "未找到对应的服务。"); return mav; } mav.setViewName("service/service_modi"); mav.addObject("service", service); return mav; } /** * 处理修改服务的请求 * URL示例: /service/saveModify */ @RequestMapping(value = "saveModify", method = RequestMethod.POST) public ModelAndView saveModifiedService(Service service, ModelAndView mav) { // 调用服务层更新服务 serviceService.updateService(service); // 设置返回视图,重定向到列表页面 mav.setViewName("redirect:/service/searchService"); return mav; } /** * 删除服务(逻辑删除) * URL示例: /service/delete?serviceId=1 */ @RequestMapping("delete") public String deleteService(@RequestParam("serviceId") Integer serviceId) { serviceService.deleteService(serviceId); return "redirect:searchService"; // 重定向到服务列表页面 } /** * 改变服务状态 * URL示例: /service/changeStatus?serviceId=1&status=0 */ @RequestMapping("changeStatus") public String changeStatus( @RequestParam("serviceId") Integer serviceId, @RequestParam("status") String status, Model model) { boolean success = serviceService.changeStatus(serviceId, status); if (success) { return "redirect:/service/searchService?operation=changeStatus&result=success"; } else { return "redirect:/service/searchService?operation=changeStatus&result=error"; } } /** * 显示服务详细信息页面 * URL示例: /service/detail?serviceId=1 */ @RequestMapping("detail") public ModelAndView serviceDetail(@RequestParam("serviceId") Integer serviceId, ModelAndView mav) { Service service = serviceService.findByServiceId(serviceId); if (service == null) { mav.setViewName("error"); mav.addObject("message", "未找到对应的服务。"); return mav; } mav.setViewName("service/service_detail"); mav.addObject("service", service); return mav; } }