struts2 实现简单BBS功能

以下是马老师教学内容。工程目标:做BBS后台管理中,对帖子目录的管理,包括添加,更新,删除,列帖子的4个功能,可以发现哈,这也数据库的增删改查是正好对应的,所以实现起来其实很简单。首先确定开发流程:

  1. 建立前台界面,用ext实现(此为官方建议流程,但我觉得1跟2可以换过来)
  2. 创建struts.xml文件-----内容包括确定namespace,package,action,result各自名称,以便较好的使用通配符,可以基本完成通路,包括前台+struts的框架运行,所有action ,jsp都依照计划可以走通。内部也有流程哈:1)写个上篇博客一样简单的框架,jsp,struts.xml,action,web.xml这些东西           2)复杂化struts.xml文件   3)完成复杂strtus.xml文件包含的action ,jsp 内容,方法都为空的,只是为了走通路;    4) 加上上面的ext前台,一起运行,走通category-list一条路  5) 由jsp的页面链接走通其他的路:category-add,category-update,category-delete。页面返回的内容也都是想test返回的页面一样,为一句话即可。
  3. 建Model层
  4. 建立DB层
  5. 建立Service层
  6. 与action连起来,将基本为空的方法用service实现,慢慢跑通即可。

具体操作:

  • ext页面为借鉴的别人的,这就不说了,工程中要添加ext的包,不然这个页面运行不起来
  • struts的搭建: 在上一个博客那边说啦简单的框架的搭建,这边也是一样,只是在其基础上添加写东西,一下为struts.xml文件内容,文件头部分的东西就省了:

<struts>
 <constant name="struts-devMode" value="true"></constant>//还是前面的那个简单工程的东西哈
<package name="front" namespace="/" extends="struts-default">
<action name="test" class="com.gao.action.TestAction">
<result>/test.jsp</result>
  </action></package>
 <package name="admin" namespace="/admin" extends="struts-default">//admin表示后台,此处action用了通配符哦,这个用着还挺爽的,第一个※为action名字,第二个为action中对应方法的名字,这个action name返回后,对应的result为action的名字,加上“-”再加上方法的页面,话说,coding中约定大于配置,所以,jsp的约定其实就是鼎城这样的,配置起来就相当简单了!
<action name="*-*" class="com.gao.action.{1}Action" method="{2}">
  <result>/admin/{1}-{2}.jsp</result>//返回的页面
  <result name="input">/admin/{1}-{2}.jsp</result>//有input返回的界面,此处为addInput,updateInput对应返回的界面,界面实现用户对帖子的增加,或者更新,最后以form的形式提交Category-add,Category-update两个action 做处理,再返回到上一个result。其实这两个可以合并,但是为了更清晰,所以就没有合并。
  </action></package></struts>

  • 对应struts.xml文件,实现action 和jsp页面
  1. action的实现:新建CategoryAction文件,其中包括list,update,add,delete,updateInput,addInput 6个空方法,returnSUCCESS,最后两个return INPUT即可。
  2. jsp 实现:新建6个jsp 文件,分别为Category-list,Category-add, Category-delete,Category-update,Category-addInput,Category-updateInput 6个文件,分别对应action中的6个方法的返回,页面内容可以只为个子的页面名称;注意连接关系,其中add,delete,update都是连接在list页面上的,不过,这是最简单的版本,所以不加也没问题。
  3. 跑通下。

基于以上内容,加上ext前台界面,跑通下!

  • 建立Model

Category类,其中包括int id,String name,String description及其set,get方法,此处若不写category的空构造方法也没事,对这个问题,有点迷糊,不知道什么时候要写,什么时候可以不写;

  • 建立DB

跟上卖弄一样简单。SQL语句如下“

create database bbs;

use bbs;

create table _category (id int primary key auto_increment,name varchar(50),description varchar(200));

即可。

  • 建Service

这个相对复杂点,在建这个之前,要建个DB的辅助类:DB类,其中包括的方法有:createConn(),prepare(),close().主要是跟DB打交道,并且吧try,catch这些东西都包括进来了,比较方便;贴出代码开看看,close就不写上来了,这里有rs,ps,conn的3个close:

public static Connection createConn() {//通常为static ,不然其他类不好调用;
Connection conn = null;
  try {Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(
"jdbc:mysql://localhost/bbs2009","root", "gao");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}

public static PreparedStatement prepare(Connection conn, String sql) {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return ps;
}

然后实现Service类了。方法有:list,add,update,delete,调用DB类中的方法实现,不难,现在用的方法是,画个图出来,按照图直接写代码,不然脑袋真是记不住啊。。。

这里还有个就是,有delete,deleteById(id)两个方法,实现了两种方式,最好的方式是delete调用deleteById,属于service 提供了更好的接口给别人,如果别人要用你这个包得话,可基于SERVICE这个方法做二次开发。还有一个loadById(id)使用在updateInput中的,为了在更新的时候把原来的内容由ID取出来,放在输入框中,起提示作用;

其实最主要的就是SQL语句,DB类方法的使用,写过一遍以后就会觉得还挺简单的,因为都是一层不变的东西,会了这个类似的你就都会了,代码如下:

package com.gao.service;//放在service包下了

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.gao.model.Category;//模型包
import com.gao.util.DB;//DB辅助类包
public class CategoryService {


 public void add(Category c) {  //add方法
Connection conn = DB.createConn();
String sql = "insert into _category values(null, ?, ?)";
PreparedStatement ps = DB.prepare(conn, sql);

try {
ps.setString(1, c.getName());
ps.setString(2, c.getDescription());
ps.executeUpdate();

} catch (SQLException e) {
e.printStackTrace();
}
DB.close(ps);
DB.close(conn);

}

public void update(Category c) {
Connection conn = DB.createConn();
String sql = "update _category set name=?,description=? where id=?";
PreparedStatement ps = DB.prepare(conn, sql);

try {
ps.setString(1, c.getName());
ps.setString(2, c.getDescription());
ps.setInt(3, c.getId());

ps.executeUpdate();

} catch (SQLException e) {
e.printStackTrace();
}
DB.close(conn);
DB.close(ps);

}

public void delete(Category c) {
deleteById(c.getId());
}

public void deleteById(int id) {
Connection conn = DB.createConn();
String sql = "delete from _category where id=?";
PreparedStatement ps = DB.prepare(conn, sql);
try {
ps.setInt(1, id);
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
DB.close(ps);
DB.close(conn);
}

public List<Category> list() {
List<Category> categories = new ArrayList<Category>();
Category c = null;
Connection conn = DB.createConn();
String sql = "select * from _category";
PreparedStatement ps = DB.prepare(conn, sql);

ResultSet rs;
try {
rs = ps.executeQuery();
while (rs.next()) {
c = new Category();
c.setId(rs.getInt("id"));
c.setName(rs.getString("name"));
c.setDescription(rs.getString("description"));
categories.add(c);
}
} catch (SQLException e) {
e.printStackTrace();
}
DB.close(ps);
DB.close(conn);

return categories;
}

public Category loadById(int id) {
Connection conn = DB.createConn();
Category c = null;
String sql = "select * from _category where id=?";
PreparedStatement ps = DB.prepare(conn, sql);
ResultSet rs = null;
try {
ps.setInt(1, id);
rs = ps.executeQuery();
while (rs.next()) {
c = new Category();
c.setId(id);
c.setName(rs.getString("name"));
c.setDescription(rs.getString("description"));
}
} catch (SQLException e) {
e.printStackTrace();
}
DB.close(rs);
DB.close(ps);
DB.close(conn);
return c;
 }}

好了,以上那个这个工作中最麻烦的工作了,记住了就万事大吉了,后面开始写action的具体方法,代码如下:

package com.gao.action;//放在action包中
import java.util.List;
import com.gao.model.Category;//model层
import com.gao.service.CategoryService;//service层
import com.opensymphony.xwork2.ActionSupport;

public class CategoryAction extends ActionSupport {//继承要记得写
 private Category category;     //定义的变量
private int id;
private List<Category> categories;
 private CategoryService categoryService = new CategoryService();//service的对象,此处定义并初始化了便可以直接调用了!
 public String add() {//add方法,只需直接调用service的方法即可,相当方便!
categoryService.add(category);
return SUCCESS;
}

 public String update() {//update方法,实现更新数据库中用户输入的内容。
categoryService.update(category);
return SUCCESS;
}

public String list() {//列出_category表中所有的内容
categories = categoryService.list();
return SUCCESS;
}

public String delete() {//注意哦,调用的是deleteById哟,因为ID也是此action的一个变量,所以可以这样,不然要写车category.id才行
categoryService.deleteById(id);
return SUCCESS;
}

 public String addInput() {//此处为空,直接返回INPUT,返回到category-addInput 界面,等用户输入结束后,再调用此action中的add方法,进行添加处理,最后返回catogory-add页面;
return INPUT;
}

public String updateInput() {//此处本来也应该为空的,但是要为category-updateInput界面提供提示,所以要做个查表的函数,将结果返回给用户;
this.category = this.categoryService.loadById(id);
return INPUT;
}

按照此aciton 的内容,将jsp的内容也都换成真的,比如category-list 中将update,delete都放在每个项目的后面,进行操作,贴出具体内容:

category-list.jsp内容:

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
  + path + "/";%> //这是新建jsp页面都会有的内容,主要是完成basepath的初始化,后面输入连接地址时,直接输本工程下的相对路径即可;
<%@taglib uri="/struts-tags" prefix="s"%>//此举为struts的标签,若不加,s:property就不可用。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><base href="<%=basePath%>">//使用!
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
  <!--<link rel="stylesheet" type="text/css" href="styles.css">-->
 </head>
<body>
  category list
<a href="admin/Category-addInput">添加categroy</a>//添加功能,注意,此处连到Category-addInput的action哦!所以会返回到category-addInput页面哦!
<br /><hr />
<s:iterator value="categories" var="c">//struts中做遍历的方式
<s:property value="#c.name" /> |//取name的值
<s:property value="#c.description" /> |//取description的值
 <a href="admin/Category-delete?id=<s:property value="#c.id"/>">删除Category</a> |//添加删除,传值id
<a href="admin/Category-updateInput?id=<s:property value="#c.id"/>">更新Category</a>//添加更新,传值id
<br />
</s:iterator>
<s:debug></s:debug>//调试标签,可查看值栈中内容
<br>
 </body></html>

category-addInput 内容:

<body>
<form action="admin/Category-add" method="post">//转到category-add的action;
category name:
<input type="text" name="category.name">//传参
category description:
<textarea name="category.description"></textarea>
<input type="submit" value="add">
<hr />
<br>
  </form> </body>

category-updateInput内容:

<body>
<form action="admin/Category-update" method="post"> //目的地,category-update 
  <input type="hidden" name="category.id"  //有ID的传值哦
  value="<s:property value="category.id"/>" /> //初始内容为查表所得,之后用户更改,然后跟ID,DESCRIPTION 一起传给category-update的action
  name:<input name="category.name"
value="<s:property value="category.name"/>" />
  descritpion<textarea name="category.description">
<s:property value="category.description" />
</textarea>
<input type="submit" value="update" />
  </form></body>

剩下的delete,add就非常简单,直接写的OK,或成功这种。

以上这些,都跑通一下就可以了!


这个比上一个是要复杂点,但对逻辑要求不是特别强,也有哈,在action ,jsp,action,jsp绕的那个地方,其他的都是基础,尤其是DB辅助类那,service那个类也是要记住的基础!还是那个方法哈,写方法之前,可以尝试着先画个流程图,然后用代码实现,这样效果会好很多!

好,这个就到这~~(这个博客好像不提供附件上传呢,还是我级别不够不让我传?!)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
001. 允许自定义积分,幸运,威望,等级,经验,认证会员,总版主,区版主,论坛版主的名称 114. 选择风格时加入预览(wensui建议) 115. HTML权限允许开放人员目前只要认证会员及版主即可(原先只允许版主) 116. 增进今**发帖,总发帖及欢迎新会员的功能,使显示数字与实际数据真正接近准确 隐藏版面的帖子也将被一同计入 117. 修正修改评价帖子时的不足 118. 加强短信通知功能:新注册用户,精华,评价,奖惩,删除,转移帖子 119. 修正首页明星插件不能单独显示第二行的错误 120. 后台重做论坛列表有一定的提速 121. 重新生成用户排名及凌晨数据更新现在更稳定了 122. 修复查看用户资料时,非版主的区版或总版主能显示担任信息的问题 123. 对后台或前台遗留的部分代码作了性能优化,有一定的速度提升 124. 现在用户修改资料后,一些不立即生效的信息现在可以立即生效 125. 为修改用户加入写入间隔检测,防止写盘类的破坏程序 126. 解决导航的菜单浏览器兼容问题,并支持多层菜单 取消CSS原先样式定义:TBMenu MenuBG MenuColor 127. 专业版本的搜索功能继续加强,修复原先的记录可能产生的重复记录 跳转页面更方便 131. 风格允许定义小局表格头尾部的HTML控制(比如顶部的导航) 133. 增加RSS订阅主题功能,可按版面或全部版面 134. 增加删除附件回赠(消耗)积分功能 135. 允许定义限制版面的帖子标题是否总是加密,限制标准开始统一 136. 新增迷你方式显示,支持显示版面帖子及内容,虚拟htm地址 统一游客状态,利于搜索引擎收录 137. 新增风格参数,SubjectFont,用来定义专题名称CSS样式 138. 修复后台修改用户资料版主类型用户错误的问题 139. 现在统计数据库的读写次数更加准确 145. 减轻密码找回功能暴力破解情况下带来的请求压力 146. 开始对切换版面带来的写入操作进行限制(WriteEvent) 147. 对游客作特殊处理,不需要额外的内存开销,并尽可能的减少硬盘资源开销 147. 改进在线用户显示分页查看性能及版面 148. 统一精华区与讨论区的显示界面 149. 解决cookie跨域访问问题 150. 退出时增加是否清空Cookie信息的选择 151. 解决一直以来论坛编码解码上的一个潜在错误 152. 对一些页面进行瘦身,进行JS文件分离 154. 总专题及版面专题,预载数据更稳定,而不需要事先访问版面 158. 允许自定义版面是否直接显示专题区 159. MP标签支持多媒体文件切换播放 160. 后台管理,批量更新 新增批量替换(更新)帖子内容功能达到某种目的 171. 兼容IP地址访问下的登录问题 172. 首页及二级版面的JS模板开始统一使用同一种模板,模板代码需要重新调整 模板调用采用JS包含,取消使用SERVER对像调用 173. 支持版面帖子列表的模板自定义显示 174. 支持定义某个分类在首页显示是否简约方式显示 175. 支持定义每个版面(或分类版面)之下的子版面,是否简约方式显示 178. 采用新的方式调用显示在线用户,兼容大部分主流浏览器 179. 修复专题显示在某些浏览器下显示混乱的问题 180. 专题调用显示采用新的方式,能兼容更多的浏览器 181. 支持投票直接显示功能,取消弹出窗口 182. 支持查看投票人员直接显示功能,取消弹出窗口 183. 投票采用POST 防止调用上的漏洞 184. 支持购买帖子及查看购买帖子成员直接调用显示 仍然支持购买再次确认的提示 185. 现在访问无权限查看的版面的帖子时不会再增加点击数了 186. 改善查看投票用户及购买帖子用户性能 187. 对查看帖子内容页面进行多重分析,再次进行性能优化,减轻服务器压力 190. Jmail邮件发送方式可以采用JMail.Message方式 若使用局域网或是本地SMTP服务器,邮件发送速度会很理想 192. 对于新注册的用户,因为邮件未能收到,可以使用忘记密码功能, 填写问题答案等信息,再次要求发送邮件 (要求在用户参数中设置忘记密码找回功能使用 即时更改密码并发送邮件) 193. 现在密码论坛要求输入密码时不会再提示错误信息 194. 支持查看帖子内容时的模板自定义 196. 解决论坛同其它系统编码不同可能产生乱码的问题 197. 对用户增加声望时,取消再奖励财富值,减少声望,也将不影响财富值 199. 插入部分隐藏标签时,提示先选择限制条件 200. 回复帖子标题并非必填项,*号不再显示 201. 普通用户能给帖子上颜色,并且将用户的财富值与此关联 Const LMTDEF_ColorSpend = 1 ' 设定帖子颜色消耗多少魅力值(财富) 当某用户有权限选择并且选择帖子标题类型(HTML,红绿蓝)时,帖子颜色选择无效 202. 发表只限某用户查看的帖子时,若对应用户不存在时将会提示错误 207. 允许设定用户一定积分值则不再需要验证码,包括发帖,短消息及编辑帖子 215. 后台风格模板选择,可以选择是否纯HTML输出,或是使用JS模板 218. 现在对发表内容有了更人性化的设计,开页将自动调节光标位置至填写内容处 219. 论坛短消息允许的ubb编码支持得更广 220. 升级论坛编辑器,主要从以下几个方面作了努力: .适当兼容Mozilla系列浏览器 .默认编辑方式全部设为高级(html)编辑方式,除非浏览器不支持,比如禁用JS .IE能享受所有功能,Mozilla系列拥有大部分编辑功能 .表情支持分页 .允许复制帖子内容为文本格式,高级编辑则复制为HTML文本内容 .全部编码转换在客户端完成,服务器端取消所有编码转换工作 .帖子表情取消一半 .修复或完善一些LeadCode中存在的错误或缺陷 .原先UBB参数设置中的发帖模式作用目前刚好相反,比如原先设为普遍模式现在将视为高级模式 .增强一些论坛编码 - 图片允许批定高度和宽度,格式为[IMG=边框粗细,排版方式,高度,宽度] - 允许单独指定文字的背景色,格式为[BGCOLOR=颜色]文字 221. 对来访用户浏览器及系统使用信息作了更新,现在将更准确 222. 预览帖子不需要再次提交,支持即时预览. 223. 改进菜单功能,对firefox等浏览器支持得更稳定,并开始支持多菜单功能 226. 附件图片缩略图现在开始允许自定义高宽 227. 允许设定附件最多允许同时上传的数量 229. 附件相关的模块作了大变动 - 支持比如百兆的大附件上传和下载 - 附件查看支持按版面来加密限制查看 - 附件存在的物理地址可以设置为不公开 - 现在下载的保存文件名称同作者上传的文件名称 - 删除相应帖子同时删除相应的附件 - 如果你的空间安装有Gfl SDK 上传的图片将自动生成缩略 - 生成的缩略大小可以在后台自定义 - 下载附件的密钥字符串可以在后台自行修改 - 允许设置最多一次发帖可以同时提交的附件数量 - 对于旧版的图片上传附件,提供升级程序,可以产生新的缩略图(支持TIF PSD等图像文件) - 附件允许插入帖子内容排版,未插入的将自动添加 - 允许修改附件内容,以及附件注释. 230. 用户头像上传功能修复,允许同步提交,并保留原先的图像组件缩小转换功能 231. 对防刷新的操作过频等问题作了更好的处理 232. 允许发布财富交易帖(财富为可定制名称)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值