基于JavaWeb和MySQL的3D网上模板商城
第1章 需求分析
1.1 项目背景和问题的提出
时代的变化,导致日新月异的网站表达方式,3D网站和3D游戏的火热,也促进了开发,学习人员对一些3D模型,全景视图等方面的需求,在初学者需要调用一定的模型文件来完成具体场景的搭建或者在项目的完成过程中建模师需要适量地减少工作量的时候,都需要在网上下载相对的模型来进行项目完善。但是在使用现在的一些现有的模板网站的时候,许多网站的安排的有一些不合理性,或者是一些网站的模型过少以及模板质量的不合格性。
1.2 项目意义和主要完成内容
1.2.1 项目意义
为了弥补上述弊端,本网站提在原有的模板网站上做出了技术和机制的创新,关键在于电子货物的商城模式 ,给用户以在线下载的方式获取网站上所需类型的模型,用户有一定的金币来兑换模型,3d视野,新式网站demo的下载,是一种视觉的享受,顺应时代的潮流,金币不够的情况下客户可以选择投稿自己的模板来或得高额的金币奖励,也可以给网站提出相应的建议来获取金币奖励,当然也可以使用网上银行进行充值。
上传到的文件经过后台的筛选和重做可以作为新的模板进行上架,扩充网站内容,经过筛选后的投稿即给予投稿者一定奖励。留言和反馈内容如果有价值也有一定的奖励发布给投稿者。
1.2.2 功能
-
用户端 :实现网站的观看,需要进行登录才能实现下载功能,如果余额充足,则顺利下载,如果不足,则可选择提供有用的建议或者投稿作品来获得金币奖励,或者使用现金充值
-
商品类型 :网站(商业,宣传,其他类型),模型(风景建筑,人物妖怪,军事器材,动植物,室内,其他杂项),动画(人物,动物,其他),3d全景视野(家居装修,公共场所,其他全景)
-
用户操作 :用户注册,用户登录,忘记密码,修改姓名和性别资料,头像上传,下载文件,金币充值,提供建议,投稿作品
-
其他功能 :验证内容的合法性,自动校验是否已下载,验证的拖动滑块验证功能,全屏滑动功能,3D背景的生成和展示以及点击事件的触发功能,产品的自动分类功能以及自动检测扣费情况
1.3 项目开发环境
操作系统 | Windows10 |
---|---|
开发工具 | Myeclipse,HBulider |
浏览器 | Google Chrome/Internet Exploer |
数据库 | MySQL |
使用语言 | JSP语言和IAVA语言 |
第2章 概要设计
2.1系统功能框架
在线模板商城分为用户端和管理员端,分别能够进行不同的操作。
2.2 功能模块说明
2.2.1 用户
-
注册登录 :用户可以注册,登录,退出登录,注册后的默认金币数量是200。忘记密码后选择使用注册的电话号码来获取验证码找回密码
-
修改资料 :修改自己的昵称和性别信息,以及上传头像
-
留言 :在网站上发表留言,发表后可以在自己的资料页上查看,可以删除自己的留言,留言分为已采纳和未采纳两种状态,由管理员操作
-
投稿 :在网站上上传文件进行一定的描述以后进行投稿,自己的投稿可以在自己的资料页看到,投稿文件显示状态,如果未被采纳,则会显示出该投稿的收益金币数量
-
下载文件 :最基本的下载网站上的文件操作,根据不同的分类可查看文件详情,系统自动判断该文件是否是该用户下载过的,如果已下载,那么不重复扣除金币
-
充值 :金币不够不足以下载文件时可以进行金币充值,默认一次充值金币数量是200
2.2.2 管理员
-
登录 :管理员进行登录以后才可以到达网站的后台查看网站的数据库内容以及进行数据库的操作
-
用户修改 :管理员可修改用户的信息资料,但是无权修改用户的金币数量和密码
-
添加用户 :可以添加新用户,用户添加后默认的金币数量是200
-
模型处理 :删除模型,添加模型,和修改模型参数,选择模型的分类后进行添加,添加模型需要上传模型展示图片和模型文件,上传后的模型默认下载数量为0。添加模型模型上传后直接显示检测出模型大小和模型格式,作为默认字段更新到数据库当中
-
留言处理 :对留言进行处理,可以采纳留言,留言采纳后系统自行给留言用户的金币数量加100,也可以删除无用的留言,已被删除掉的用户留言信息无法采纳
-
投稿处理 :对用户投稿的信息进行处理,可以删除无用的信息,也可以下载后进行修改或其他操作以后发布到网站中,如果投稿信息有用,则管理员进行采纳,采纳后金币发放到达该用户账户,如果该用户已被删除,那么无法进行采纳
-
文件下载 :对网站上的商品直接进行下载。
第3章 详细设计
3.1 前端设计
3.1.1设计理念
由于网站的下载内容具有多样性,所以为了避免色调的颜色混搭不协调,网页的风格为黑白简洁,将网站中的资源文件分类方便查看。
为了迎合当前网站的设计理念和网站的新形象,在登录,注册,密码找回界面,网站首页设置3D外观的表现形式。开发形式为three.js。其将界面分别设置为海洋和山坡。
管理员界面,尽量要求简洁,可操作性强,在登录界面导入黑色的飞鸟群来使界面看起来充实。
3.1.2 实现方法
搭载框架后使用天空盒子营造天空形象,在使用海洋通道进行渲染,渲染后加强视觉效果使用normal-map来达到立体效果,使用water方案来加入平面实现,全程加入环境光和太阳光,使用太阳光晕来熏染达到阳光效果,接近海水颜色的雾化效果使用较远的显示效果达到海平面的视觉效果。使用IcosahedronGeometry来创建完全的球状物体并使用图片贴图,为球形物体添加鼠标点击事件使跳转往主页,并使用OrbitControls控件达到视野移动的效果。
山地的制作情况可以简要概述为:使用噪音处理得到起伏的山地效果,对着色器的各个属性进行图片贴图效果处理,形成色彩效果,在渲染器中对每一帧渲染时都进行更新造成移动效果。鸟类为js中的现有动画,添加到环境中后以混合动画的形式加入数组,同时定义一个数组存储每个对象的运动速度,然后在render函数中遍历数组更新其中的动画,雾化效果适当加入隐藏背景色。
导入鸟类的js动画文件,进行200次初始化,同时初始化200个鸟类的飞行状态的自定义数组,每帧刷新的时候都根据鸟类到中心点的位置来进行颜色的刷新,同时添加鼠标的移动事件来使鸟群避开鼠标所在位置。
3.1.3 关键代码
噪音干扰
java
float snoise( vec3 v ) {
const vec2 C = vec2( 1.0 / 6.0, 1.0 / 3.0 );
const vec4 D = vec4( 0.0, 0.5, 1.0, 2.0 );
vec3 i = floor( v + dot( v, C.yyy ) );
vec3 x0 = v - i + dot( i, C.xxx );
vec3 g = step( x0.yzx, x0.xyz );
vec3 l = 1.0 - g;
vec3 i1 = min( g.xyz, l.zxy );
vec3 i2 = max( g.xyz, l.zxy );
vec3 x1 = x0 - i1 + 1.0 * C.xxx;
vec3 x2 = x0 - i2 + 2.0 * C.xxx;
vec3 x3 = x0 - 1. + 3.0 * C.xxx;
i = mod( i, 289.0 );
vec4 p = permute( permute( permute(
i.z + vec4( 0.0, i1.z, i2.z, 1.0 ) )
+ i.y + vec4( 0.0, i1.y, i2.y, 1.0 ) )
+ i.x + vec4( 0.0, i1.x, i2.x, 1.0 ) );
float n_ = 1.0 / 7.0; // N=7
vec3 ns = n_ * D.wyz - D.xzx;
vec4 j = p - 49.0 * floor( p * ns.z *ns.z );
vec4 x_ = floor( j * ns.z );
vec4 y_ = floor( j - 7.0 * x_ );
vec4 x = x_ *ns.x + ns.yyyy;
vec4 y = y_ *ns.x + ns.yyyy;
vec4 h = 1.0 - abs( x ) - abs( y );
vec4 b0 = vec4( x.xy, y.xy );
vec4 b1 = vec4( x.zw, y.zw );
vec4 s0 = floor( b0 ) * 2.0 + 1.0;
vec4 s1 = floor( b1 ) * 2.0 + 1.0;
vec4 sh = -step( h, vec4( 0.0 ) );
vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;
vec3 p0 = vec3( a0.xy, h.x );
vec3 p1 = vec3( a0.zw, h.y );
vec3 p2 = vec3( a1.xy, h.z );
vec3 p3 = vec3( a1.zw, h.w );
vec4 norm = taylorInvSqrt( vec4( dot( p0, p0 ), dot( p1, p1 ), dot( p2, p2 ), dot( p3, p3 ) ) );
p0 *= norm.x; p1 *= norm.y;
p2 *= norm.z; p3 *= norm.w;
vec4 m = max( 0.6 - vec4( dot( x0, x0 ), dot( x1, x1 ), dot( x2, x2 ), dot( x3, x3 ) ), 0.0 );
m = m * m;
return 42.0 * dot( m*m, vec4( dot( p0, x0 ), dot( p1, x1 ),
dot( p2, x2 ), dot( p3, x3 ) ) ); }
每帧图像渲染
java
var speeds=[250,250,250,300,350,500];
var prevTime = Date.now();
var len=0;
function render() {
var delta = clock.getDelta();
var time = Date.now();
for (var i=0;i<morphs.length;i++){
morphs[i].update( ( time - prevTime ) * 0.001 );
amins[i].position.x=(amins[i].position.x+speeds[i]*0.015);
if(amins[i].position.x>(SCREEN_WIDTH+500))
amins[i].position.x=-2500 - Math.random() * 500;
}
len++;
鸟群的初始化
java
var Boid = function() {
var vector = new THREE.Vector3(),
_acceleration, _width = 500, _height = 500, _depth = 200, _goal, _neighborhoodRadius = 100,
_maxSpeed = 4, _maxSteerForce = 0.1, _avoidWalls = false;
this.position = new THREE.Vector3();
this.velocity = new THREE.Vector3();
_acceleration = new THREE.Vector3();
this.setGoal = function ( target ) {
_goal = target; };
this.setAvoidWalls = function ( value ) {
_avoidWalls = value; };
this.setWorldSize = function ( width, height, depth ) {
_width = width;
_height = height;
_depth = depth; };
this.run = function ( boids ) {
if ( _avoidWalls ) {
vector.set( - _width, this.position.y, this.position.z );
vector = this.avoid( vector );
vector.multiplyScalar( 5 );
_acceleration.add( vector );
vector.set( _width, this.position.y, this.position.z );
vector = this.avoid( vector );
vector.multiplyScalar( 5 );
_acceleration.add( vector );
vector.set( this.position.x, - _height, this.position.z );
vector = this.avoid( vector );
vector.multiplyScalar( 5 );
_acceleration.add( vector );
vector.set( this.position.x, _height, this.position.z );
vector = this.avoid( vector );
vector.multiplyScalar( 5 );
_acceleration.add( vector );
vector.set( this.position.x, this.position.y, - _depth );
vector = this.avoid( vector );
vector.multiplyScalar( 5 );
_acceleration.add( vector );
vector.set( this.position.x, this.position.y, _depth );
vector = this.avoid( vector );
vector.multiplyScalar( 5 );
_acceleration.add( vector ); }
if ( Math.random() > 0.5 ) { this.flock( boids );}
this.move();};
this.flock = function ( boids ) {
if ( _goal ) {
_acceleration.add( this.reach( _goal, 0.005 ) ); }
_acceleration.add( this.alignment( boids ) );
_acceleration.add( this.cohesion( boids ) );
_acceleration.add( this.separation( boids ) ); };
this.move = function () {
this.velocity.add( _acceleration );
var l = this.velocity.length();
if ( l > _maxSpeed ) {
this.velocity.divideScalar( l / _maxSpeed ); }
this.position.add( this.velocity );
_acceleration.set( 0, 0, 0 ); };
3.1.4 效果图示
登录注册页背景效果
首页背景效果
管理员登录背景效果
3.2 用户登录
3.2.1 数据设计
逻辑结构设计
实现用户登录需要用户先进行注册,注册的唯一标识为手机号码,手机号码验证可以先判断是否该号码已注册或者号码格式合理,如果可以注册,况且密码两次校验正确,则滑动滑块进行验证。验证成功则注册成功可以登录。
登录时密码错误或者是账号错误都会进行提醒,忘记密码则能去找回页面找回,找回方式为接收往该注册手机上发送的密码,如果验证正确,则可以重新设置新的密码,验证通过后再次登录。
如果用户出现某种特殊违法行为或不道德行为,管理员可以在线对其账号信息删除,或者进行用户的信息修改,管理员查看用户信息时采用分页方式来方便查询。
存储结构设计
用户的登录需要记录用户的手机号码作为唯一性标识,在忘记密码的时候需要依次根据该标识来找回密码。用户的注册后默认金币数量为200,如果使用完需要再行现金充值或者留言投稿等行为赚取金币。
用户的注册后拥有默认头像和默认的未知性别,已下载的资料文件也默认为空。
3.2.2 相关ajax实现
注册
javascript
function myonblur(){
var tell=$("#tell").val();
if(tell==""){
$("#yizhuce").html("号码不能为空");
}
else{
$.ajax({
type : "GET",
url : "<%=request.getContextPath()%>/domyselet",
data:{ "tell":tell, },
async : true,
success : function(data, textStatus, jqXHR) {
if(data=="yes"){
$("#yizhuce").html("此号码已被占用");
}else if(data=="no"){
$("#yizhuce").html("号码可用");
}else{
$("#yizhuce").html("");
} },
error:function(jqXHR, textStatus, errorMs){
$("#yizhuce").html(errorMs);
} });
} }
登录
javascript
function myonblur(){
var tell=$("#tell").val();
if(tell==""){
$("#yizhuce").html("号码不能为空"); }
else{
$.ajax({
type : "GET",
url : "<%=request.getContextPath()%>/domyselet",
data:{ "tell":tell, },
async : true,
success : function(data, textStatus, jqXHR) {
if(data=="no"){
$("#yizhuce").html("号码不存在");
}else{ $("#yizhuce").html(""); } },
error:function(jqXHR, textStatus, errorMs){
$("#yizhuce").html(errorMs); } }); } }
function sub(){
var tell=$("#tell").val();
var pass=$("#pass").val();
$.ajax({
type : "GET",
url : "<%=request.getContextPath()%>/dologin",
data:{
"tell":tell,
"pass":pass,
},
async : true,
success : function(data, textStatus, jqXHR) {
if(data=="ok"){
alert("登录成功");
window.location.href="show.jsp";
}else{
alert("密码错误");
} },
error:function(jqXHR, textStatus, errorMs){
$("#yizhuce").html(errorMs);
} });
}
分页
3.1.3 流程图
3.3 资源文件
3.3.1 数据设计
逻辑结构设计
管理员可以添加各种类型的资源,添加时系统默认后缀为该表名的首字母,添加后的下载数量默认为0,当文件上传后自动检测上传文件的文件大小,文件格式。修改资源只能修改名称,售价和分类,售价为number类型。
当用户想要下载某个资源时,系统会进行判断是否该用户已登录,如果没有登录,则跳转到登录界面,如果已登录,那么系统会根据用户信息和当前商品的信息尝试扣费操作,这时如果用户的金币余额不够支付当前资源将会返回错误信息,如果余额足够,用户的点击操作会触动下载事件资源开始下载资源,下载后的资源保存在浏览器的默认地址中。下载资源后数据库会对目前商品的下载数量进行加一的更新操作,同时,该资源的编号也会作为标记加到用户的下载资源字段后,每个资源都只记录编号,因为可以从编号的首字母找到资源的所在表;每个编号之间使用“,”隔开。
在用户需要在资料界面中查看已下载资源时,再把字段分隔开来进行显示,同时直接不扣费下载而不用系统再次辨认。
由于网站信息的不断扩大,对每个表内的文件都使用分页功能以方便查看,分页格式可使用传参的方式每页只显示十条信息。
存储结构设计
由于不同类型的资源大小等属性的不同,为了方便查询和展示,将所有文件分为四类,分别存入四个表,表中资源的编号作为主键具有唯一性,此外价格地址大小格式等也占据一定的字节空间,添加下载数量字段使下载用户更加了解每个文件的热度,用户每下载一次该文件则数量加一,资源的价格和下载数量设置为整型。资源的展示图片方便用户更直观得了解到资源的表现。
管理员上传文件可以选择上传文件的类型,属性,名称和售价,其他格式和大小信息由系统自行判断,且规定上传文件的最大为100M,最大请求值为150M,内存临界值为3M。
3.3.2 代码描述
在用户提交下载信息时用ajax进行提交申请,在servlet界面中首先判断是否已下载,如果是,那么直接更新数据库中文件的下载数量,返回更新后的下载数量,ajax接收后更当前页面内记录下载数量的div的显示内容。如过未下载过,则先去判断用户余额是否足够,如果不够,返回空值,显示界面接收后弹出提示对应对话框;如果余额足够,则继续更新用户信息中的已下载字段内容,然后再进行更新数据库文件下载数量的操作。
在管理员实现资源文件的添加时接收表单提交的所有信息,迭代表单数据,判断是普通的表单信息还是文件信息,如果是普通信息,那么获取名称和值,如果是文件信息,记录压缩文件的类型和大小,然后一起计入数据库。
ajax代码实现
javascript
function submit(){
var id = $("#id").html();
var sort = $("#sort").html();
var num = $("#num").html();
var jiage=$("#jiage").html();
var dizhi= $("#dizhi").html();
var play=$("#playnum").html();
console.log(id);
$.ajax({
type : "GET",
url : "<%=request.getContextPath()%>/doreduce",
data:{
"id":id,
"sort":sort,
"num":num,
"jiage":jiage
},
async : true,
success : function(data, textStatus, jqXHR) {
if(data==""){
var con;
con=confirm("金币不足,去赚钱?"); //在页面上弹出对话框
if(con==true){
window.location.href="contact.jsp";
}
}else if(data=="error"){
alert("发生错误");
}else{
window.location.href=dizhi;
$("#playnum").html("下载数目:"+data);
} },
error:function(jqXHR, textStatus, errorMs){
alert("error!");
} });}
servlet关键代码实现
java
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
String id= request.getParameter("id");
String sort= request.getParameter("sort");
String num= request.getParameter("num");
System.out.println(num);
int numInteger=Integer.parseInt(num);
String tell=(String)request.getSession().getAttribute("id");
String jiage=request.getParameter("jiage");
int jiageInteger=Integer.parseInt(jiage);
int n=1;
n*=updatehuiyuan(tell, jiageInteger, sort, id);
if(n>0){
n*=updatemoxing(id, sort, numInteger+1);}
if(n>0){ out.print(numInteger+1); }
else if(n<0){ out.print("error");}
else { out.print(""); } }
/**
* 模型的下载数量加一
* @param id,表示模型的id号码
* @param sort,表示所在表的名称
* @param num,表示该模型原有的数量
* @return 是否成功更新
*/
public int updatemoxing(String id,String sort,Integer num) {
moxingservice moxingservice1=new moxingservice();
int m=moxingservice1.updatenum(sort, id, num);
return m;
}
/***
* 用户的信息更新,用户的金币减去一定数量,用户的已下载加入
* @param tell 电话号码
* @param jiage 金币价格
* @param sort 模型所在表信息
* @param id 模型id
*/
public int updatehuiyuan(String tell,Integer jiage,String sort,String id) {
huiyuanservice huiyuanservice1=new huiyuanservice();
String downString=huiyuanservice1.selectdownload(tell);
String [] sp=downString.split(",");
for(int i=1;i<sp.length;i++){
if(sp[i].equals(id)){
return 1; }
}
if(huiyuanservice1.huafei(tell, jiage)>0){//金币足够,余额变化
if(huiyuanservice1.download(tell, sort, id)>0){//已下载的资源变化
return 1;
} }
return 0; }
文件上传相关代码
java
List<FileItem> formItems = upload.parseRequest(request);
if (formItems != null && formItems.size() > 0) {
for (FileItem item : formItems) {
if (!item.isFormField()) {
String fileName = new File(item.getName()).getName();
if(item.getFieldName().equals("picElem")){
String filePath = uploadPath + File.separator + fileName;
File storeFile = new File(filePath);
item.write(storeFile);
picString="images"+ File.separator+fileName;
System.out.println(picString);
}else if(item.getFieldName().equals("fileElem")){
String filePath = uploadPath1 + File.separator + fileName;
File storeFile = new File(filePath);
item.write(storeFile);
fileString="files"+ File.separator+fileName;
System.out.println(fileString);
long daxiao=item.getSize()/1024;
if(daxiao<1024){
daxiaoString=""+daxiao+"k";
}else{
daxiao=(daxiao*10)/1024;
double da=daxiao/10.0;
daxiaoString=""+da+"M"; }
String[] names=fileName.split("\\.");
int i=names.length-1;
geshiString=names[i]; }
}else {
String mynameString=item.getFieldName();
String myvalueString=item.getString();
if(mynameString.equals("sort")){
sort=myvalueString;
}else if(mynameString.equals("id")){
idString=myvalueString;
}else if(mynameString.equals("name")){
name=myvalueString;
}else if(mynameString.equals("jiage")){
jiageString=myvalueString;
jiage=Integer.valueOf(jiageString);
}else if(mynameString.equals("leixing")){
leixing=myvalueString;
}
} } }
3.3.3 流程图
3.4 留言
3.4.1数据设计
逻辑结构设计
用户留言时有相应的登录判断,如果用户未登录,则跳出是否立即登录的提醒,用户可以选择立即登录,也可以选择放弃留言。
用户已成功登录的情况下,留言内容会和用户信息一起提交到网站后台,经过管理员采纳后金币会自动加入到账户余额。
同时,用户可以在资料页查看和删除自己的留言,以及跟踪留言的采纳状态。
存储结构设计
留言的唯一性标志为留言的id,留言id默认为一个随机数。采纳状态只需要一个标记性地数字即可,为了节省数据库内存,默认未标记的采纳字段为空,已采纳的留言采纳字段为“1”。
3.4.2 相关代码
java
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
String huiyuanidString=(String)request.getSession().getAttribute("id");
String themeString=request.getParameter("theme");
String contectString=request.getParameter("contect");
liuyan liuyan1=new liuyan(huiyuanidString, themeString, contectString);
liuyanservice liuyanservice1=new liuyanservice();
int n=liuyanservice1.insert(liuyan1);
if(n!=0){
out.print("您的留言信息已提交");
}else {
out.print("留言提交失败!");
}
3.4.3 流程图
3.5投稿
3.5.1数据设计
逻辑结构设计
用户投稿时有相应的登录判断,如果用户未登录,则跳出是否立即登录的提醒,用户可以选择立即登录,也可以选择放弃投稿。
如果用户成功登录,那么用户需要添加投稿文件的名称及描述,也可以选填文件的推荐分类。上传相关照片和资源文件,提交后则发布到后台,默认状态为未采纳,由管理员采纳以后,状态更新为已采纳,投稿的用户账户金额更新,用户投稿后可以在自己的资料页查看投稿内容和投稿状态,但是无法再次修改和删除。
存储结构设计
为了使投稿内容更加清晰,可以选填文件的描述和分类,投稿的唯一性标记则是随机数组成的投稿id,采纳字段设置为空或一定的字符串,如果为空,代表未采纳,如果非空,用户所获益的值即存储在该采纳字段中,且指定上传的文件大小规定最大100M,最大请求值为150M,内存临界值为3M。
3.5.2 算法描述
通过导入common-fileupload和common-io两个包来实现文件的上传,使用file类型的input实现打开计算机中的本地文件,form的enctype的值设为"multipart/form-data",将上传路径设置为绝对路径来避免文件发布到tomcat的临时文件中而重启的消失。读取form内的每个input对象时判断该对象是file类型的还是普通的输入框类型,判断后如果是file类型,则去提交,否则提取出文件的name和value值,然后将value进行数据库的更新操作。
为了方便将文件选择框进行css美化,使用两个input类型的显示对象,分别设为button和text类型,添加点击事件。
form
```html
<a href="javascript:void(0);"<% if(name==null||name.equals("")){ out.print("onclick='gologin()'"); }else{ out.print("onclick='submit()'"); } %>class="B78_0fcc_cc9de76 default-button">提交 ```
js
java
function submit(){$("#file").submit();}
function gologin(){
var con;
con=confirm("还没有登录,现在登录?"); //在页面上弹出对话框
if(con==true){
window.location.href="login.jsp";
}}
function me(){
document.getElementById("picElem").click();}
function me1(){
document.getElementById("fileElem").click();}
文件上传
java
try {
List<FileItem> formItems = upload.parseRequest(request);
if (formItems != null && formItems.size() > 0) {
// 迭代表单数据
for (FileItem item : formItems) {
// 处理不在表单中的字段
if (!item.isFormField()) {
String fileName = new File(item.getName()).getName();
if(item.getFieldName().equals("picElem")){
String filePath = uploadPath + File.separator + fileName;
File storeFile = new File(filePath);
// 在控制台输出文件的上传路径
item.write(storeFile);
picString="images"+ File.separator+fileName;
}else if(item.getFieldName().equals("fileElem")){
String filePath = uploadPath1 + File.separator + fileName;
File storeFile = new File(filePath);
// 在控制台输出文件的上传路径
item.write(storeFile);
fileString="files"+ File.separator+fileName; }
System.out.println(item.getFieldName());
}else {
String mynameString=item.getFieldName();
String myvalueString=item.getString();
if(mynameString.equals("name")){
nameString=myvalueString;
}else if(mynameString.equals("leixing")){
leiString=myvalueString;
}else if(mynameString.equals("miaoshu")){
miaoshuString=myvalueString;
} } } }
} catch (Exception ex) {
request.setAttribute("errors:",
"cuowuxinxi: " + ex.getMessage()); }
if(fileString!=null&&picString!=null){
System.out.println("OK");
submit(request, response,fileString,picString,nameString,leiString,miaoshuString);
}
3.5.3 流程图
3.7 数据库设计
3.7.1 数据设计
背景
名称 | 说明 |
---|---|
数据库名称 | shixun |
数据库用户名 | root |
密码 | root |
数据库系统 | MySQL 5.0 |
客户端连接工具 | SQLyog-64bit |
**E-R图 **
存储结构设计
3.7.2 物理设计表汇总
用户
表名 | Huiyuan(会员信息表) | |||
---|---|---|---|---|
列名 | 数据类型(精度范围) | 空/非空 | 约束条件 | 说明 |
Huiyuantell | Varchar(20) | 非空 | 主键 | 会员联系方式 |
Huiyuanpass | Varchar(50) | 非空 | 会员密码 | |
Huiyuanname | Varchar(50) | 非空 | 会员名称 | |
Huiyuanbi | Int | 非空 | 会员金币余额 | |
Huiyuanziyuan | Varchar(300) | 已下载资源 | ||
Huiyuansex | Varchar(8) | 性别 |
模型文件
表名 | moxing(模型表) | |||
---|---|---|---|---|
列名 | 数据类型(精度范围) | 空/非空 | 约束条件 | 说明 |
Moxingid | Varchar(20) | 非空 | 主键 | 模型编号 |
Moxingname | Varchar(50) | 非空 | 模型名称 | |
Moxingjiage | Int | 非空 | 模型价格 | |
Moxingnum | Int | 非空 | 模型下载量 | |
Moxingpic | Varchar(50) | 非空 | 模型展示图片 | |
Moxingdizhi | Varchar(50) | 非空 | 模型地址 | |
Moxinggeshi | Varchar(20) | 非空 | 模型格式 | |
Moxingleixing | Varchar(10) | 非空 | 模型类型 | |
Moxingdaxiao | Varchar(10) | 非空 | 模型大小 |
动画文件
表名 | donghua(动画表) | |||
---|---|---|---|---|
列名 | 数据类型(精度范围) | 空/非空 | 约束条件 | 说明 |
Moxingid | Varchar(20) | 非空 | 主键 | 模型编号 |
Moxingname | Varchar(50) | 非空 | 模型名称 | |
Moxingjiage | Int | 非空 | 模型价格 | |
Moxingnum | Int | 非空 | 模型下载量 | |
Moxingpic | Varchar(50) | 非空 | 模型展示图片 | |
Moxingdizhi | Varchar(50) | 非空 | 模型地址 | |
Moxinggeshi | Varchar(20) | 非空 | 模型格式 | |
Moxingleixing | Varchar(10) | 非空 | 模型类型 | |
Moxingdaxiao | Varchar(10) | 非空 | 模型大小 |
全景文件
表名 | quanjing(全景表) | |||
---|---|---|---|---|
列名 | 数据类型(精度范围) | 空/非空 | 约束条件 | 说明 |
Moxingid | Varchar(20) | 非空 | 主键 | 模型编号 |
Moxingname | Varchar(50) | 非空 | 模型名称 | |
Moxingjiage | Int | 非空 | 模型价格 | |
Moxingnum | Int | 非空 | 模型下载量 | |
Moxingpic | Varchar(50) | 非空 | 模型展示图片 | |
Moxingdizhi | Varchar(50) | 非空 | 模型地址 | |
Moxinggeshi | Varchar(20) | 非空 | 模型格式 | |
Moxingleixing | Varchar(10) | 非空 | 模型类型 | |
Moxingdaxiao | Varchar(10) | 非空 | 模型大小 |
网站文件
表名 | wangzhan(网站表) | |||
---|---|---|---|---|
列名 | 数据类型(精度范围) | 空/非空 | 约束条件 | 说明 |
Moxingid | Varchar(20) | 非空 | 主键 | 模型编号 |
Moxingname | Varchar(50) | 非空 | 模型名称 | |
Moxingjiage | Int | 非空 | 模型价格 | |
Moxingnum | Int | 非空 | 模型下载量 | |
Moxingpic | Varchar(50) | 非空 | 模型展示图片 | |
Moxingdizhi | Varchar(50) | 非空 | 模型地址 | |
Moxinggeshi | Varchar(20) | 非空 | 模型格式 | |
Moxingleixing | Varchar(10) | 非空 | 模型类型 | |
Moxingdaxiao | Varchar(10) | 非空 | 模型大小 |
留言
表名 | liuyan(留言表) | |||
---|---|---|---|---|
列名 | 数据类型(精度范围) | 空/非空 | 约束条件 | 说明 |
Liuyanid | Varchar(20) | 非空 | 主键 | 留言编号 |
huiyuantell | Varchar(20) | 非空 | 外键 | 会员联系方式 |
liuyantheme | Varchar(50) | 非空 | 留言主题 | |
liuyancontent | Varchar(200) | 非空 | 留言内容 | |
caina | Vachar(5) | 采纳情况 |
投稿
表名 | tougao(投稿表) | |||
---|---|---|---|---|
列名 | 数据类型(精度范围) | 空/非空 | 约束条件 | 说明 |
tougaoid | Varchar(50) | 非空 | 主键 | 投稿编号 |
Huiyuantell | Varchar(20) | 非空 | 外键 | 会员联系方式 |
wenjianname | Varchar(50) | 非空 | 模型名称 | |
wenjianmiaoshu | Varchar(50) | 非空 | 模型描述 | |
wenjianleixing | Varchar(50) | 非空 | 模型类型 | |
wenjianpic | Varchar(50) | 非空 | 模型展示图片 | |
wenjiandizhi | Varchar(50) | 非空 | 文件地址 |
管理员
表名 | guanli(管理员信息表) | |||
---|---|---|---|---|
列名 | 数据类型(精度范围) | 空/非空 | 约束条件 | 说明 |
Membertell | Varchar(20) | 非空 | 主键 | 管理员电话 |
membername | Varchar(20) | 非空 | 管理员名称 | |
pwd | Varchar(20) | 非空 | 管理员密码 |
第4章 系统测试
4.1 用户测试
4.1.1 登录注册
验证登录情况的时候,可分为以下几种情况进行测试:
-
登录号码为空,提示号码不能为空
-
登录电话号码为未登录的号码,这时提示内容为不存在该号码
-
登录电话正确但是密码错误,提示内容为密码错误
-
密码电话均正确,成功登录,同时提交该用户头像和昵称到网站首页
用户账号为空提示
用户账号错误提示
用户密码错误提示
成功登录后界面显示
4.1.2 修改资料
-
修改用户的昵称和性别资料,修改成功后用户资料页内容改变,并且上方地址栏的用户名称也改变
-
修改用户的头像,用户在本地上传图片到项目,长传后图片可以在项目中找到且可以及时显示,确认修改后用户资料页内容改变,并且上方地址栏的用户头像也改变
用户修改资料页面
用户修改资料成功后页面
用户上传头像页面
4.1.3 留言
用户在联系我们的界面进行留言,留言后可以显示在资料页。
用户留言图
4.1.4 投稿
用户在联系我们的界面进行投稿,本地上传后可以添加到数据库,在个人资料页面可以查看。
用户上传资料图
4.1.5 文件下载
-
用户在金币不足的情况下下载已下载过的文件,预测结果:成功下载,且数据库中改文件的下载数量不加一
-
用户在金币不足的情况下下载未下载过的文件,预测结果:成功失败,弹出提示去赚钱的对话框
-
用户在金币充足的情况下下载已下载过的文件,预测结果:成功下载,且数据库内用户的金币数量没有变化,同时数据库中改文件的下载数量加一
-
用户在金币充足的情况下下载未下载过的文件,预测结果:成功下载,且用户的金币数量减去了相应文件的金额,同时数据库中改文件的下载数量加一
重复下载已下载资料
金币不足提示图
金币充足下载图
4.2管理员测试
4.2.1 修改用户
-
登录后的管理员可以进行会员查看工作
-
可以进行会员修改操作
-
可以进行会员删除操作
-
可以进行会员添加操作(会员的添加操作会使用ajax来进行号码的判断,是否该号码已被注册)
管理员查看所有用户
管理员修改用户
删除用户成功提示
管理员添加用户
4.2.2资源文件管理
-
管理员可以查看所有的资源信息,并且可以正确分页
-
可以添加新的资源文件,添加后检测得到的文件类型和大小正确
-
可以删除不需要的文件
-
可以正确修改文件的名称,价格,分类字段
管理员查看所有模型类资源
管理员添加资源
管理员修改资源
管理员删除资源
4.2.3 留言处理
-
可以查看数据库中的留言
-
采纳留言后数据库内的留言状态也改变
-
可以删除留言
管理员查看所有留言
管理员采纳留言后数据库变化图
管理员删除留言成功图
4.2.4 投稿文件操作
-
可以查看所有用户已经投稿的文件
-
下载投稿的文件
-
删除投稿
-
可以采纳投稿,已注销用户的投稿不能被采纳
管理员查看所有投稿
管理员下载投稿成功图
管理员删除投稿成功图
管理员采纳投稿成功图
总 结
通过本次的上机实训,使我对网站的开发进一步熟练,对MVC开发模式有了更深刻的了解。对页面的设计更加的熟悉,能够使用CSS 对页面进行修饰,使用各种不同的js使页面生动形象功能更加完善,将Servlet, JSP等技术和Tomcat,My Eclipse,MySQL有机结合起来。实现到了3D网页和传统网页的结合,了解到了怎么导入外包实现文件的上传功能,以及对目标文件的属性提取,在查看信息时进行分页处理,学习到了使用ajax来实现数据的提交和返回数据的接收,熟悉了JavaScript在网站开发中的一些重要的操作方法,以及使用frame界面实现子页面和父页面的相互传值控制功能,和session在实验中起到的全局变量的作用储存现登录的用户信息。同时,熟悉了使用jquary和bootstrap来完善界面功能。
本次实训使我们对软件开发的工程思想和实际问题的解决有了更深的理解。实训使我们实现的一个完全的网站的开发加深了我们对javaweb项目开发的了解,增加了我们的经验,老师对我们的指导和评价更使我们明确了网站建设的评价标准和用户需求的关键所在,对网站的安全性也有了一定的了解。这些对于我们来说可能是一个非常有价值的经验。
最后,通过本次实训使我学到很多东西,这样便于今后让我提早进入工作状态。
参考文献
- 基于JAVA的B2C电子商城设计与实现(西安电子科技大学·胡峰)
- 基于SSH架构的个人空间交友网站的设计与实现(北京邮电大学·隋昕航)
- 基于J2EE中EJB组件技术的研究及其在电子商务中的应用(西北大学·陈智罡)
- 电子产品网络购物系统的设计与实现(电子科技大学·李睿)
- 基于J2EE的企业电子商务平台的研究及优化设计(武汉理工大学·金双武)
- 基于JAVA的B2C电子商城设计与实现(西安电子科技大学·胡峰)
- 基于JAVA的B2C电子商城设计与实现(西安电子科技大学·胡峰)
- 中小型企业电商网站架构设计与实现(吉林大学·赵璐)
- 基于PHP和MySQL的网上购物系统设计与实现(电子科技大学·李华明)
- 基于SSM框架的B2C网上商城系统的设计与实现(湖南大学·陈峰)
- 基于SSM框架的B2C网上商城系统的设计与实现(湖南大学·陈峰)
- 中小型企业电商网站架构设计与实现(吉林大学·赵璐)
- 基于SSH架构的个人空间交友网站的设计与实现(北京邮电大学·隋昕航)
- 基于JSP技术的网上购物系统设计与实现(电子科技大学·包敏)
- 网上电器销售系统的设计与实现(吉林大学·荆闯)
本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:毕设客栈 ,原文地址:https://m.bishedaima.com/yuanma/35362.html