Struts2+Spring在项目中的应用


     本文不属原创,只是日常工作的一点总结。下面的工程示例只是展示了最基本的配置,能够测试Hello World通过。

1,web.xml配置;

2,常用三方包;

3,Struts2、Spring Bean配置;

4,log4j、国际化资源文件;

5,三层结构设计;

6,异常体系结构;

7,工程结构图。

 

----------------------------------------------------------------------------------------------------------------------------

 

1,web.xml配置

     一个Listener两个Filter,加载Spring容器上下文,初始化struts2中央转发器。

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
	xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<display-name>ICCardManager</display-name>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>utf-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
		<dispatcher>REQUEST</dispatcher>
		<dispatcher>FORWARD</dispatcher>
	</filter-mapping>

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
		classpath*:applicationContext-*.xml
	</param-value>
	</context-param>

	<welcome-file-list>
		<welcome-file>jsp/index.html</welcome-file>
		<welcome-file>jsp/index.htm</welcome-file>
		<welcome-file>jsp/login.jsp</welcome-file>
		<welcome-file>jsp/default.html</welcome-file>
		<welcome-file>jsp/default.htm</welcome-file>
		<welcome-file>jsp/default.jsp</welcome-file>
	</welcome-file-list>
</web-app>

 

 

2、常用三方包

     struts2、spring、Oracle、数据库连接池驱动包、dom4j、Jackson、POI以及iText等。

     Struts2+Spring在项目中的应用

 

3、Struts2、Spring Bean配置

 

      struts.xml

     

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
	<!-- if devMode=true,modify this file don't need to restart tomcat -->
	<constant name="struts.devMode" value="false" />
	<constant name="struts.objectFactory" value="spring" />
	<constant name="struts.action.extension" value="action,do,aspx" />
	<constant name="struts.multipart.maxSize" value="1009715200" />
	
	<!-- include multiple config-->
	<include file="struts-default.xml" />
	<include file="struts-icc.xml" />
</struts>

 

    自定义struts-icc.xml

   

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
	<constant name="struts.custom.i18n.resources" value="icc"></constant>
	
	<package name="ICCardManager" namespace="/" extends="struts-default">
	    <global-results>
		  <result name="failed">jsp/error.jsp</result>
		  <result name="main">jsp/HomeManager.jsp</result>
	    </global-results>
	    <action name="login" class="LoginAction">
		   <result name="success">/jsp/HomeManager.jsp</result>
		   <result name="login">/jsp/login.jsp</result>
	    </action>
	</package>
</struts>

 

   Spring上下文监听器加载指定配置文件*:applicationContext-*.xml,在src目录下新建文件applicationContext-icc.xml

  

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:aop="http://www.springframework.org/schema/aop"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans   
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd   
           http://www.springframework.org/schema/context   
           http://www.springframework.org/schema/context/spring-context-2.5.xsd   
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">  
   	<bean id="LoginAction" class="cn.hunnu.icc.action.LoginAction" scope="prototype">
	</bean>
	
	<!-- Service Beans -->
	<bean id="UserService" class="cn.hunnu.icc.service.impl.UserService">
	    <property name="userDAO">
	    	<ref bean="UserDAO"/>
	    </property>
	</bean>
	<bean id="CardService" class="cn.hunnu.icc.service.impl.CardService">
	    <property name="cardDAO">
	    	<ref bean="CardDAO"/>
	    </property>
	</bean>
	
	<!-- DAO Beans -->
	<bean id="UserDAO" class="cn.hunnu.icc.dao.impl.UserDAO">
	</bean>
	<bean id="CardDAO" class="cn.hunnu.icc.dao.impl.CardDAO">
	</bean>
</beans>

 

4,log4j、国际化资源文件

     4.1 日志管理log4j.properties

    

log4j.rootCategory=INFO, stdout , R 
log4j.logger.cn.hunnu.icc=INFO,ICC


log4j.appender.ICC=org.apache.log4j.DailyRollingFileAppender

log4j.appender.ICC.File=${catalina.home}/ICC/logs/ICC.log

log4j.appender.ICC.layout=org.apache.log4j.PatternLayout

log4j.appender.ICC.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n


log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n


log4j.appender.R=org.apache.log4j.DailyRollingFileAppender

log4j.appender.R.File=${catalina.home}/ICC/logs/qc.log

log4j.appender.R.layout=org.apache.log4j.PatternLayout

log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n


log4j.logger.com.neusoft=DEBUG

log4j.logger.com.opensymphony.oscache=ERROR

log4j.logger.net.sf.navigator=ERROR

log4j.logger.org.apache.commons=ERROR

log4j.logger.org.apache.struts=WARN

log4j.logger.org.displaytag=ERROR

log4j.logger.org.springframework=INFO

log4j.logger.com.ibatis.db=WARN

log4j.logger.org.apache.velocity=FATAL

log4j.logger.com.canoo.webtest=WARN

 
   4.2 国际化资源文件在struts.xml中指定了其命名,我们采用struts2默认的国际化支持

  

<constant name="struts.custom.i18n.resources" value="icc"></constant>

    资源文件列表:

    icc_en_US.properties

    icc_zh_CN.properties

    icc.properties

 

    美国英文资源icc_en_US.properties示例:

   

homemanager.toolbar.action=Action
homemanager.toolbar.action.newnote=New Note
homemanager.toolbar.action.duplicatenote=Duplicate Note
homemanager.toolbar.action.deletenote=Delete Note(s)
homemanager.toolbar.action.newfilter=New Filter
homemanager.toolbar.action.shareoutside=Share Outside My Firm
homemanager.toolbar.export=Export
homemanager.toolbar.print=Print
homemanager.toolbar.columnview=Column View
homemanager.toolbar.setting=Default Note Settings
homemanager.tab.filter=Filter Settings
homemanager.tab.detail=Note Settings
homemanager.tab.content=Note Content


panel.filter.ApplyFilter=Apply Filter
panel.filter.Effective=Effective
panel.filter.to=to
panel.filter.Modified=Modified
panel.filter.SearchDefault=search keywords or phrases

 5、三层结构设计

     5.1 DAO接口以及实现类

    

package cn.hunnu.icc.dao;

public interface ICardDAO
{
	//接口列表...
}

   

package cn.hunnu.icc.dao;

public interface IUserDAO
{
	//接口列表...
}

   

  

package cn.hunnu.icc.dao.impl;

import cn.hunnu.icc.dao.ICardDAO;

public class CardDAO implements ICardDAO
{
	//接口实现列表...
}

   

package cn.hunnu.icc.dao.impl;

import cn.hunnu.icc.dao.IUserDAO;

public class UserDAO implements IUserDAO
{
	//接口实现列表...
}

       5.2 Service接口以及实现类

    

package cn.hunnu.icc.service;

public interface ICardService
{
	//接口列表...
}

   

package cn.hunnu.icc.service;

public interface IUserService 
{
	//接口列表...
}

  

package cn.hunnu.icc.service.impl;

import cn.hunnu.icc.dao.ICardDAO;
import cn.hunnu.icc.service.ICardService;

public class CardService implements ICardService
{
	private ICardDAO cardDAO;

	public ICardDAO getCardDAO()
	{
		return cardDAO;
	}

	public void setCardDAO(ICardDAO cardDAO)
	{
		this.cardDAO = cardDAO;
	}
	
	
}

  

package cn.hunnu.icc.service.impl;

import cn.hunnu.icc.dao.IUserDAO;
import cn.hunnu.icc.service.IUserService;

public class UserService implements IUserService
{
	private IUserDAO userDAO;

	public IUserDAO getUserDAO()
	{
		return userDAO;
	}

	public void setUserDAO(IUserDAO userDAO)
	{
		this.userDAO = userDAO;
	}
	
}

 

     关于究竟是在Service层调用多个DAO层,还是Service层调用多个Service层,在网上各有争论。

     service - > dao:
     Struts2+Spring在项目中的应用
      service - > service
     Struts2+Spring在项目中的应用
  

 5.3  Action层调用Service接口

  

package cn.hunnu.icc.action;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;

import cn.hunnu.icc.service.IUserService;
/**
 * 用户登录
 * @author Administrator
 *
 */
public class LoginAction extends BaseAction
{
	private static final long serialVersionUID = -2234417925314808583L;
	
	public static final Log log = LogFactory.getLog(LoginAction.class);

	private IUserService userService;
	
	private String account;
	private String pwd;
	
	public String execute()
	{
		log.info("execute HelloAction...");
		HttpServletRequest request = ServletActionContext.getRequest();
		request.setAttribute("userName", account);
		
		boolean success = false;
		if("xiaobo".equals(account))
		{
			success = true;
		}
		if(success)
		{
			return SUCCESS;
		}
		else
		{
			request.setAttribute("msg", "对不起,您的输入有误,请重新输入!");
			return LOGIN;
		}
	}

	public String getAccount() {
		return account;
	}

	public void setAccount(String account) {
		this.account = account;
	}

	public String getPwd() {
		return pwd;
	}

	public void setPwd(String pwd) {
		this.pwd = pwd;
	}

	public IUserService getUserService()
	{
		return userService;
	}

	public void setUserService(IUserService userService)
	{
		this.userService = userService;
	}
}

   注意BaseAction,这是一个自定义的通用Action,提供了一些常用方法,下面展示其源码:

 

package cn.hunnu.icc.action;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;

import cn.hunnu.icc.util.Constants;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

@SuppressWarnings("serial")
public class BaseAction extends ActionSupport
{
	protected static final Logger LOGGER = Logger.getLogger(BaseAction.class);

	protected static final String DEFAULT_CHARACTER = Constants.DEFAULT_CHARACTER;

	protected static final String ContentType_HTML = "text/html";
	protected static final String ContentType_XML = "text/xml";
	protected static final String ContentType_JSON = "application/json";


	/**
	 * get project root directory.
	 *
	 * @return
	 */
	protected String getWebRealPath() {
		return ServletActionContext.getServletContext().getRealPath("/");
	}

	/**
	 * get request of parameter value.
	 *
	 * @param parameter
	 * @return string parameter value,if this value is null then return "".
	 */
	protected String getParameter(String parameter) {
		Object value = getParameters().get(parameter);
		if (value != null) {
			return ((String[]) value)[0];
		}
		return "";
	}

	protected HttpServletRequest getRequest() {
		return ServletActionContext.getRequest();
	}

	protected HttpServletResponse getResponse() {
		return ServletActionContext.getResponse();
	}

	protected ServletContext getServletContext() {
		return ServletActionContext.getServletContext();
	}

	/**
	 * get request of parameter values.
	 *
	 * @param parameter
	 * @return string parameter values.
	 */
	protected String[] getParameterValues(String parameter) {
		String[] values = this.getRequest().getParameterValues(parameter);
		if (values != null) {
			return values;
		}
		return new String[] {};
	}

	/**
	 * get request of int parameter value.
	 *
	 * @param parameter
	 * @return int
	 */
	protected int getIntParameter(String parameter) {
		Object value = getParameters().get(parameter);
		if (value != null) {
			try {
				return Integer.parseInt(((String[]) value)[0]);
			} catch (Exception e) {
				return 0;
			}
		}
		return 0;
	}

	@SuppressWarnings("unchecked")
	protected Map getParameters() {
		ActionContext actionContext = ActionContext.getContext();
		Map parameters = (Map) actionContext.getParameters();
		return parameters;
	}

	/**
	 * get web deployment Path.
	 *
	 * @return
	 */
	public String getContextPath() {
		return ServletActionContext.getServletContext().getRealPath("/");
	}

	/**
	 * The information directly back to the browser,Default character is utf-8.
	 *
	 * @param content
	 * @throws IOException
	 */
	protected void sendClient(String content) {
		this.sendClient(content, DEFAULT_CHARACTER, ContentType_HTML);
	}
	/**
	 * The information directly back to the browser.
	 *
	 * @param content
	 * @param character
	 * @throws IOException
	 */
	protected void sendClient(String content, String character)
			throws IOException {
		sendClient(content, character, ContentType_XML);
	}
	/**
	 * The information directly back to the browser.
	 *
	 * @param content
	 * @param character
	 * @throws IOException
	 */
	protected void sendClient(String content, String character, String contentType)
			{
		HttpServletResponse response = ServletActionContext.getResponse();
		response.setContentType(String.format("%s;charset=%s", contentType, character));
		PrintWriter out;
		try {
			out = response.getWriter();
			out.print(content);
			out.flush();
			out.close();
		} catch (IOException e) {}

	}
	/***
	 * Send xml data to client, utf-8 encoding
	 * @param content
	 * @throws IOException
	 */
	protected void sendClientXML(String content) throws IOException {
		this.sendClient(content, DEFAULT_CHARACTER, ContentType_XML);
	}

	/***
	 * Send JSON data to client, utf-8 encoding
	 * @param content
	 * @throws IOException
	 */
	protected void sendClientJSON(String content) throws IOException {
		this.sendClient(content, DEFAULT_CHARACTER, ContentType_JSON);
	}

	/**
	 *
	 * @param queryString
	 * @return
	 */
	@SuppressWarnings("unchecked")
	protected Map getParameterMap(String queryString) {
		if (queryString == null || "".equals(queryString))
			return null;
		Map parameterMap = new HashMap();
		String[] parArray = queryString.split("&");
		for (int i = 0; i < parArray.length; i++) {
			if (parArray[i].split("=").length == 2) {
				parameterMap.put(parArray[i].split("=")[0], parArray[i]
						.split("=")[1]);
			}
		}
		return parameterMap;
	}


	protected String getProperty(String key)
	{
		String ret = getRequest().getParameter(key);
		if (ret==null || ret.isEmpty())
		{
			return getRequest().getAttribute(key).toString();
		}
		else
		{
			return ret;
		}
	}
}

 

6,异常体系结构

     设计异常的基本原则是:

     (1) DAO层所有的接口都不声明checked异常,但建议都声明unchecked异常,DAO实现类统一使用RuntimeException,可以参考Spring Jdbctemplate设计原则,举例:
          

 public void update(Task task);

 

    (2) Service层接口统一抛出自定义的Service异常,并且在Service实现类中所有的DAO操作都要try..catch..,举例:
   

public interface ITaskService
{
          public void updateTask(Task task) throws ServiceException;
}

public class TaskService implements ITaskService
{
        ITaskDAO taskdao;
        IUserDAO userdao;
        public void updateTask(Task task) throws ServiceException
       {
	try
	{
	          taskdao.update(task);
	}
	catch(Exception e)
	{
	          throw new ServiceException(“code+message”);
	}
	//other logic operations
				
	try
	{
	         user = userdao.getUser(env);
	}
	catch(Exception e)
	{
	         throw new ServiceException(“code+message”);
	}
       }
}

 

   (3) 在Action捕获Service异常,可以根据ServiceException的code和message进行异常归类和异常消息国际化处理。

 7,工程结构图

     以下代码组织结构仅供参考:
      Struts2+Spring在项目中的应用   Struts2+Spring在项目中的应用
 
 

 

 

 

 

你可能感兴趣的:(DAO,spring,log4j,struts,项目管理)