留言板功能需求:

1.页面效果如下图所示,应包含留言和管理员回复功能;
2.访客发布和显示只要一个JSP页面,页面最上方是发布内容区域;
3.管理员回复功能由另一个页面实现。
4.页面下方列出已有留言,还需显示提交时间;

5.留言数据存在服务器的数据库中;


留言发布页面board,jsp的核心代码:

<body class="body">

	<center>
	<div class="cen">
		<div class="edit">
			<br><br>
			<font face="Tw Cen MT" color="#665ea9" size="6" align="left">Leave your traces!</font><br><br>
			<!-- 用户输入表单 -->
			<form name="form_submit" action="board.jsp" align="center" method="post">    
				<!-- 用户图标 -->
				<img src="user.png" width="40px" height="40px" align="center">  
				<!-- 用户名输入框 -->
				<input type="text" class="cinput" name="user" placeholder="Username" maxlength="20" οnfοcus="ufocus()"><br>
				<div id="name_id" class="divfont"> </div>
				<!-- 邮箱图标 -->
				<img src="email.png" width="40px" height="40px" align="center"> 
				<!-- 邮箱输入框 -->
				<input type="text" class="cinput" name="email" placeholder="Email" maxlength="20" οnfοcus="efocus()"><br>  			
				<div id="email_id" class="divfont"> </div>
				<!-- 留言输入框 -->
				<textarea type="text" class="ctext" name="saying" placeholder="To say someting..." οnfοcus="sfocus()"></textarea><br> 
				<div id="saying_id" class="divfont"> </div>
				
				<input type="hidden" name="stime" id="time_id" value="">
				<input type="hidden" name="sip" id="ip_id" value="">
				<!-- 提交按钮 -->
				<input type="submit" class="btn_out" value="" name="OK" οnclick="return checksubmit()" οnmοusemοve="this.className='btn_move'" οnmοuseοut="this.className='btn_out'" > 
			</form>	
		</div>

		<%
			//如果用户提交信息 则插入数据库 其中头像为随机
			if(request.getParameter("user")!=null)
			{
				Class.forName("com.mysql.jdbc.Driver");
				Connection conn = DriverManager.getConnection("jdbc:mysql://url??useUnicode=true&characterEncoding=utf-8",用户名,密码);
				Statement stat = conn.createStatement();		
				
				//参数化
				String sql = "INSERT INTO MessageBoard(MDisplay, MIp, MName, MEmail, MTime, MSaying, MImage) VALUES(1,?,?,?,?,?,?)";
				PreparedStatement ps = conn.prepareStatement(sql);
				//随机头像
				int i=new Random().nextInt(10);
				String muser=new String(request.getParameter("user").getBytes("iso-8859-1"),"utf-8");
				String msaying=new String(request.getParameter("saying").getBytes("iso-8859-1"),"utf-8");
				//设置参数
				ps.setString(1,request.getParameter("sip"));
				ps.setString(2,muser);
				ps.setString(3,request.getParameter("email"));
				ps.setString(4,request.getParameter("stime"));
				ps.setString(5,msaying);
				ps.setString(6,"img/head"+i+".png");
				ps.executeUpdate();

				stat.close();
				conn.close();
			}
		%>

		<%      //获取页数
				int pagei=0;
				int maxp=0;
				if(request.getParameter("page")!=null)
					if(request.getParameter("page")!=""){
					String str1=request.getParameter("page");
					Pattern pattern = Pattern.compile("[0-9]*");  
	    			if(pattern.matcher(str1).matches())
	    				pagei=Integer.parseInt(str1);	
				}
Connection conn = DriverManager.getConnection("jdbc:mysql://url?useUnicode=true&characterEncoding=utf-8",用户名,密码);
Statement stat = conn.createStatement();
				//查询总记录数
				String sql1 = "SELECT count(MyId) totalCount FROM MessageBoard WHERE MDisplay=1";
				ResultSet rset = stat.executeQuery(sql1); 
				int rowCount = 0; 
				//获取总记录数
				while(rset.next()) { 
				   rowCount=rset.getInt("totalCount"); 
				}
				maxp=(rowCount-1)/10;	
				 //计算页数						
				if((pagei*10+1)>rowCount)
					pagei=maxp;
		%>
			<input type="hidden" name="getpage" id="getpage_id" value="<%=pagei%>">
			<input type="hidden" name="maxpage" id="maxpage_id" value="<%=maxp%>">
		<%
				pagei*=10;
		%> 

		<div class="board">
			<%	
				// 分页查询 pagei由程序计算生成 不是用户输入 因此不需要参数化	
				String sql = "SELECT Myid, MName, MTime, MSaying, MImage FROM MessageBoard WHERE MDisplay=1 ORDER BY MTime DESC limit "+pagei+" ,10 ";
				ResultSet rs = stat.executeQuery(sql);			
				//把查询结果先保存下来
				List<String> mesIdlist = new ArrayList<String>();
				List<String> mesNamelist = new ArrayList<String>();
				List<String> mesTimelist = new ArrayList<String>();
				List<String> mesSayinglist = new ArrayList<String>();
				List<String> mesImglist = new ArrayList<String>();
				//打印留言信息
				while(rs.next()){
					mesIdlist.add(rs.getString("Myid"));
					mesNamelist.add(rs.getString("MName"));
					mesTimelist.add(rs.getString("MTime"));
					mesSayinglist.add(rs.getString("MSaying"));
					mesImglist.add(rs.getString("MImage"));
				}
				for(int ite=0;ite<mesIdlist.size();ite++){
					String mesId =  mesIdlist.get(ite);
					String mesName = mesNamelist.get(ite);		
					String mesTime = mesTimelist.get(ite);	
					String mesSaying = mesSayinglist.get(ite);
					String mesImg = mesImglist.get(ite);

					mesName=mesName.replaceAll("<","<");
					mesName=mesName.replaceAll(">",">");
					mesName=mesName.replaceAll("\"",""");
					mesName=mesName.replaceAll(" "," ");

					String mesHead = mesSaying.substring(0, 1);
					String mesLast = mesSaying.substring(1);
					mesLast=mesLast.replaceAll("<","<");
					mesLast=mesLast.replaceAll(">",">");
					mesLast=mesLast.replaceAll("\"",""");
					mesLast=mesLast.replaceAll(" "," ");

			%>
					<div class="mandiv">
					<img src="<%=mesImg%>" width="74px" height="74px">
					<%=mesName%>
					</div>
					<div class="sayingdiv"><font size="6"><%=mesHead%></font><%=mesLast%></div>
					<div class="timediv"><%=mesTime%></div>

			<%
				// 查询对应留言回复 mesId由程序计算生成 因此不需要参数化	
				String resql = "SELECT Retext, Rtime FROM ReplyBoard WHERE MyId="+mesId+" ORDER BY Rtime";
				ResultSet res = stat.executeQuery(resql);	
				//打印留言回复
				while(res.next()){
					String mesReply = res.getString("Retext");			
					String mesRtime = res.getString("Rtime");
					mesReply=mesReply.replaceAll("<","<");
					mesReply=mesReply.replaceAll(">",">");
					mesReply=mesReply.replaceAll("\"",""");
					mesReply=mesReply.replaceAll(" "," ");
			%>				
						<div class="commentdiv"><strong>Administrator reply: </strong><%=mesReply%></div>				
						<div class="retimediv"><%=mesRtime%></div>
			<%			
					}
			%>
					<HR>
			<%			
				}
			%>

			<%
				stat.close();
				conn.close();
			%>
			
		</div>
	</div>	
		<input type="text" style="width:950px;visibility:hidden;" >
		<%	
			//分页按钮
			if(pagei!=0){
		%>
		<button id="btn_previous" class="page_out" οnclick="prepage()" οnmοusemοve="this.className='page_move'" οnmοuseοut="this.className='page_out'"><</button>		
		<%
			}else{
		%>
			<button class="page_out" style="visibility:hidden;" >h</button>
		<%
			}
		%>
		<font size="2"><%=pagei/10+1%></font>
		<font size="2">/</font>
		<font size="2"><%=maxp+1%></font>
		<%
			if(pagei/10<maxp){
		%>		
		<button id="btn_next" class="page_out" οnclick="nextpage()" οnmοusemοve="this.className='page_move'" οnmοuseοut="this.className='page_out'">></button>
		<%
			}else{
		%>
			<button class="page_out" style="visibility:hidden;" >h</button>
		<%
			}
		%>
	</center>

</body>





管理员回复页面adm,jsp的核心代码:

<body class="body">

	<center>
	<div class="cen">
		<div class="edit">
			<br><br>
			<font face="Tw Cen MT" color="#665ea9" size="6" align="left">Leave your traces!</font><br><br>
			<!-- 用户输入表单 -->
			<form name="form_submit" action="board.jsp" align="center" method="post">    
				<!-- 用户图标 -->
				<img src="user.png" width="40px" height="40px" align="center">  
				<!-- 用户名输入框 -->
				<input type="text" class="cinput" name="user" placeholder="Username" maxlength="20" οnfοcus="ufocus()"><br>
				<div id="name_id" class="divfont"> </div>
				<!-- 邮箱图标 -->
				<img src="email.png" width="40px" height="40px" align="center"> 
				<!-- 邮箱输入框 -->
				<input type="text" class="cinput" name="email" placeholder="Email" maxlength="20" οnfοcus="efocus()"><br>  			
				<div id="email_id" class="divfont"> </div>
				<!-- 留言输入框 -->
				<textarea type="text" class="ctext" name="saying" placeholder="To say someting..." οnfοcus="sfocus()"></textarea><br> 
				<div id="saying_id" class="divfont"> </div>
				
				<input type="hidden" name="stime" id="time_id" value="">
				<input type="hidden" name="sip" id="ip_id" value="">
				<!-- 提交按钮 -->
				<input type="submit" class="btn_out" value="" name="OK" οnclick="return checksubmit()" οnmοusemοve="this.className='btn_move'" οnmοuseοut="this.className='btn_out'" > 
			</form>	
		</div>

		<%
			//如果用户提交信息 则插入数据库 其中头像为随机
			if(request.getParameter("user")!=null)
			{
				Class.forName("com.mysql.jdbc.Driver");
				Connection conn = DriverManager.getConnection("jdbc:mysql://url?useUnicode=true&characterEncoding=utf-8",用户名,密码);
				Statement stat = conn.createStatement();		
				
				//参数化
				String sql = "INSERT INTO MessageBoard(MDisplay, MIp, MName, MEmail, MTime, MSaying, MImage) VALUES(1,?,?,?,?,?,?)";
				PreparedStatement ps = conn.prepareStatement(sql);
				//随机头像
				int i=new Random().nextInt(10);
				String muser=new String(request.getParameter("user").getBytes("iso-8859-1"),"utf-8");
				String msaying=new String(request.getParameter("saying").getBytes("iso-8859-1"),"utf-8");
				//设置参数
				ps.setString(1,request.getParameter("sip"));
				ps.setString(2,muser);
				ps.setString(3,request.getParameter("email"));
				ps.setString(4,request.getParameter("stime"));
				ps.setString(5,msaying);
				ps.setString(6,"img/head"+i+".png");
				ps.executeUpdate();

				stat.close();
				conn.close();
			}
		%>

		<%      //获取页数
				int pagei=0;
				int maxp=0;
				if(request.getParameter("page")!=null)
					if(request.getParameter("page")!=""){
					String str1=request.getParameter("page");
					Pattern pattern = Pattern.compile("[0-9]*");  
	    			if(pattern.matcher(str1).matches())
	    				pagei=Integer.parseInt(str1);	
				}	
				Connection conn = DriverManager.getConnection("jdbc:mysql://url?useUnicode=true&characterEncoding=utf-8",用户名,密码);
				Statement stat = conn.createStatement();
				//查询总记录数
				String sql1 = "SELECT count(MyId) totalCount FROM MessageBoard WHERE MDisplay=1";
				ResultSet rset = stat.executeQuery(sql1); 
				int rowCount = 0; 
				//获取总记录数
				while(rset.next()) { 
				   rowCount=rset.getInt("totalCount"); 
				}
				maxp=(rowCount-1)/10;	
				 //计算页数						
				if((pagei*10+1)>rowCount)
					pagei=maxp;
		%>
			<input type="hidden" name="getpage" id="getpage_id" value="<%=pagei%>">
			<input type="hidden" name="maxpage" id="maxpage_id" value="<%=maxp%>">
		<%
				pagei*=10;
		%> 

		<div class="board">
			<%	
				// 分页查询 pagei由程序计算生成 不是用户输入 因此不需要参数化	
				String sql = "SELECT Myid, MName, MTime, MSaying, MImage FROM MessageBoard WHERE MDisplay=1 ORDER BY MTime DESC limit "+pagei+" ,10 ";
				ResultSet rs = stat.executeQuery(sql);			
				//把查询结果先保存下来
				List<String> mesIdlist = new ArrayList<String>();
				List<String> mesNamelist = new ArrayList<String>();
				List<String> mesTimelist = new ArrayList<String>();
				List<String> mesSayinglist = new ArrayList<String>();
				List<String> mesImglist = new ArrayList<String>();
				//打印留言信息
				while(rs.next()){
					mesIdlist.add(rs.getString("Myid"));
					mesNamelist.add(rs.getString("MName"));
					mesTimelist.add(rs.getString("MTime"));
					mesSayinglist.add(rs.getString("MSaying"));
					mesImglist.add(rs.getString("MImage"));
				}
				for(int ite=0;ite<mesIdlist.size();ite++){
					String mesId =  mesIdlist.get(ite);
					String mesName = mesNamelist.get(ite);		
					String mesTime = mesTimelist.get(ite);	
					String mesSaying = mesSayinglist.get(ite);
					String mesImg = mesImglist.get(ite);

					mesName=mesName.replaceAll("<","<");
					mesName=mesName.replaceAll(">",">");
					mesName=mesName.replaceAll("\"",""");
					mesName=mesName.replaceAll(" "," ");

					String mesHead = mesSaying.substring(0, 1);
					String mesLast = mesSaying.substring(1);
					mesLast=mesLast.replaceAll("<","<");
					mesLast=mesLast.replaceAll(">",">");
					mesLast=mesLast.replaceAll("\"",""");
					mesLast=mesLast.replaceAll(" "," ");

			%>
					<div class="mandiv">
					<img src="<%=mesImg%>" width="74px" height="74px">
					<%=mesName%>
					</div>
					<div class="sayingdiv"><font size="6"><%=mesHead%></font><%=mesLast%></div>
					<div class="timediv"><%=mesTime%></div>

			<%
				// 查询对应留言回复 mesId由程序计算生成 因此不需要参数化	
				String resql = "SELECT Retext, Rtime FROM ReplyBoard WHERE MyId="+mesId+" ORDER BY Rtime";
				ResultSet res = stat.executeQuery(resql);	
				//打印留言回复
				while(res.next()){
					String mesReply = res.getString("Retext");			
					String mesRtime = res.getString("Rtime");
					mesReply=mesReply.replaceAll("<","<");
					mesReply=mesReply.replaceAll(">",">");
					mesReply=mesReply.replaceAll("\"",""");
					mesReply=mesReply.replaceAll(" "," ");
			%>				
						<div class="commentdiv"><strong>Administrator reply: </strong><%=mesReply%></div>				
						<div class="retimediv"><%=mesRtime%></div>
			<%			
					}
			%>
					<HR>
			<%			
				}
			%>

			<%
				stat.close();
				conn.close();
			%>
			
		</div>
	</div>	
		<input type="text" style="width:950px;visibility:hidden;" >
		<%	
			//分页按钮
			if(pagei!=0){
		%>
		<button id="btn_previous" class="page_out" οnclick="prepage()" οnmοusemοve="this.className='page_move'" οnmοuseοut="this.className='page_out'"><</button>		
		<%
			}else{
		%>
			<button class="page_out" style="visibility:hidden;" >h</button>
		<%
			}
		%>
		<font size="2"><%=pagei/10+1%></font>
		<font size="2">/</font>
		<font size="2"><%=maxp+1%></font>
		<%
			if(pagei/10<maxp){
		%>		
		<button id="btn_next" class="page_out" οnclick="nextpage()" οnmοusemοve="this.className='page_move'" οnmοuseοut="this.className='page_out'">></button>
		<%
			}else{
		%>
			<button class="page_out" style="visibility:hidden;" >h</button>
		<%
			}
		%>
	</center>

</body>


结果展示:

访客发布和显示页面:

java mvc 留言板 javaee留言板_java mvc 留言板

管理员回复页面:

java mvc 留言板 javaee留言板_java mvc 留言板_02


技术要点总结:

1、PreparedStatement参数化传值进行SQL操作,防止恶意用户的SQL注入。

2、分页查询(limit)可减轻数据库的负载以及web页面在传输时所占的带宽。

3、对于提交内容的特殊字符进行转换,以防止HTML或JS攻击。

4、对于中文字符,需要对其进行转码操作。

5、项目大了,纯JSP的页面显然显得过于臃肿,还是建议使用MVC模式或者其他框架模块化编写。