Struts2项目开发总结
(注:Struts2版本:Struts2.1.6,数据库:Oracle9i)
所须架包:
commons-logging-1.0.4.jar、commons-fileupload-1.2.1.jar、freemarker-2.3.13.jar
ognl-2.6.11.jar、struts2-core-2.1.6.jar、xwork-2.1.2.jar
1、 若在前台页面使用orgl表达式:
必须定义:<%@ page isELIgnored = "false" %>
使用:${requestScope.count}来获取session中的值
2、在jsp页面中显示action中的数据,不需要点击链接到action再返回页面中显示数据
第一步,写一个action类
第二步:配置struts.xml文件,如:
<actionname="sort5"class="com.txxw.cms.news.action.NewsSortListAction"method="sort5list">
<resultname="success">/sort1.jsp</result>
<resultname="error">/error.jsp</result>
</action>
第三步:在sort1.jsp中遍历action方法为sort5list的结果集:
<s:iteratorvalue="sort5list"id="ctype"status="status">
<ahref="sortnlist.action?ct_id=<s:propertyvalue="ct_id"/>"><FONTCOLOR="#FFFFFF"><s:propertyvalue="ct_name"/></FONT></a>
</s:iterator>
第四步:在index.jsp中调用action为sort5list的方法
<s:actionname="sort5"
executeResult="true"><s:iteratorvalue="sort5list"
id="ctype"></s:iterator></s:action>
3、 Struts2超链接传参方式:
第一种:
<a href="newdetail2.action?nid=<s:property value="nid" />"><s:propertyvalue="ntitle"/></a>
第二种:
<s:urlid="Newsquerynew"action="querynew.action">
<s:paramname="request_locale">Newsquerynew</s:param>
</s:url>
<s:a href="%{Newsquerynew}">最新文章</s:a>
第三种:
<s:a href="newsAction.action ">直接使用即可 </s:a>
注意:Struts2超链接标签<s:a href=””>中的href属性是必选参数,否则在项目整合中可能会出现不明的标签异常。
4、 使用Struts2标签<s:iterator>循环遍历结果集:
<s:iteratorvalue="sort5newslist">
<a href="newdetail2.action?nid=<s:propertyvalue="nid"/>"><s:propertyvalue="ntitle"/></a>
<s:propertyvalue="ntime"/>
</s:iterator>
其中内嵌html语言,<s:iterator>除了value属性外,还有可选属性id=" "status="status",value属性是必选的
5、 格式化日期显示方法
或者 ,只需要改变 即可
必须定义:<%@page import="java.text.SimpleDateFormat;"%>
Body体中引用:<%SimpleDateFormat s =new SimpleDateFormat("yyyy-MM-dd");
Date ntime =new Date();
%><%=s.format(ntime)%>
6、 Struts2下拉菜单的使用
<s:selectname="ct_sid"list="ctypesonlist"listKey="ct_id"
listValue="ct_name"theme="simple"headerKey="0"
headerValue="一级栏目">
</s:select>
<s:selectname="ninvalidate"list="#{1:'是',2:'否'}"
listKey="key"listValue="value"headerKey="0"></s:select>
属性注解:name是给Struts2<s:select>标签取名字,这个也是提交到action并保存到对应的数据库中的字段名所必须得参数;list是下拉选项数值;listKey是选项列表所对应的id,listValue是选项列表每个字段的名称;theme是自定义下拉框格式,headerkey是首选项的主键id,headerValue是首选项的字段名
7、 Struts2.1.6使用日期控件:
需要导入包:struts2-dojo-plugin-2.1.6.jar
<%@ taglib uri="/struts-dojo-tags"prefix="sx"%>
在head体中加入:<sx:head/>
在body体中引用:
<sx:datetimepickername="ninvalidate_time"type="date"
displayFormat="yyyy/MM/dd"value="%{'today'}"></sx:datetimepicker>
属性注解:name是给<sx:detetimepicker>标签取名,type为date日期类型,displayFormat格式化显示日期,value是获取时间值,value="%{'today'}"是获取当前系统时间
8、Struts2中form提交表单格式
<s:form action="login"method="post"theme="simple"validate="true">
</s:form>
在form中加入theme="simple"属性,就不会受Struts2<s:form>定义格式的影响
9、使用属性驱动取值
在action中将要输出的属性生成get和set方法,并将返回值定义为返回对象,如:
private String ntitle;//标题
private Stringncontent;//内容
private Stringntime;//时间
private Stringusername;//发布人
News news=ns.queryNnewsdetailsql2(nid);//返回一个对象
public String getNtitle(){
returnntitle;
}
publicvoid setNtitle(String ntitle) {
this.ntitle = ntitle;
}
public String getNcontent() {
returnncontent;
}
publicvoid setNcontent(String ncontent) {
this.ncontent = ncontent;
}
public String getNtime() {
returnntime;
}
publicvoid setNtime(String ntime) {
this.ntime = ntime;
}
public String getUsername() {
returnusername;
}
publicvoid setUsername(String username) {
this.username = username;
}
由action直接跳转到要显示这些属性详细内容的页面
在jsp中直接使用标签<s:propertyvalue="ncontent"/>取出即可
使用模型驱动:查改
新建action查询文章类型:
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.txxw.cms.news.model.Ctype;
import com.txxw.cms.news.model.CtypeService;
/**
*@authorfejdE-mail:[email protected]
*@version创建时间:May22,20091:43:21PM
*功能实现:文章类型修改内容查询
*/
publicclass CtypeeditActionextends ActionSupportimplements ModelDriven{
private Ctypectype=new Ctype();//将封装数据的ctype实现get和set方法
@Override
public String execute()throws Exception {
//TODO Auto-generatedmethod stub]
HttpServletRequest request=ServletActionContext.getRequest();
int ct_id=Integer.parseInt(request.getParameter("ct_id").replace(",",""));//通过选择复选框来实现单个文章类型修改
CtypeService cs=new CtypeService();
Ctypectype=cs.editctypesql(ct_id);
this.setCtype(ctype);
return"success";
}
public Object getModel() {
//TODO Auto-generatedmethod stub
returnnull;
}
public Ctype getCtype() {
returnctype;
}
publicvoid setCtype(Ctype ctype) {
this.ctype = ctype;
}
}
Editctypesql()方法如下:
public Ctypeeditctypesql(int ct_id)throws IOException{
dbcon=new DBConnection();
con=dbcon.getCon();
Ctype cty=null;
List ctylist=new ArrayList();
try {
psta=con.prepareStatement(this.getEditCtypesql(ct_id));
psta.setInt(1, ct_id);
rs=psta.executeQuery();
while(rs.next())
{
cty=new Ctype();
cty.setCt_id(rs.getInt("ct_id"));
cty.setCt_name(rs.getString("ct_name"));
cty.setCt_sid(rs.getString("ct_sid"));
//数据类型Clob转换String类型START//
try
{
oracle.sql.CLOB clob=(oracle.sql.CLOB)rs.getClob("ct_introduction");//数据库中存文本的CLOB型字段名
String ct_introduction=clob.getSubString((long)1,(int)clob.length());//subString是截取字符串(从1截到length)
if(clob==null||ct_introduction==null||ct_introduction==""){
returnnull;
}
cty.setCt_introduction(ct_introduction);
System.out.println(ct_introduction);
}//try
catch(Exception e){
logger.debug("数据类型Clob转换String类型出现异常");
logger.info("数据类型Clob转换String类型出现异常");
e.printStackTrace();
}
//数据类型Clob转换String类型END//
cty.setCt_image(rs.getString("ct_image"));
ctylist.add(cty);
}
} catch (SQLException e) {
//TODO Auto-generatedcatch block
e.printStackTrace();
}
return cty;
}
public String getEditCtypesql(int ct_id) {
this.editCtypesql="select*from system.ctype where ct_id=?";
returneditCtypesql;
}
publicvoid setEditCtypesql(String editCtypesql) {
this.editCtypesql = editCtypesql;
}
注明:上述方法中涉及到Oracle数据类型Clob转换成String类型问题
在jsp中使用
<s:propertyvalue="ctype.ct_id"/>
即可取出ctype中的数据。
10、Struts2+ajax实现批量删除,批量更新操作
全选: checkAll()
不选: checkAllNo()
反选: swichAll()
批量删除: deletenews()
批量更新:display1news()
<scripttype="text/javascript">
functioncheckAll(){
var obj=document.getElementsByName("nid");
for(i=0;i<obj.length;i++){
obj[i].checked=true;
}
}
function checkAllNo(){
var obj=document.getElementsByName("nid");
for(i=0;i<obj.length;i++){
obj[i].checked=false;
}
}
function switchAll(){
var obj=document.getElementsByName("nid");
for(i=0;i<obj.length;i++){
obj[i].checked=! obj[i].checked;
}
}
function vals(input1,input2)
{
var temp="";
varobjForm = document.forms[input1];
varobjLen = objForm.length;
for(var iCount = 0; iCount < objLen; iCount++)
{
if (objForm.elements[iCount].type == "checkbox")
{
if(objForm.elements[iCount].checked==true&&objForm.elements[iCount].nid!="allSelected"&&objForm.elements[iCount].nid!="allConcled")
{
temp=temp+objForm.elements[iCount].value+",";
}
// objForm.elements[iCount].checked = true;
}
}
return temp;
}
function deletenews(){
var nid=vals('form1','this')
if(nid==""){
alert('你没有选中内容');
return false;
}else{
if(confirm('你确定要删除选中的内容吗'+'?'+nid)){
var url="delete.action?nid="+nid;
window.location.href=url;
}
}
}
function display1news(){
var nid=vals('form1','this')
if(nid==""){
alert('你没有选中内容');
return false;
}else{
if(confirm('你确定要显示选中的内容吗'+'?'+nid)){
var url="display1news.action?nid="+nid;
window.location.href=url;
}
}
}
</script>
11、控制Struts2 <s:form>提交表单样式
<!-- form提交表单样式设置Start -->
<styletype="text/css">
<!--
form {margin:0px;display:inline; }
-->
</style>
<!-- 控制form表单样式 -->
<scriptlanguage="javascript">
functionsub()
{
document.form.submit();
}
</script>
<!-- form提交表单样式设置End -->
12、ajax前台验证(一部分)
<scriptlanguage="javascript">
functioncheck()
{
if(document.getElementById("ct_name").value==""){
alert("请输入栏目名称!");
return false;
}
document.form.submit();
}
</script>
<scriptlanguage="javascript">
functioncheck()
{
if(document.getElementById("ntitle").value==""){
alert("请输入文章标题!");
return false;
}
if(document.getElementById("nprovider").value==""){
alert("请输入供稿人!");
return false;
}
if(document.getElementById("ntelephone").value==""){
alert("请输入联系电话!");
return false;
}
var partten1 = /^1[3,5]\d{9}$/;
varpartten2 = /^0(([1,2]\d)|([3-9]\d{2}))\d{8}$/;
if(partten1.test(document.getElementById("ntelephone").value)==false&&partten2.test(document.getElementById("ntelephone").value)==false)
{
alert("请检查您输入的联系电话格式");
return false;
}
if(document.getElementById("email").value==""){
alert("请输入Email!");
return false;
}
var zz=/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;
if(zz.test(document.getElementById("email").value)==false)
{
alert("请输入正确格式的Email.");
return false;
}
document.form.submit();
}
</script>
<s:form action="updatectype"name="form"method="post"theme="simple">
<s:textfieldname="ctype.ct_name"id="ct_name"size="30"></s:textfield>
</s:form>
<scriptlanguage="javascript">
functioncheck()
{
if(document.getElementById("nt").value=="")
{
alert("请输入查询关键字");
return false;
}
document.getElementById("form2").submit();
}
</script>
<formaction="searchsortnews.action"name="form2"id="form2"method="post">
按标题:
<inputtype="text"name="ntitle"id="nt"size="20"/>
<s:hiddenname="ct_id"></s:hidden>
<inputtype="image"src="images/tj.jpg"align="bottom"
onClick="returncheck();"/>
<s:a style="cursor:pointer"onClick="return check();">查询</s:a>
</form>
<s:a style="cursor:pointer"onclick="returndeletenews()">删除</s:a>
13、Struts2+Oracle9i数据库分页
第一步:新建分页的公共接口:
FenYeDao
publicinterfaceFenYeDao{
publicint count(int ct_id);//带有参数
}
第二步:实现接口方法(从数据库中获取数据的总行数):
FenYeService
publicintcount(int ct_id) {
int intRowCount = 0;//总行数
String sql= null ;
ResultSet rs = null ;
dbcon=new DBConnection();
con=dbcon.getCon();
sql = "select nid,ntitle,ntime, ntype from system.news awhere a.ntype =(select ct_id from system.ctype c where c.ct_id=?)order by nidasc";//Sql语句可自定义
try
{
psta=con.prepareStatement(sql);
psta.setInt(1, ct_id);
rs =psta.executeQuery();
while( rs.next()){
//游标指向第一行
intRowCount+=1;//取得总行数
}
}
catch(Exception e)
{
System.out.println(e) ;
}
return intRowCount;
}
第三步:新建action类:
SortNewsListAction
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.txxw.cms.news.model.News;
import com.txxw.cms.news.model.NewsService;
publicclass SortNewsListActionextends ActionSupportimplements ModelDriven{
privateintct_id;//分页需要的参数
private Stringntype;//文章类型
private Listsortclist;//文章类型列表
private Listsortnlist;//文章所有列表
private Newsnews;//文章对象
privateintpageNow = 1 ;//初始化为1,默认从第一页开始显示
privateintpageSize = 8 ;//每页显示8条记录
privateintk;//储存最大页面数
privateinti;//从第i条查询数据
privateintintRowCount;//总行数
privateintintPageCount;//总页数
private NewsServicens=new NewsService();
@Override
public String execute()throws Exception {
//TODO Auto-generatedmethod stub
HttpServletRequest request=ServletActionContext.getRequest();
if(request.getParameter("pageNow")!=null){
try{
pageNow=Integer.parseInt(request.getParameter("pageNow"));
}catch (Exception ex)
{
pageNow=1;
}
if(request.getParameter("ct_id")!=null)
ct_id=Integer.parseInt(request.getParameter("ct_id"));
}
sortclist=ns.sortclist(ct_id); //文章类型列表
intRowCount=ns.count(ct_id); //获取匹配条件文章的总条数
k = (intRowCount+pageSize-1) / pageSize;//计算出总页数
//-------------翻页控制START--------------//
if(pageNow < 1)
{
pageNow=1;
}
if(pageNow >=k){
pageNow =k;
}
if(pageNow==0)
{
pageNow=1;
}
//-------------翻页控制END--------------//
i=pageNow*pageSize-pageSize;//每页要显示文章的条数
sortnlist=ns.sortnlist(i,pageSize,ct_id);//获取文章列表
return"success";
}
public Object getModel() {
//TODO Auto-generatedmethod stub
returnnull;
}
public List getSortnlist() {
returnsortnlist;
}
publicvoid setSortnlist(List sortnlist) {
this.sortnlist = sortnlist;
}
publicint getCt_id() {
returnct_id;
}
publicvoid setCt_id(int ct_id) {
this.ct_id = ct_id;
}
public String getNtype() {
returnntype;
}
publicvoid setNtype(String ntype) {
this.ntype = ntype;
}
public News getNews() {
returnnews;
}
publicvoid setNews(News news) {
this.news = news;
}
public List getSortclist() {
returnsortclist;
}
publicvoid setSortclist(List sortclist) {
this.sortclist = sortclist;
}
publicint getPageNow() {
returnpageNow;
}
publicvoid setPageNow(int pageNow) {
this.pageNow = pageNow;
}
publicint getPageSize() {
returnpageSize;
}
publicvoid setPageSize(int pageSize) {
this.pageSize = pageSize;
}
publicint getK() {
returnk;
}
publicvoid setK(int k) {
this.k = k;
}
publicint getI() {
returni;
}
publicvoid setI(int i) {
this.i = i;
}
publicint getIntRowCount() {
returnintRowCount;
}
publicvoid setIntRowCount(int intRowCount) {
this.intRowCount = intRowCount;
}
publicint getIntPageCount() {
returnintPageCount;
}
publicvoid setIntPageCount(int intPageCount) {
this.intPageCount = intPageCount;
}
}
第四步:在model层中实现方法
NewsService
获取文章类型列表方法Sortclist()
public Listsortclist(int ct_id){
dbcon=new DBConnection();
con=dbcon.getCon();
List sortclist=new ArrayList();
try {
psta=con.prepareStatement(this.getSortclistSql());
psta.setInt(1, ct_id);
rs=psta.executeQuery();
while(rs.next()){
Ctype ctype=new Ctype();
ctype.setCt_id(rs.getInt("ct_id"));
ctype.setCt_name(rs.getString("ct_name"));
ctype.setCt_image(rs.getString("ct_image"));
sortclist.add(ctype);
}
} catch (SQLException e) {
//TODO Auto-generatedcatch block
e.printStackTrace();
}
return sortclist;
}
分类文章列表显示方法Sortnlist()
public Listsortnlist(int i,int pageSize,int ct_id){
dbcon=new DBConnection();
con=dbcon.getCon();
List sortnlist=new ArrayList();
try {
pstac=con.prepareStatement(this.getQueryCctypesql());
rsc=pstac.executeQuery();
String ntype[]=new String[1000];
while(rsc.next()){
ntype[(int)rsc.getInt("ct_id")]=rsc.getString("ct_name");
}
rsc.close();
pstac.close();
psta=con.prepareStatement(this.getSortnlistSql());
psta.setInt(1, ct_id);
rs=psta.executeQuery();
int a=0;
while(rs.next()){
a++;
if((a>i)&&(a<=i+pageSize)){
news=new News();
news.setNid(rs.getInt("nid"));
news.setNtitle(rs.getString("ntitle"));
String ct_name=ntype[(int)rs.getInt("ntype")];
news.setNtype(ct_name);
news.setNcontent(rs.getString("ncontent"));
news.setNtime(rs.getString("ntime"));
news.setUsername(rs.getString("username"));
news.setAuditing(rs.getInt("auditing"));
news.setDisplay(rs.getInt("display"));
news.setCommend(rs.getInt("commend"));
news.setNsubhead(rs.getString("nsubhead"));
news.setNsource(rs.getString("nsource"));
news.setNinvalidate(rs.getString("ninvalidate"));
news.setNinvalidate_time(rs.getString("ninvalidate_time"));
news.setNprovider(rs.getString("nprovider"));
news.setNtelephone(rs.getString("ntelephone"));
news.setEmail(rs.getString("email"));
sortnlist.add(news);
}
}
} catch (SQLException e) {
//TODO Auto-generatedcatch block
e.printStackTrace();
}
return sortnlist;
}
第五步:jsp视图层:在“上一页”和“下一页”中加入判断,当pageNow<1时,“上一页”不可点击;当“pageNow>k总页数”时,“下一页”不可点击
共<s:propertyvalue="intRowCount"/>条 |
共<s:propertyvalue="k"/>页 |
第<s:propertyvalue="pageNow"/> 页 |
<s:ahref="sortnlist.action?pageNow=1&ct_id=%{ct_id}">首页</s:a> |
<s:urlid="url_pre"value="sortnlist.action?pageNow=%{pageNow-1}&ct_id=%{ct_id}">
<s:paramname="pageNow"value="pageNow-1"></s:param>
</s:url>
<s:iftest="pageNow>1"><s:ahref="%{url_pre}">上一页</s:a></s:if>
<s:else>上一页</s:else> |
<s:urlid="url_next"value="sortnlist.action?pageNow=%{pageNow+1}&ct_id=%{ct_id}">
<s:paramname="pageNow"value="pageNow+1"></s:param>
</s:url>
<s:iftest="pageNow<k"><s:ahref="%{url_next}">下一页</s:a></s:if>
<s:else>下一页</s:else> |
<s:a href="sortnlist.action?pageNow=%{k}&ct_id=%{ct_id}">尾页</s:a>
<s:formaction="newsAction.action"method="post"theme="simple">
跳转到第<s:textfieldname="pageNow"size="3"></s:textfield>页
<s:submitvalue="Go"></s:submit>
注:这种分页方式比较啰嗦,完全可以实现纯Struts2+数据库分页,建议小的项目可使用,不建议大项目使用,可以考虑利用数据库中来实现分页.