icanci version 1.10 文末底部有源码链接,和我自己的QQ会话链接 图片看不清楚可以放大浏览器页面
关键词 MVC JavaEE 博客
项目演示地址 建议使用PC访问 因为没有做手机兼容 http://www.jwebblog.icanci.cn/
开发环境
1.Windows 10 操作系统 i5处理器 RAM 16GB 64位操作系统
2.使用Hbuilder完成前端静态页面 并且为后端提供接接口
3.使用 eclipse 集成开发工具
4.基于 JDK8 开发
5.使用 Mysql5.x 开发
6.使用 Tomcat7.x 开发
使用到的jar包
email 邮件发送包
1.activation.jar
2.javax.mail.jar
3.commons-email-1.5.jar
fileupload 文件上传包
1.commons-fileupload-1.2.2.jar
2.commons-io-1.4.jar
druid 连接池
1.druid-1.1.16.jar
lombok 包 作用:极简JavaBean代码
1.lombok.jar
@简单粗暴节省JavaBean代码插件 Lombok.jar
mysql 连接包
1.mysql-connector-java-5.1.29.jar
操作EL表达式和JSP以及JSTL包 以及servlet包
1.el-api.jar
2.jsp-api.jar
3.servlet-api.jar
4.taglibs-standard-impl-1.2.5.jar
5.taglibs-standard-spec-1.2.5.jar
6.standard.jar
Apache封装的工具类
1.standard.jar
如果有些包在导入之后不见了,那可能是创建web项目的时候引入了Tomcat的lib 此时会有合并现象
需求分析
引言
本文对系统进行需求分析,系统按照功能逻辑被分为前台功能和后台和功能两个部分。前台功能主要包括用户信息、查询好友、博客内容、博客查询等功能。后台功能主要是对前展示内容的管理,包括用户的注册与登录、用户个人信息资料的变更、已发布博客的删除和新增博客的发布。
系统总体流程
普通用户用例图
管理员用户图
数据需求
输人输出要求
输入要求:界面所有的非固定性数据都来自用户所以在用户输入的时候,首先会在前端界面进行JavaScript脚本的检验,只有通过所有检验的用户数据才会传输到后台,在后台进行第二次检验,对数据内容的合法性进行验证,验证通过之后才传递到数据库,会在数据库进行第三次验证。都验证通过之后才会传递到数据库。
输出要求:系统会提供用户数据的展示。系统会在特定的位置将用户的数据展示出来。因为网站的大部分数据来自用户,所以输出的数据也来自用户。
安全保密性要求
对用户的密码进行后台数据库MD5算法加密保护,除了用户知道自己密码,其他人不知道用户密码。
系统架构设计
架构设计
架构设计的重点在于根据系统的不同视角和对质量的要求,设计出系统的不同结构,通常最主要的结构是将系统分层并产生层次内的模块,阐明模块之间的关系.
概要设计
确定模块结构或类结构,划分功能模块,将软件功能需求分配给所划分的最小单元模块。确定模块之间的联系,确定数据结构、文件结构、数据库模式,确定测试方法与策略。
详细设计
详细设计是根据概要设计提供的文档,确定每一个模块的算法,内部的数据组织,选定工具清晰表达算法,编写详细设计说明书和详细测试用例与计划。详细设计的重点在将模块的对象分解为属性和方法,并阐述如何实现。
DAO层
自定义Util类 logs类 JDBC模板类 exception类
Test单元测试 和 过滤器
应用逻辑层
数据库设计
数据库设计是系统设计的重要环节,数据要求和数据结构最终都要和数据库的表结构对应起来。数据库设计过程:
概要设计(ER图)-> 逻辑结构设计(设计关系模式并规范化)-> 物理设计(建表)
每一个JavaBean 对应数据库的一张表
实例:
User :
Long id;
String username;
String password;
String email;
Long jointime;
String headimage;
String sex;
Long age;
String personalizedSignature;
User表:
字段名称 数据类型 说明
id bigint(11) 自动递增
username varchar(20) 用户名
password varchar(80) 密码
email varchar(25) 电子邮件
jointime bigint(20) 加入小璨日期
headimage varchar(200) 头像
sex varchar(10) 性别
age bigint(5) 年龄
personalizedSignature varchar(255) 个性签名
用户界面设计
用户界面设计的目的是让用户易于使用,做到界面布局合理,美观大方,字体大小合适,色彩搭配合理。
系统实现
数据库实现
表1-1 数据库表设计说明
数据表 中文名 说明
admin 管理员表 存储管理员信息,包括用户名,密码,申请管理员的code
friendrelationship 好友关系表 存储互为好友的用户ID字段
user 用户信息表 存储注册用户的信息,包括用户名、密码、email、加入时间、头像、性别、年龄、个性签名
userfeedback 反馈信息表 存储用户反馈的信息,包括反馈主题、反馈内容、反馈时间等字段
uesrspace 发表博客表 存储已发布博客的具体信息,包括博客内容、上传图片、发表时间等字段以及相关外键字段
系统中的每个数据表的详细说明如下:
(1) admin表
申请管理员的信息
字段名称 数据类型 说明
id bigint(20) 自动递增 主键
username varchar(20) 用户名
password varchar(100) 密码
joinCode varchar(50) 申请管理员的code
(2) friendrelationship表
好友之间的id关系表,通过外键建立两个用户之间的好友关系
字段名称 数据类型 说明
id bigint(11) 自动递增 主键
userId1 bigint(11) 注册用户1
userId2 bigint(11) 注册用户2
(3) user表
用户的信息
字段名称 数据类型 说明
id bigint(11) 自动递增 主键
username varchar(20) 用户名
password varchar(80) 密码
email varchar(25) 电子邮件
jointime bigint(20) 加入小璨日期
headimage varchar(200) 头像
sex varchar(10) 性别
age bigint(5) 年龄
personalizedSignature varchar(255) 个性签名
(4) userfeedback表
用户反馈的信息
字段名称 数据类型 说明
id bigint(11) 自动递增 主键
feedbackTheme varchar(255) 反馈信息主题
feedbackContent varchar(255) 反馈信息内容
feedbackTime bigint(11) 反馈信息的时间(毫秒)
outPrint varchar(30) 数据库存储的反馈信息时间转换为自定义的日期显示
(5) userspace表
用户发表博客表
字段名称 数据类型 说明
id bigint(11) 自动递增 主键
uesrId bigint(11) 用户id
userMessagea varchar(612) 发表博客信息
userImage varchar(255) 博客配图
outputTime bigint(11) 发表时间(毫秒)
outPrint varchar(30) 数据库存储的发表时间转换为自定义的日期显示
系统具体功能实现
本项目分为了前端部分和后端部分两个工程。
用户注册 用户修改个人信息 用户修改密码 用户发表小璨
用户查询已经发表的小璨 用户删除小璨
用户意见反馈
用户查询好友
用户联系客服 通过连接唤起QQ会话客服
系统核心代码
分页核心代码:PageResult.java
package cn.icanci.page;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
//分页的结果对象
@SuppressWarnings("all")
@Getter
public class PageResult {
private List<?> listData; // 结果集数据,通过SQL查询
private Integer totalCount; // 结果总数,通过SQL查询
private Integer currentPage = 1; // 当前页 用户传入
private Integer pageSize = 5; // 每一页条数 用户传入
private Integer beginPage = 1;// 首页
private Integer prevPage;// 上页 计算
private Integer nextPage;// 下页 计算
private Integer totalPage;// 末页 计算
public PageResult(List<?> listData, Integer totalCount, Integer currentPage, Integer pageSize) {
super();
this.listData = listData;
this.totalCount = totalCount;
this.currentPage = currentPage;
this.pageSize = pageSize;
this.totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
this.prevPage = currentPage - 1 >= 1 ? currentPage - 1 : 1;
this.nextPage = currentPage + 1 <= totalPage ? currentPage + 1 : totalPage;
}
}
JDBC核心代码1:JDBCUtil.java JDBC工具类
package cn.icanci.util;
import java.sql.ResultSet;
import java.sql.PreparedStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
public class JDBCUtil {
private static Properties p = new Properties();
private static DataSource ds =null;
//加载驱动 连接数据库 定义PreparedStatement 语句 执行sql语句 关闭连接
static {
try {
//从本地的class路径寻找配置文件的资源
p.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("druid.properties"));
ds = DruidDataSourceFactory.createDataSource(p);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接 加载驱动在druid连接池就已经完成了
* @return 返回 连接对象
*/
public static Connection getConnection() {
try {
return ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* 把连接还给连接池
* @param conn Connection 对象
* @param stmt PreparedStatement 对象
* @param rs ResultSet 对象
*/
public static void close(Connection conn,PreparedStatement stmt,ResultSet rs) {
try {
if(rs!=null) {
rs.close();
}
}catch(Exception e) {
}finally {
try {
if(stmt!=null) {
stmt.close();
}
}catch(Exception e) {
}finally {
try {
if(conn!=null) {
conn.close();
}
}catch(Exception e) {
}
}
}
}
}
JDBC核心代码2:JDBCTemplate.java 操作JDBC的模板类
package cn.icanci.template;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Connection;
import cn.icanci.dao.IResultSetHander;
import cn.icanci.util.JDBCUtil;
public class JDBCTemplate {
/**
* 重构DML操作
*
* @param sql sql语句 带有占位符
* @param objects Object数组
* @return 返回影响的行数
*/
public static int update(String sql, Object... objects) {
Connection conn = null;
PreparedStatement stmt = null;
conn = JDBCUtil.getConnection();
try {
stmt = conn.prepareStatement(sql);
for (int index = 0; index < objects.length; index++) {
stmt.setObject(index + 1, objects[index]);
}
return stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtil.close(conn, stmt, null);
}
return 0;
}
/**
* 查询操作
*
* @param <T> 查询的JavaBean的类型
* @param sql 需要执行的sql语句
* @param rsh 顶级接口 IResultSetHander 的接口实现
* @param objects 不定长参数数组 用来填充预编译语句的?
* @return 返回一个结果集
*/
public static <T> T query(String sql, IResultSetHander<T> rsh, Object... objects) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
conn = JDBCUtil.getConnection();
try {
stmt = conn.prepareStatement(sql);
System.out.println(sql);
for (int index = 0; index < objects.length; index++) {
// 匹配到 like
if (sql.contains("like") && index == 0) {
Object obj = "%" + objects[index] + "%";
stmt.setObject(index + 1, obj);
} else {
stmt.setObject(index + 1, objects[index]);
}
}
rs = stmt.executeQuery();
return rsh.hander(rs);
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtil.close(conn, stmt, rs);
}
throw new RuntimeException("查询有异常");
}
public static <T> T query(String sql, IResultSetHander<T> rsh, Long... userIds) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
conn = JDBCUtil.getConnection();
try {
stmt = conn.prepareStatement(sql);
for (int index = 0; index < userIds.length; index++) {
stmt.setObject(index + 1, userIds[index]);
}
rs = stmt.executeQuery();
return rsh.hander(rs);
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtil.close(conn, stmt, rs);
}
throw new RuntimeException("查询有异常");
}
}
文件上传核心代码:FileUtil.java
package cn.icanci.util;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import cn.icanci.exception.LogicException;
public class FileUtil {
// 可以接收的图片类型
private static final String UPLOAD_IMAGES_TYPE = "bmp,jpg,png,tif,gif,pcx,tga,exif,fpx,svg,psd,cdr,pcd,dxf,ufo,eps,ai,raw,WMF,webp";
@SuppressWarnings({ "unused", "unchecked" })
public static void upload(HttpServletRequest req, Map<String, String> map) throws ServletException, IOException {
req.setCharacterEncoding(StaticResources.encoding);
try {
// 解析和检查请求 方式是不是POST 请求编码是不是 ....
boolean isMultipart = ServletFileUpload.isMultipartContent(req);
// 创建FileItemFactory对象
DiskFileItemFactory factory = new DiskFileItemFactory();
// 缓存大小 默认值是10k
factory.setSizeThreshold(1024 * 200); // 20kb
// 创建文件上传的处理器
ServletFileUpload upload = new ServletFileUpload(factory);
// 设置最大上传文件大小为 7M
upload.setFileSizeMax(1024 * 1024 * 7);
List<FileItem> items = upload.parseRequest(req);
for (FileItem fileItem : items) {
String fileName = fileItem.getFieldName();
if (fileItem.isFormField()) {
// 普通表单控件 获取普通表单控件的参数值
map.put(fileName, fileItem.getString(StaticResources.encoding));
} else {
// 当前文件的MIME类型
// req.getServletContext().getMimeType(fileItem.getName());
// 上传文件的拓展名
String ext = FilenameUtils.getExtension(fileItem.getName());
// 判断文件类型
String[] type = UPLOAD_IMAGES_TYPE.split(",");
// 当前上传的文件不支持
if (!Arrays.asList(type).contains(ext)) {
throw new LogicException("图片类型不支持");
}
// 上传表单控件 把二进制数据写到哪一个文件中
String dir = req.getServletContext().getRealPath("/headImagesUploadedByUsers");
String uuidName = UUID.randomUUID().toString() + "."
+ FilenameUtils.getExtension(fileItem.getName());
System.out.println("文件上传之前");
fileItem.write(new File(dir, uuidName));
System.out.println("文件上传之后");
System.out.println(fileName + " put 名字");
System.out.println("/headImagesUploadedByUsers/" + uuidName);
map.put(fileName, "/headImagesUploadedByUsers/" + uuidName);
}
}
} catch (LogicException e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
}
}
}
邮件发送核心代码:EmailUtil.java
package cn.icanci.util;
import java.util.Random;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail;
import cn.icanci.dao.IUserDao;
import cn.icanci.dao.impl.UserDaoImpl;
import cn.icanci.domain.User;
public class EmailUtil {
/**
* 生成6位数 验证
*
* @return 返回验证码 code
*/
public static String getRandomCode() {
String code = "";
Random rd = new Random();
for (int i = 0; i < 6; i++) {
int r = rd.nextInt(10); // 每次随机出一个数字(0-9)
code = code + r; // 把每次随机出的数字拼在一起
}
System.out.println(code);
return code;
}
/**
* 向邮件发送验证码
*
* @param email 需要发送的邮箱地址
* @param randomCode 需要发送的code值
*/
public static void sendEmail(String email, String randomCode) {
IUserDao userDao = new UserDaoImpl();
User user = new User();
String sendMessage = "登陆";
HtmlEmail send = new HtmlEmail();// 创建一个HtmlEmail实例对象
// 获取随机验证码
String resultCode = randomCode;
// ---------------------------------------------------------
// 在这里判断数据库是否存在该账户,用来发送不同的验证码
user = userDao.getUserByEmail(email);
User u = userDao.isRoot(user);
if (u != null) {
// user存在 那就是登陆
sendMessage = "登陆";
} else {
// user不存在 那就是注册
sendMessage = "注册";
}
// ------------------------------------------------------
try {
send.setHostName("smtp.163.com");
send.setAuthentication("icanci@163.com", "icancixswl"); // 第一个参数是发送者的 163 Eamil邮箱 第二个参数是授权码
send.setFrom("icanci@163.com", "璨詞文化");// 发送人的邮箱为自己的,用户名可以随便填 记得是自己的邮箱
send.setSmtpPort(587); // 端口号 必须开
send.setSSLOnConnect(true); // 开启SSL加密
send.setCharset("utf-8");
send.addTo(email); // 设置收件人 email为你要发送给谁的邮箱账户 上方参数
send.setSubject("欢迎" + sendMessage + " ICANCI 官网"); // 邮箱标题
send.setMsg("【璨詞文化】你正在" + sendMessage + " ICANCI 官网,验证码: " + resultCode
+ " 验证码十分钟之内有效。 转发可能导致帐号被盗。如果这不是你本人操作请忽略..."); // Eamil发送的内容
send.send(); // 发送
System.out.println("发送成功");
} catch (EmailException e) {
e.printStackTrace();
}
}
}
核心 配置文件:web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<!-- 全局的初始化参数 -->
<context-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</context-param>
<error-page>
<error-code>404</error-code>
<location>/errorPages/404.html</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/errorPages/500.html</location>
</error-page>
<error-page>
<exception-type>Exception</exception-type>
<location>/errorPages/exception.html</location>
</error-page>
<!-- 对所有资源过滤 设置编码为 UTF-8 -->
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>cn.icanci.web.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 对登陆进行过滤 <filter> <filter-name>CheckLoginFilter</filter-name> <filter-class>cn.icanci.web.filter.CheckLoginFilter</filter-class>
</filter> <filter-mapping> <filter-name>CheckLoginFilter</filter-name> <url-pattern>/user/*</url-pattern>
</filter-mapping> 没有登陆就不能访问 -->
<!-- 对所有的文件进行过滤 session 的存活时间是 60 * 10 秒-->
<filter>
<filter-name>MaxSessionLifeFilter</filter-name>
<filter-class>cn.icanci.web.filter.MaxSessionLifeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MaxSessionLifeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
JSP操作Session的核心代码
代码块1 用户博客主页读取数据核心代码:index.jsp
<ic:forEach items="${pageResult.listData}" var="user">
<ic:set var="flag" value="true" />
<ic:if test="${pageResult.listData == null}">
<ic:set var="flag" value="false"/>
<div class="user-message">
<div class="out">
<ul>
<li class="l10"><a href="">你还没有发布任何小璨小璨 赶快去发布一个吧 </a></li>
<li>你还没有发布任何小璨小璨 赶快去发布一个吧</li>
</ul>
</div>
</div>
</ic:if>
<div class="user-message">
<div class="out">
<ul>
<li class="user-img"><img src="${sessionScope.USER_IN_SESSION.headimage}"></li>
<li class="l10">${sessionScope.USER_IN_SESSION.username}</li>
<li class="l10">个性签名: ${sessionScope.USER_IN_SESSION.personalizedSignature} </li>
<li class="l10">${user.outPrint}</li>
<li class="l10"><a href="/user/deleteSelfUserSpace?deleteUserSpaceID=${user.id}">删除此条小璨</a></li>
</ul>
</div>
<div class="info">
<div class="message">
<!-- 从用户数据读取的文字 -->
<ic:if test="${user.userMessages!=null}">
<p>
${user.userMessages}
</p>
</ic:if>
<p> </p>
</div>
<ic:if test="${user.userImage!=null}">
<div class="imgs">
<!-- 从用户信息读取的图片 -->
<img src="${user.userImage}">
</div>
</ic:if>
</div>
<div class="clearfloat"></div>
</div>
</ic:forEach>
代码块2 用户主页页面分页核心代码:index.jsp
<!-- 底部盒子导航 -->
<div class="jump">
<p>
<a href="/user/userSpaceInfomationPages?currentPage=${pageResult.beginPage}&pageSize=${PageSize}">首页</a>
<a href="/user/userSpaceInfomationPages?currentPage=${pageResult.prevPage}&pageSize=${PageSize}">上一页</a>
<a href="/user/userSpaceInfomationPages?currentPage=${pageResult.nextPage}&pageSize=${PageSize}">下一页</a>
<a href="/user/userSpaceInfomationPages?currentPage=${pageResult.totalPage}&pageSize=${PageSize}">尾页</a>
当前是 ${pageResult.currentPage}/${pageResult.totalPage} 页 一共 ${pageResult.totalCount} 条数据
</p>
<form action="/user/userSpaceInfomationPages" method="post">
跳转到第 <input class="numget" type="number" value="${pageResult.currentPage}" min="1" max="${pageResult.totalPage}" name="currentPage" id="" /> 页
<input type="submit" class="numsub" value="跳转"/>
</form>
</div>
<div class="foot">
<p> </p>
<p><a href="">加入我们</a> <a href="">关于我们</a> <a href="">联系我们</a> <a href="">技术交流</a> <a href="">商务合作</a> </p>
<p>© ICANCI 版权所有 一切行为解释权归 ICANCI 所有</p>
</div>
</div>
</div>
</div>
<!-- 底部导航 -->
其余核心代码见文章尾部连接
系统测试
单元测试 白盒测试
单元测试属于白盒测试,通过分析程序内部的逻辑与执行路线来设计测试用例,可以结合当前流行的自动化测试框架,例如Junit。
部分测试如下
黑盒测试的书写
测试结果
登陆界面测试
注册界面测试 发送成功之后会给出提示
邮箱接收验证码测试
完善用户信息测试
登陆测试
用户界面测试 完善信息之后会直接跳转到主页面
修改资料测试
发表文章测试
查询文章测试
删除文章测试
联系客服测试
意见反馈测试
安全退出登陆测试 退出之后返回登陆界面
管理员界面测试
对软件功能的结论
测试结果显示系统前台的文章的浏览、图片的展示等功能均正确,后台的用户注册、登录、文章的发布及删除查询、修改资料、等功能均无问题,用户的个人信息存储安全。经过以上所有的测试,本系统在所有的测试过程都能够保持稳定的运行,并且页面加载速度快速,展示良好,达到了系统的设计需求。
项目总结
实际的开发结果
实现了用户的注册、用户信息完善、用户登陆动态验证码验证、用户发表和删除博客、用户意见反馈、用户搜索博客、用户查询好友,同时也实现了用户与QQ之间组件的互联。实现了管理员的登陆验证、管理员查看用户基本信息的实现、管理员查看用户意见反馈的实现。
开发工作评价
在JDBC方面使用了阿里巴巴的Druid连接池,手动封装了JDBC工具类,JDBC模板类,界面图片验证码,动态刷新技术。历经2周开发完成,现在为第一个版本。
经验和教训
在登陆验证上面花了很多的功夫,总共经历了三次验证,才将数据传入到数据库中。在界面的动态展示,在数据库存储的用户发表的博客时间为系统的毫秒值,后来又增加了一个字段,用来存储具体的格式化的时间值,用户刷新个人博客空间的时候,按照数据库时间的毫秒值进行排序,对博客的分页处理和查询处理页封装了方法。缺点:界面不够美化,一些动态JavaScript没有写的很好,后台设计的时候没有合并可以合并的Servlet类导致看起来有些混乱。
版本迭代计划
优化:
优化整体界面 优化相应速度 使得界面更加人性化 可以自定义 背景等
优化代码包风格
优化 JS 弹窗
优化全局搜索
测试优化之后的时间对比
增加功能:
添加好友 删除好友 好友之间通信 安全验证 增加系统安全 加密算法放在 JS 脚本中
增加管理员的通信 管理员与用户之间的通信 增加公告 增加广告设计
增加顶级管理员 用来管理管理员 增加系统的动态效果 以及动态投放等功能
增加系统对用户个人的探索发现
增加 用户的一些基本功能
兼容PC浏览器和手机浏览器开发
手机端同步 设计手机端样式
项目说明
JDBC配置文件 此处使用 @阿里巴巴的Druid连接池 四个配置资源的名字是固定的
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/icanci?useOldAliasMetadataBehavior=true
username=root
password=ok
maxActive=100
运行此项目的所需的
1.配置JDBC资源文件
2.配置自己的邮箱和密码 允许发送邮箱的协议 此处@java实现邮箱发送邮件功能
3.此系统逻辑 用户注册之后必须完善基本信息 不然不可以登陆 所有数据包括查询的数据都是按照时间由近及远排序
4.貌似管理员没有退出按钮
5.一些jar包的使用比如 Lombok 我给个实例吧
如下图只要贴一个标签 就可以生成 Getter/Setter/toString等等方法 不用手动生成 修改字段也不需要重新生成Getter/Setter等方法 我举得简单粗暴 hhh
package cn.icanci.domain;
import lombok.Data;
@Data
public class User {
private Long id;
private String username;
private String password;
private String email;
private Long jointime;
private String headimage;
private String sex;
private Long age;
private String personalizedSignature;
}
5.其他的想起了补上去 我觉得应该没得了emmm