MVC开发模式
MVC模式是经典的Java开发模式。处理基于“请求-响应”模式的程序中的各种问题。
数据模型(model),视图(view,jsp),控制器(control,Action控制)
Strust2框架搭建
首先向项目中添加struts2的jar包,从struts2的安装路径下找一个示例程序,把web_info下lib包的jar工具拷贝过来,如下是我们所需要的:也把struts.xml和web.xml配置文件拷贝过来,便于参考
(一)构建数据库
sql 语句,或者使用mysql图形化工具Navicat操作,并且在项目下创建sql文件夹,添加mysql文件,记录项目中用到的sql语句,便于查看
create database bbs;
use bbs;
create table _category(id int primary key auto_increment,
name varcahr(50),
description varchar(200));
顺便导入mysql的驱动jar包,build path
(二)建立model层
medel层与数据库表相对应,所以在model包下建立Category类,相对应表的字段信息,建立对应的属性以及set get 方法
package xidian.lili.bbs.model;
public class Category {
private int id;
private String name;
private String description;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
(三)建立service 层
首先建立DB的util包,把连接数据库创建statement,关闭连接放入utils包,方便使用
package xidian.lili.bbs.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DB {
public static Connection getConn(){
Connection con=null;
try {
Class.forName("com.mysql.jdbc.Driver");
con=DriverManager.getConnection("jdbc:mysql://localhost/bbs2009","root","123456");
} catch (Exception e) {
e.printStackTrace();
}
return con;
}
public static PreparedStatement getStatement(Connection con,String sql){
PreparedStatement ps=null;
try {
ps= con.prepareStatement(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return ps;
}
public static void close(Connection con){
if(con!=null);
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(PreparedStatement ps){
if(ps!=null);
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(ResultSet rs){
if(rs!=null);
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
涉及的service主要有增删改查
package xidian.lili.bbs.sercive;
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 xidian.lili.bbs.model.Category;
import xidian.lili.bbs.utils.DB;
public class CategoryService {
//增加
public void add(Category c){
Connection con=DB.getConn();
String sql="insert into _category value(null,?,?);";
PreparedStatement ps=DB.getStatement(con, sql);
try {
ps.setString(1,c.getName());
ps.setString(2,c.getDescription());
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
DB.close(ps);
DB.close(con);
}
//删除
public void delete(Category c){
this.delete(c.getId());
}
public void delete(int id){
Connection con=DB.getConn();
String sql="delete from _category where id=?";
PreparedStatement ps=DB.getStatement(con, sql);
try {
ps.setInt(0, id);
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
DB.close(ps);
DB.close(con);
}
//更新
public void update(Category c){
Connection con=DB.getConn();
String sql="update _category set name=?,description=? where id=?;";
PreparedStatement ps=DB.getStatement(con, 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(ps);
DB.close(con);
}
//查询
public List<Category> list(){
Connection con=DB.getConn();
String sql="select * form _category;";
List<Category> list=new ArrayList();
ResultSet rs=null;
PreparedStatement ps=DB.getStatement(con, sql);
Category c=null;
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"));
list.add(c);
}
} catch (SQLException e) {
e.printStackTrace();
}
DB.close(rs);
DB.close(ps);
DB.close(con);
return list;
}
}
至此后台的代码就开发完了,我们需要把前台的框架准备好
(四)建立界面原型
使用Ext js完成界面部分,将解压以后的ext下的adapter,resources以及ext-all.js,ext-lang-zh_CN.js拷贝到WebRoot下的admin文件夹,我们把后台要显示的界面都放到admin中
完成自己的界面采用直接使用解压以后的ext的ext-3.0.0/examples/layout/accordion.html的界面html进行修改
界面index.html,
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030" />
<title>西电BBS2018论坛管理平台</title>
<link rel="stylesheet" type="text/css"
href="ext/resources/css/ext-all.css" />
<!-- GC -->
<!-- LIBS -->
<script type="text/javascript" src="ext/adapter/ext/ext-base.js">
</script>
<!-- ENDLIBS -->
<script type="text/javascript" src="ext/ext-all.js">
</script>
<script type="text/javascript" src="ext/ext-lang-zh_CN.js">
</script>
<style type="text/css">
html,body {
font: normal 12px verdana;
margin: 0;
padding: 0;
border: 0 none;
overflow: hidden;
height: 100%;
}
.empty .x-panel-body {
padding-top: 0;
text-align: center;
font-style: italic;
color: gray;
font-size: 11px;
}
.x-btn button {
font-size: 14px;
}
.x-panel-header {
font-size: 14px;
}
</style>
<script type="text/javascript">
Ext.onReady( function() {
//页面一加载从这个函数开始执行
var addPanel = function(btn, event) {
var n;
n = tabPanel.getComponent(btn.id);
if(n) {
tabPanel.setActiveTab(n);
return;
}
n = tabPanel.add( {
id : btn.id,
title : btn.id,
html : '<iframe width=100% height=100% src=' + btn.id + ' />',
//autoLoad : '',
closable : 'true'
});
tabPanel.setActiveTab(n);
}
var item1 = new Ext.Panel( {
title : 'Category管理',
//html : '<empty panel>',
cls : 'empty',
items : [
new Ext.Button({
id : 'Category_list',
text : 'Category列表',
width : '100%',
listeners : {
click : addPanel
}
}),
new Ext.Button({
id : 'Settings',
text : '设置',
width : '100%',
listeners : {
click : addPanel
}
})
]
});
var item2 = new Ext.Panel( {
title : 'Contacts',
html : '<empty panel>',
cls : 'empty',
items : [
new Ext.Button({
id : 'New Friend',
text : '新朋友',
width : '100%',
listeners : {
click : addPanel
}
}),
new Ext.Button({
id : 'Group Chat',
text : '群聊',
width : '100%',
listeners : {
click : addPanel
}
})
]
});
var item3 = new Ext.Panel( {
title : 'Discover',
html : '<empty panel>',
cls : 'empty'
});
var item4 = new Ext.Panel( {
title : 'Accordion Item 4',
html : '<empty panel>',
cls : 'empty'
});
var item5 = new Ext.Panel( {
title : 'Accordion Item 5',
html : '<empty panel>',
cls : 'empty'
});
var accordion = new Ext.Panel( {
region : 'west',
margins : '5 0 5 5',
split : true,
width : 210,
layout : 'accordion',
items : [ item1, item2, item3, item4, item5 ]
});
var tabPanel = new Ext.TabPanel( {
region : 'center',
enableTabScroll : true,
deferredRender : false,
activeTab : 0,
items : [ {
title : 'index',
//html : 'aaaaaa'
autoLoad : 'Category_list'
} ]
});
var viewport = new Ext.Viewport( {
layout : 'border',
items : [ accordion, tabPanel ]
});
});
</script>
</head>
<body>
<!-- EXAMPLES -->
</body>
</html>
整个界面是一个viewport,分成两块,左面是参考ext examples中的accordion块,右边是加入的tabPanel
var viewport = new Ext.Viewport( {
layout : 'border',
items : [ accordion, tabPanel ]
});
定义tabPanel块,主要是 autoLoad 参数,可以在panel上显示对应的jsp文件
var tabPanel = new Ext.TabPanel( {
region : 'center',
enableTabScroll : true,
deferredRender : false,
activeTab : 0,
items : [ {
title : 'index',
autoLoad : 'Category_list'
} ]
});
定义accordion块,west位置在左边,然后加入5个items
var accordion = new Ext.Panel( {
region : 'west',
margins : '5 0 5 5',
split : true,
width : 210,
layout : 'accordion',
items : [ item1, item2, item3, item4, item5 ]
});
分别定义5个items,以第一个为例说明,每一个items是一个Panel,给里面加入button,每个button都有对应的id,并在button的click事件中添加监听器,就是放点击该button时,执行addPanel函数
var item1 = new Ext.Panel( {
title : 'Category管理',
//html : '<empty panel>',
cls : 'empty',
items : [
new Ext.Button({
id : 'Category_list',
text : 'Category列表',
width : '100%',
listeners : {
click : addPanel
}
}),
new Ext.Button({
id : 'Settings',
text : '设置',
width : '100%',
listeners : {
click : addPanel
}
})
]
});
解析addPanel函数,获取tabPanel的事件,根据button的id判断,若tabPanel已经有该button说明在tabPanel中打开了button对应的页面,此时active激活,若是没有该button对应的id,在tabPanel新建一个Component,并激活
var addPanel = function(btn, event) {
var n;
n = tabPanel.getComponent(btn.id);
if(n) {
tabPanel.setActiveTab(n);
return;
}
n = tabPanel.add( {
id : btn.id,
title : btn.id,
html : '<iframe width=100% height=100% src=' + btn.id + ' />',
//autoLoad : '',
closable : 'true'
});
tabPanel.setActiveTab(n);
}
结果
(五)struts.xml文件配置及Action类实现
首先配置完成Action类,要实现的功能有增删改查,规定对应的Action名字,做出相应的返回
对于增加 Action name Category_add name对应对应的action method 为add 对应的jsp文件定义为Category_add.jsp
这样定义我们在struts.xml文件中可以使用通配符
将前台和后天在Action类中联系起来
当前台有Category_add的action时,执行method为add,就是执行CategoryAction类中的add()方法,这个时候先执行后天service中的增加方法,这样就把前台和后台联系起来了
package xidian.lili.bbs.action;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
import xidian.lili.bbs.model.Category;
import xidian.lili.bbs.sercive.CategoryService;
public class CategoryAction extends ActionSupport{
private CategoryService categoryservice=new CategoryService();
private Category c;
private List<Category> categories;
private int id;
public String add(){
categoryservice.add(c);
return SUCCESS;
}
public String delete(){
categoryservice.deletebyId(id);
return SUCCESS;
}
public String update(){
categoryservice.update(c);
return SUCCESS;
}
public String list(){
categories=categoryservice.list();
return SUCCESS;
}
public String addinput(){
return INPUT;
}
public String updateinput(){
this.c=this.categoryservice.loadById(id);
return INPUT;
}
public CategoryService getCategoryservice() {
return categoryservice;
}
public void setCategoryservice(CategoryService categoryservice) {
this.categoryservice = categoryservice;
}
public Category getC() {
return c;
}
public void setC(Category c) {
this.c = c;
}
public List<Category> getCategories() {
return categories;
}
public void setCategories(List<Category> categories) {
categories = categories;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
struts.xml配置文件:
<package name="front" namespace="/" extends="struts-default">
<default-action-ref name="Category_list" />
<action name="Category_list" class="xidian.lili.bbs.action.CategoryAction" method="list">
<result>/index.jsp</result>
</action>
</package>
<package name="admin" namespace="/admin" extends="struts-default">
<action name="*_*" class="xidian.lili.bbs.action.{1}Action" method="{2}">
<result>/admin/{1}_{2}.jsp</result>
<result name="input">//admin/{1}_{2}.jsp</result>
</action>
</package>
我们在前面的界面中,让TabPanel对应的Action是Category_list.,这就是TabPanel,执行CategoryAction中的list()函数查找,我们把前台增删改的action都放在这个jsp文件中
<body>
Category_list
<a href="admin/Category_addinput">添加用户</a>
<hr/>
<s:iterator value="categories" var="c">
<s:property value="#c.name"/>|
<s:property value="#c.description"/>|
<a href="admin/Category_delete?id=<s:property value="#c.id"/>">删除用户</a>
<a href="admin/Category_updateinput?id=<s:property value="#c.id"/>">更新用户</a>
<br/>
</s:iterator>
<s:debug></s:debug>
</body>
添加
当你想添加一个category,应该要输入值,所以我们执行Category_addinput的Action,转到Category_addinput.jsp,输入数据,然后提交到Category_add的Action,这里使用domin model进行参数接收,读取到输入的name和description,这个时候CategoryAction的model变量c就有了值,然后执行方法add(),完成数据添加
<body>
add input
<form action="admin/Category_add" method="post">
name<input name="c.name" />
description<textarea name="c.description" ></textarea>
<input type="submit" value="add" />
</form>
</body>
查询
执行了Action类中的list(),Action类中的局部变量categories就有了内容,我们用struts标签来遍历这个list,并通过OGNL表达式进行读取数据,这里使用var,存放到ActionContext中,用#加的方式读取
<s:iterator value="categories" var="c">
<s:property value="#c.name"/>|
<s:property value="#c.description"/>|
<a href="admin/Category_delete?id=<s:property value="#c.id"/>">删除用户</a>
<a href="admin/Category_updateinput?id=<s:property value="#c.id"/>">更新用户</a>
<br/>
</s:iterator>
删除
用?+参数名接收参数,取到当前遍历到的对象的id传递给delete action,进行操作
更新
用跟删除同样的方法接收要更新的id,传递给updateinput的action(同addinput),然后根据id得到要更新的Category,然后交给Category_update的Action,但是要在updateinput的时候做下面的事情:
<body>
update input
<form action="admin/Category_update" method="post">
<input type="hidden" name="c.id" value="<s:property value="c.id"/>" />
name<input name="c.name" value="<s:property value="c.name"/>"/>
description<textarea name="c.description" ><s:property value="c.description"/></textarea>
<input type="submit" value="update" />
所以这里要在service中增加方法
public Category loadById(int id){
Connection con=DB.getConn();
String sql="select * from _category where id=?;";
ResultSet rs=null;
PreparedStatement ps=DB.getStatement(con, sql);
Category c=null;
try {
ps.setInt(1, id);
rs=ps.executeQuery();
while(rs.next()){
c=new Category();
c.setId(rs.getInt("id"));
c.setName(rs.getString("name"));
c.setDescription(rs.getString("description"));
}
} catch (SQLException e) {
e.printStackTrace();
}
DB.close(rs);
DB.close(ps);
DB.close(con);
return c;
}
然后再action的updateinput中执行该方法