以下是本人在學習過程中做的一點點小小的總結,在這里留個副本!


現有代碼存在的問題:

為了解決每個業務模塊對應一個ServletServlet過多的問題

解決辦法:

使用一個新的Servlet,匯總了所有的業務模塊Servlet,增加邏輯判斷,具體調用哪個業務Servlet

public class ServletAction extends HttpServlet {

//未抽取之前;

protected void service(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

String path = request.getServletPath();

if(path.indexOf("/userServlet.action") >=0 ){

//userService.getList(name);

request.setAttribute("user", "user");

this.getServletContext().getRequestDispatcher("/user/user_list.jsp").forward(request, response);

}

if(path.indexOf("/roleServlet.action") >= 0) {

//roleService.getList();

request.setAttribute("role", "role");

this.getServletContext().getRequestDispatcher("/user/role_list.jsp").forward(request, response);

}

}

}

該匯總的Servletweb.xml中注冊時,匹配多個,所有的Servlet路徑;

 <servlet>

 <servlet-name>ActionServlet</servlet-name>

 <servlet-class>com.bjsxt.struts.ActionServlet</servlet-class>

 </servlet>

 <servlet-mapping>

 <servlet-name>ActionServlet</servlet-name>

 <url-pattern>/role/roleServlet.action</url-pattern>

 </servlet-mapping>

 <servlet-mapping>

 <servlet-name>ActionServlet</servlet-name>

 <url-pattern>/user/userServlet.action</url-pattern>

 </servlet-mapping>

抽取匯總的ServletAction

各業務Servlet中重復的一些業務代碼抽取出來,成為一個單獨的類UserAction, RoleAction

同時,forward的頁面轉向的Url也可以從這些單獨的類中返回;

這些單獨的類擁有同一個方法execute(),返回值為在forward的頁面轉向的Url,該方法中執行各自的業務邏輯,由此,抽象出他們共同的接口Iaction;

public interface IAction {

public String execute(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException ;

}

public class UserAction implements IAction{

public String execute(HttpServletRequest request,

HttpServletResponse response) throws ServletException, IOException {

//roleService.getList(name);

request.setAttribute("role", "role");

return "/user/user_list.jsp";

}

}

public class RoleAction implements IAction {

public String execute(HttpServletRequest request,

HttpServletResponse response) throws ServletException, IOException {

//userService.getList(name);

request.setAttribute("user", "user");

return "/user/role_list.jsp";

}

}

在匯總的ServletAction中只需要有一個IAction的引用,指向不同的子類對象;

public class ServletAction extends HttpServlet {

// 抽取以后;

protected void service(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

String path = request.getServletPath();

if(path.indexOf("/userServlet.action") >=0 ){

IAction action = new UserAction();

String url = action.execute(request, response);

this.getServletContext().getRequestDispatcher(url).forward(request, response);

}

if(path.indexOf("/roleServlet.action") >= 0) {

IAction action = new UserAction();

String url = action.execute(request, response);

this.getServletContext().getRequestDispatcher(url).forward(request, response);

}

}

}

由于每增加一個業務邏輯Action,都需要在匯總的ServletAction中進行判斷,代碼冗余繁瑣,所以需要動態調用每個Action

實現動態調用的思路:

得到一個map,key里面存放所有的ServletPath,value存放對應的類及jsp;

(以前我們實現動態調用使用反射機制)

分析現狀:得到每個ServletPath,根據每個ServletPath映射到不同的Action,從而取得要轉向的頁面;

解決辦法:寫一個struts-config.xml配置文件,定義每個ServletPath(web.xml中的url-patten),及對應的Servlet類(需要調用的Action類即子類對象),及對應的轉向頁面;

<?xml version="1.0" encoding="UTF-8"?>

<action-mappings>

<action path="/user/userServlet.action" type="com.bjsxt.struts.UserAction" forward="/user/user_list.jsp" />

<action path="/role/roleServlet.action" type="com.bjsxt.struts.RoleAction" forward="/user/role_list.jsp" />

</action-mappings>

如何解析這個xml文件呢?

使用jdom API,新建一個類XMLReader,其中定義read()方法;

引入jdom .jar文件

public class XMLReader {

//將xml文件中的一個標簽元素及其屬性存儲到一個Map中;

public static void read() {

SAXBuilder builder = new SAXBuilder();

Document doc = null;

Map map = new HashMap();

try {

doc = builder.build(Thread.currentThread().getContextClassLoader()

.getResourceAsStream("struts-config.xml"));

Element e = doc.getRootElement();

System.out.println(e);

List list = e.getChildren();

for(Iterator i= list.iterator(); i.hasNext();) {

ActionMapping am = new ActionMapping();

Element element = (Element)i.next();

am.setPath(element.getAttributeValue("path"));

am.setType(element.getAttributeValue("type"));

am.setForward(element.getAttributeValue("forward"));

//把一個ActionMapping放進Map中;使用put()方法;

map.put(element.getAttributeValue("path"), am);

}

} catch (JDOMException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

} catch (IOException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

}

       }        將解析得到的document,element的值放入一個map中;

為了使這個類只被ActionServlet調用一次,載入內存,其他任何類不得調用,重構這個XMLReader類的代碼:

map設置為靜態成員變量;

如果不采用在tomcat啟動的時候把XMLReader載入內存的方式的話,使用什么方法呢?

因為XMLReader運行在JVMTomcat下的調用機制是不同的,JVM是不需要用到該類就載入內存,而tomcat是用到該類才載入內存;

import org.jdom.JDOMException;

import org.jdom.input.SAXBuilder;

public class XMLReader {

private static Map map = new HashMap();

private static final XMLReader xr = new XMLReader();

private XMLReader(){

read();

}

public static XMLReader getInstance() {

return xr;

}

//將xml文件中的一個標簽元素及其屬性存儲到一個Map中;

private void read() {

SAXBuilder builder = new SAXBuilder();

Document doc = null;

try {

doc = builder.build(Thread.currentThread().getContextClassLoader()

.getResourceAsStream("struts-config.xml"));

Element e = doc.getRootElement();

System.out.println(e);

List list = e.getChildren();

for(Iterator i= list.iterator(); i.hasNext();) {

ActionMapping am = new ActionMapping();

Element element = (Element)i.next();

am.setPath(element.getAttributeValue("path"));

am.setType(element.getAttributeValue("type"));

am.setForward(element.getAttributeValue("forward"));

//把一個ActionMapping放進Map中;使用put()方法;

map.put(element.getAttributeValue("path"), am);

}

} catch (JDOMException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

} catch (IOException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

}

//定義一個根據key得到map中的值的方法;

public static ActionMapping getActionMapping(String path) {

return (ActionMapping)map.get(path);

}

public static void main(String[] args) {

getInstance().read();

}

ActionServlet調用XMLReader的代碼重構;

// 調用XMLReader;

protected void service(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

String path = request.getServletPath();

ActionMapping am = XMLReader.getActionMapping(path);

String forward = am.getForward()        ;

String type = am.getType();

IAction action = null;

try {

action = (IAction)Class.forName(type).newInstance();

action.execute(request, response);

} catch (InstantiationException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IllegalAccessException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (ClassNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

this.getServletContext().getRequestDispatcher(forward).forward(request, response);

}

以后如果增加新的業務,只需要增加Action類,配置文件中配置好就可以了

現在存在的問題:

直接Forward出去;用戶想更靈活,在Action中定義轉向的頁面;

業務中不同的條件forward到不同的頁面怎么辦;

辦法:改造配置文件中的forward屬性

<?xml version="1.0" encoding="UTF-8"?>

<action-mappings>

<action path="/user/userServlet.action" type="com.bjsxt.struts.UserAction" >

<forward name="sucsess" path="/user/user_list.jsp"></forward>

<forward name="failure" path="/user/user_list.jsp"></forward>

</action>

<action path="/role/roleServlet.action" type="com.bjsxt.struts.RoleAction" >

<forward name="sucsess" path="/user/role_list.jsp"></forward>

<forward name="failure" path="/user/role_list.jsp"></forward>

</action>

</action-mappings>

修改ActionMapping

package com.bjsxt.struts;

import java.util.Map;

public class ActionMapping {

private String path;

private String type;

private Map map;

public String getPath() {

return path;

}

public void setPath(String path) {

this.path = path;

}

public String getType() {

return type;

}

public void setType(String type) {

this.type = type;

}

public Map getMap() {

return map;

}

public void setMap(Map map) {

this.map = map;

}

}

修改讀取XML的類XMLReader

//將xml文件中的一個標簽元素及其屬性存儲到一個Map中;

private void read() {

SAXBuilder builder = new SAXBuilder();

Document doc = null;

try {

doc = builder.build(Thread.currentThread().getContextClassLoader()

.getResourceAsStream("struts-config.xml"));

Element e = doc.getRootElement();

System.out.println(e);

List list = e.getChildren();

for(Iterator i= list.iterator(); i.hasNext();) {

ActionMapping am = new ActionMapping();

Element element = (Element)i.next();

am.setPath(element.getAttributeValue("path"));

am.setType(element.getAttributeValue("type"));

//am.setForward(element.getAttributeValue("forward"));

List forward = element.getChildren();

Map m = new HashMap();

for(Iterator t= forward.iterator(); t.hasNext();) {

Element forwardemle = (Element)t.next();

m.put(forwardemle.getAttributeValue("name"), forwardemle.getAttributeValue("path"));

}

//把一個ActionMapping放進Map中;使用put()方法;

am.setMap(m);

map.put(element.getAttributeValue("path"), am);

}

} catch (JDOMException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

} catch (IOException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

}

修改ServletAction,以前是通過Map中的ActionMappinggetPath()轉向,改為通過UserAction返回的Path進行forward轉向;

// 調用XMLReader;

protected void service(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

String path = request.getServletPath();

ActionMapping am = XMLReader.getActionMapping(path);

//String forward = am.getForward()        ;

String type = am.getType();

IAction action = null;

String url = null;

try {

action = (IAction)Class.forName(type).newInstance();

url = action.execute(request, response);

} catch (InstantiationException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IllegalAccessException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (ClassNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

this.getServletContext().getRequestDispatcher(url).forward(request, response);

}

修改UserAction,增加判斷轉向邏輯;

public String execute(HttpServletRequest request,

HttpServletResponse response) throws ServletException, IOException {

//roleService.getList(name);

request.setAttribute("role", "role");

String path = request.getServletPath();

//需要得到ActionMapping;

ActionMapping am = XMLReader.getActionMapping(path);

//forward的兩個屬性放到map中了;

Map m = am.getMap();

/*

if(true) {

return(String) m.get("failure");

}*/

return (String)m.get("sucess");

}

存在的問題:

每一個Action,如UserAction都要得到ActionMapping,麻煩;

辦法:

ActionServlet中存在ActionMapping,把它當作參數傳到UserAction中;

public String execute(HttpServletRequest request,

HttpServletResponse response, ActionMapping am) throws ServletException, IOException {

//roleService.getList(name);

request.setAttribute("role", "role");

String path = request.getServletPath();

/*if(true) {

return(String) m.get("failure");

}*/

//return (String)am.getMap().get("sucess");

//改造ActionMapping類,增加getPath(String path)方法,得到Map中的getPath();

/*public String getPath(String path) {

return (String)map.get(path);

}*/

return am.getPath(path);

存在的問題:

sendRedirect不好用了

辦法:

重新設置配置文件;

<?xml version="1.0" encoding="UTF-8"?>

<action-mappings>

<action path="/user/userServlet.action" type="com.bjsxt.struts.UserAction" >

<forward name="sucsess" path="/user/user_list.jsp" redirect="false"></forward>

<forward name="failure" path="/user/user_list.jsp" redirect="false"></forward>

</action>

<action path="/role/roleServlet.action" type="com.bjsxt.struts.RoleAction" >

<forward name="sucsess" path="/user/role_list.jsp" redirect="true"></forward>

<forward name="failure" path="/user/role_list.jsp" redirect="true"></forward>

</action>

</action-mappings>

由于Forward有三個屬性,直接放在Map中不合適了,所以增加ActionForward類:

package com.bjsxt.struts;

public class ActionForward {

private String name;

private String path;

private boolean redirect;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getPath() {

return path;

}

public void setPath(String path) {

this.path = path;

}

public boolean isRedirect() {

return redirect;

}

public void setRedirect(boolean redirect) {

this.redirect = redirect;

}

}

修改XMLReader

private void read() {

SAXBuilder builder = new SAXBuilder();

Document doc = null;

try {

doc = builder.build(Thread.currentThread().getContextClassLoader()

.getResourceAsStream("struts-config.xml"));

Element e = doc.getRootElement();

System.out.println(e);

List list = e.getChildren();

for(Iterator i= list.iterator(); i.hasNext();) {

ActionMapping am = new ActionMapping();

Element element = (Element)i.next();

am.setPath(element.getAttributeValue("path"));

am.setType(element.getAttributeValue("type"));

//am.setForward(element.getAttributeValue("forward"));

List forward = element.getChildren();

Map m = new HashMap();

for(Iterator t= forward.iterator(); t.hasNext();) {

Element forwardemle = (Element)t.next();

ActionForward actionForward = new ActionForward();

actionForward.setName(forwardemle.getAttributeValue("name"));

actionForward.setPath(forwardemle.getAttributeValue("path"));

actionForward.setRedirect(Boolean.valueOf(forwardemle.getAttributeValue("redirect")));

m.put(forwardemle.getAttributeValue("name"),actionForward);

}

//把一個ActionMapping放進Map中;使用put()方法;

am.setMap(m);

map.put(element.getAttributeValue("path"), am);

}

} catch (JDOMException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

} catch (IOException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

}

修改UserAction增加返回值;

UserAction應該不只是返回URL,還應該返回isRedirect,所以,它應該返回一個ActionForward對象:

public ActionForward execute(HttpServletRequest request,

HttpServletResponse response, ActionMapping am) throws ServletException, IOException {

//roleService.getList(name);

request.setAttribute("role", "role");

//String path = request.getServletPath();

//改造ActionMapping類,增加getPath(String path)方法,得到Map中的getPath();

/*public ActionMapping getPath(String path) {

return (String)map.get(path);

}*/

return am.getPath("success");

}

根據傳過來的ActionForward對象,ServletAction判斷是forward還是sendRedirect?

protected void service(HttpServletRequest request,

HttpServletResponse response) throws ServletException, IOException {

String path = request.getServletPath();

ActionMapping am = XMLReader.getActionMapping(path);

// String forward = am.getForward() ;

String type = am.getType();

IAction action = null;

ActionForward actionForward = null;

try {

action = (IAction) Class.forName(type).newInstance();

actionForward = action.execute(request, response);

} catch (InstantiationException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IllegalAccessException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (ClassNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

if (actionForward.isRedirect()) {

response.sendRedirect(request.getContextPath()

+ actionForward.getPath());

} else {

this.getServletContext().getRequestDispatcher(

actionForward.getPath()).forward(request, response);

}

}

存在的問題:明天解決

解決request對象依賴過多的問題:

如何讓它自動映射,不需要從request.getParameter()拿數據.