以下是马老师教学内容。工程目标:做BBS后台管理中,对帖子目录的管理,包括添加,更新,删除,列帖子的4个功能,可以发现哈,这也数据库的增删改查是正好对应的,所以实现起来其实很简单。首先确定开发流程:
- 建立前台界面,用ext实现(此为官方建议流程,但我觉得1跟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返回的页面一样,为一句话即可。
- 建Model层
- 建立DB层
- 建立Service层
- 与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页面
- action的实现:新建CategoryAction文件,其中包括list,update,add,delete,updateInput,addInput 6个空方法,returnSUCCESS,最后两个return INPUT即可。
- jsp 实现:新建6个jsp 文件,分别为Category-list,Category-add, Category-delete,Category-update,Category-addInput,Category-updateInput 6个文件,分别对应action中的6个方法的返回,页面内容可以只为个子的页面名称;注意连接关系,其中add,delete,update都是连接在list页面上的,不过,这是最简单的版本,所以不加也没问题。
- 跑通下。
基于以上内容,加上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那个类也是要记住的基础!还是那个方法哈,写方法之前,可以尝试着先画个流程图,然后用代码实现,这样效果会好很多!
好,这个就到这~~(这个博客好像不提供附件上传呢,还是我级别不够不让我传?!)