commons-beanutils.jar
commons-digester.jar
commons-logging.jar
struts.jar
2.工程代码
package sun.com.struts.action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.actions.MappingDispatchAction; import sun.com.struts.pojo.LoginForm; import sun.com.struts.service.ServiceLocator; import sun.com.struts.service.UserService; /** * user login action * @author fengyilin * @version $Revision: 64555 $ $Date: 2012-04-19 15:01:28 +0800 (Thu, 19 Apr 2012) $ * @since 2012/04/26 * */ public class LoginAction extends MappingDispatchAction { /** get the serviceLocator */ private static ServiceLocator locator = ServiceLocator.getInstance(); /** user service*/ private UserService userService = (UserService) locator .getService("UserService"); /** * login * * @param map ActionMapping * @param form ActionForm * @param request HttpServletRequest * @param response HttpServletResponse * @return actionForward */ public ActionForward login(ActionMapping map, ActionForm form, HttpServletRequest request, HttpServletResponse response) { LoginForm loginForm = (LoginForm) form; String name = loginForm.getName(); String passWord = loginForm.getPassWord(); String userName = userService.findUserByName(name); if ("lin".equals(userName) && "lin".equals(passWord)) { return map.findForward("success"); } else { return map.findForward("input"); } } }
这个action和普通的struts action的区别在于里面有如下src
/** get the serviceLocator */ private static ServiceLocator locator = ServiceLocator.getInstance(); /** user service*/ private UserService userService = (UserService) locator .getService("UserService");
即用到的service是由serviceLocator这个类提供的,ServiceLocator是自己定义的一个类扫描类,代码会在下面给出。
/** * */ package sun.com.struts.annotation.service; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @author fengyilin * */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Service { /** service name */ String value(); }
/** * */ package sun.com.struts.pojo; import org.apache.struts.action.ActionForm; /** * user login action * @author fengyilin * @version $Revision: 64555 $ $Date: 2012-04-19 15:01:28 +0800 (Thu, 19 Apr 2012) $ * @since 2011/08/05 * */ public class LoginForm extends ActionForm { /** * */ private static final long serialVersionUID = 7260629305234876476L; private String name; private String passWord; /** * @param name * the name to set */ public void setName(String name) { this.name = name; } /** * @return name name */ public String getName() { return name; } /** * @param passWord * the passWord to set */ public void setPassWord(String passWord) { this.passWord = passWord; } /** * @return the passWord */ public String getPassWord() { return passWord; } }
BaseService接口编写,所有的service接口都要继承自这个接口。
/** * */ package sun.com.struts.service; /** * @author fengyilin * */ public interface BaseService { /** * init the service */ void init (); /** * destory the service */ void destory(); }
UserService接口编写
/** * */ package sun.com.struts.service; /** * @author fengyilin * */ public interface UserService extends BaseService { /** * find the user * @param name userName * @return user */ public String findUserByName(String name); }
UserServiceImpl编写,该类的特别之处在于声明了Service这个annotation
/** * */ package sun.com.struts.service.impl; import sun.com.struts.annotation.service.Service; import sun.com.struts.service.UserService; /** * @author fengyilin * */ @Service("UserService") public class UserServiceImpl implements UserService { @Override public void destory() { } @Override public void init() { } /** * find the user * @param name userName * @return user */ @Override public String findUserByName(String name) { if ("gaofeng".equals(name)) { return "lin"; } else { return ""; } } }
编写本文的重点类,类扫描器,这个类将对src\sun\com\struts\service这个包下的所有的类,然后会判断哪个类定义了Service的annotation,如果定义了,就将该类的一个实例保存到services这个map中。这样我们在action中想用哪一个service,直接从services中get出来就可以了。
/** * */ package sun.com.struts.service; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * @author fengyilin * */ public final class ServiceLocator { /** * annotation path * * the class witch is belong to this path will be read */ private static final String TARGET_PATH = "sun/com/struts/service/"; //----------------------------------------------------------------- static 変数 /** the unique system Locator instance */ private static ServiceLocator locator = new ServiceLocator(); /** construct method */ private ServiceLocator() {} /** put the service instance to cache */ private Mapservices; /** Log instance */ private static Log log = LogFactory.getLog(ServiceLocator.class); /** * get the unique system Locator instance * * @return Locator instance */ public static ServiceLocator getInstance() { return locator; } /** type of the class file */ private static final String CLASS_EXTENSION = ".class"; /** * get the service. * * @param service type * @param name service name * @return service * @see #load() */ public T getService(String name) { if (name == null) { return null; } if (services == null) { try { log.debug("reade the service..."); load(); } catch (Error e) { log.error("[BUG] can not reade the service correctly", e); services = null; throw e; } catch (RuntimeException e) { log.error("[BUG] can not reade the service correctly", e); services = null; throw e; } } @SuppressWarnings("unchecked") T service = (T) services.get(name); return service; } /** * read the service of the path */ private void load() { services = new HashMap (); // get all the class try { for (Class> c : getClasses(TARGET_PATH)) { sun.com.struts.annotation.service.Service s = c .getAnnotation(sun.com.struts.annotation.service.Service.class); if (s != null) { BaseService service = createBaseService(c); services.put(s.value(), service); log.debug(" [annotation]:" + service); } } } catch (Exception e) { log.debug(e); } log.debug(services); } /** * get the service * * @param c class * @return BaseService service * @throws Exception error */ private BaseService createBaseService(Class> c) throws Exception { try { BaseService service = (BaseService)c.newInstance(); return service; } catch (Exception e) { e = new ClassCastException(c.getName()); throw e; } } /** * * read all the class belong to the path *
* * @param path class path (ex. sun/com/struts/service/) * @return class * @throws Exception error */ public static Class>[] getClasses(String path) throws Exception { Enumeratione; try { ClassLoader loader = Thread.currentThread().getContextClassLoader(); e = loader.getResources(path); } catch (IOException ex) { throw new RuntimeException( "can not get the src(" + path + ")", ex); } if (log.isWarnEnabled()) { if (!e.hasMoreElements()) { log.warn("########## [getClasses] the source does not exist" + "(" + path + ")"); } } //buf of the path StringBuilder buf = new StringBuilder(); Set > classes = new LinkedHashSet >(); while (e.hasMoreElements()) { URL url = e.nextElement(); if (log.isDebugEnabled()) { log.debug("########## [getClasses] " + url); } // get the of the path File file = new File(url.getFile()); URI uri = file.toURI(); for (File f : listFiles(file)) { buf.setLength(0); classes.add(forClass(buf.append(path) .append(uri.relativize(f.toURI()).getPath()) .toString())); } } return classes.toArray(new Class>[classes.size()]); } /** * get the next flow of the directory * return the directory * * @param file file * @return directory list */ private static List listFiles(File file) { List files = new ArrayList (); // class file if (file.getName().endsWith(CLASS_EXTENSION)) { files.add(file); } // next flow is exit File[] fs = file.listFiles(); if (fs != null) { for (File f : file.listFiles()) { files.addAll(listFiles(f)); } } return files; } /** * get the object of the path * * Class> c = forClass("sun/com/struts/service/BaseService.class"); * * equlesWith * * Class> c = Class.forName("sun.com.struts.service.BaseService"); * * @param path class * @return object * @throws Exception error */ private static Class> forClass(final String path) throws Exception { String name = toClassName(path); if (log.isDebugEnabled()) { log.debug("########## [forClass] " + path); } try { return Class.forName(name, false, Thread.currentThread().getContextClassLoader()); } catch (ClassNotFoundException e) { if (log.isWarnEnabled()) { log.warn("########## [forClass] " + name + " does not exict。", e); } return null; } catch (ExceptionInInitializerError e) { log.error(name + " can not init。", e); throw new Exception(path, e); } catch (NoClassDefFoundError e) { log.error(name + " does not exict。", e); throw new Exception(path, e); } } /** * convert the path。 * * @param path class path (ex. sun/com/struts/service/BaseService.class); * @return the class name (ex. sun.com.struts.service.BaseService) */ private static String toClassName(String path) { if (!path.endsWith(CLASS_EXTENSION)) { throw new IllegalArgumentException( "[BUG]type is not the\"" + CLASS_EXTENSION + " (" + path + ")"); } return path.substring(0, path.length() - CLASS_EXTENSION.length()).replace("/", "."); } }
编写配置文件。struts-config.xml
修改web.xml添加struts1的支持。
myStruts1 action org.apache.struts.action.ActionServlet config /WEB-INF/struts-config.xml debug 2 detail 2 2 action /action/* login.jsp
login.jsp
<%@ page language="java" contentType="text/html; charset=windows-31j" pageEncoding="windows-31j"%>Login Home