struts2自定義MVC框架
本文實(shí)例為大家分享了struts2自定義MVC框架的方法,供大家參考,具體內(nèi)容如下
自定義MVC: (首先了解Model1和Model2的概念)
Model1與Model2:
Model1:就是一種純jsp開(kāi)發(fā)技術(shù),將業(yè)務(wù)邏輯代碼和視圖渲染代碼雜糅在一起。
Model2:Model2是在Model1的基礎(chǔ)上,將業(yè)務(wù)邏輯的代碼分離開(kāi)來(lái),單獨(dú)形成一個(gè)Servlet,Model2也是基于MVC開(kāi)發(fā)。
總結(jié)MVC特點(diǎn)如下:
(1)數(shù)據(jù)的獲取和顯示分離
(2)控制器將不同的模型和視圖組合在一起
(3)應(yīng)用分為三部分,三部分之間松耦合并協(xié)同工作,從而提高應(yīng)用的可擴(kuò)展性和可維護(hù)性
(4)各層負(fù)責(zé)不同的功能,各司其職,每一層的組件具有相同的特征,便于通過(guò)工程化和工具化產(chǎn)生程序代碼
MVC思想及其優(yōu)勢(shì)(很強(qiáng)勢(shì))
MVC是一種架構(gòu)模式,目的是將模型(業(yè)務(wù)邏輯)、視圖(表示層)分離,使模型和視圖可以獨(dú)立修改互不影響。大多數(shù)軟件在設(shè)計(jì)架構(gòu)時(shí)都采用此模式。使用MVC模式有很多處,當(dāng)一個(gè)通過(guò)瀏覽器瀏覽的系統(tǒng)想要開(kāi)發(fā)手機(jī)版本時(shí),只需要重新開(kāi)發(fā)視圖,模型部分的業(yè)務(wù)邏輯可以重用。許多軟件需要同時(shí)推出B/S和C/S版本,采用MVC模式,模型部分可以重用,只需要開(kāi)發(fā)不同的視圖即可。MVC思想將一個(gè)應(yīng)用分成三個(gè)基本部分M(Model,模型)V(View,視圖)C(Controller,控制器)。其中M表示處理業(yè)務(wù)邏輯的部分,V表示顯示數(shù)據(jù)和獲取用戶輸入的部分,C類似中介,保證M和V不會(huì)直接交互。

基本步驟如下:
1.創(chuàng)建XML文檔Framework.xml
2.定義Action接口
3.定義一個(gè)actionMapping類,視為action節(jié)點(diǎn)
4.定義ActionMappingManage類來(lái)管理ActionMapping類(actions節(jié)點(diǎn))
5.定義ActionManager類使用反射機(jī)制根據(jù)字符串類型的類名獲取到具體的類(web.xml標(biāo)簽的書(shū)寫(xiě))
6.編寫(xiě)servlet進(jìn)行運(yùn)行時(shí)機(jī)的控制
7.定義LoginAction類進(jìn)行測(cè)試
1.創(chuàng)建XML文檔Framework.xml
<!--?xml version="1.0" encoding="UTF-8"?-->
<!-- 定義約束文件 -->(標(biāo)注)
<!-- ELEMENT 表示元素 -->
<!-- ATTLIST 表示屬性 -->
<!-- CDATA 表示字符串類型 -->
<!-- REQUIRED 表示此屬性必須的寫(xiě) -->
<!-- *代表多個(gè) -->
<!-- IMPLIED 表示此屬性可寫(xiě) -->
<!-- redirect 重定向或轉(zhuǎn)發(fā) -->
<!--ELEMENT actions (action)-->
<!--ELEMENT action (result*)-->(*表示可以多個(gè))
<!--ATTLIST action name CDATA #REQUIRED
class CDATA #REQUIRED
-->
<!--ATTLIST RESULT name CDATA #IMPLIED
redirect (true|false) "false"
-->
]>
<framework>
<!-- 進(jìn)行測(cè)試 -->
<actions>
<action name="loginAction" class="cn.hq.Action.LoginAction">
<result name="success">success.jsp</result>
<result name="login">index.jsp</result>
</action>
</actions>
</framework>
注意:空格和<>的書(shū)寫(xiě)規(guī)范。
節(jié)點(diǎn)的層次。
2.定義Action接口

注意:excute參數(shù)的書(shū)寫(xiě),請(qǐng)求和響應(yīng)。
3.定義一個(gè)actionMapping類,視為action節(jié)點(diǎn)(進(jìn)行action節(jié)點(diǎn)的標(biāo)簽的書(shū)寫(xiě))


進(jìn)行封裝字段和results集合的添加數(shù)據(jù)。
注意:添加數(shù)據(jù)的書(shū)寫(xiě)。(Map集合)
4.定義ActionMappingManage類來(lái)管理ActionMapping類(actions節(jié)點(diǎn))
/*
* action節(jié)點(diǎn)不止一個(gè)
* 用來(lái)來(lái)管理ActionMapping類
*/
public class ActionMappingManager {
//actionMapping類的集合
private Map<String,ActionMapping> maps=new HashMap<String,ActionMapping>();
public ActionMapping getActionMapping(String name)
{
return maps.get(name);
}
//解析在src項(xiàng)目下的所有配置文件
//實(shí)例化完畢后進(jìn)行解析
public ActionMappingManager(String[] file){
for (String filename : file) {
Init(filename);
}
}
//init初始化方法
//解析xml文檔
public void Init(String path){
try {
InputStream is=this.getClass().getResourceAsStream("/"+path);
//解析xml
Document doc=new SAXReader().read(is);
//獲取根節(jié)點(diǎn)
Element root = doc.getRootElement();
//獲取actions節(jié)點(diǎn)
Element actions=(Element)root.elementIterator("actions").next();
//使用for循環(huán)來(lái)遍歷actions節(jié)點(diǎn)下的所有action節(jié)點(diǎn)
for(Iterator<Element> action=actions.elementIterator("action");action.hasNext();)
{
//獲取到<action>節(jié)點(diǎn)
Element actionnext = action.next();
//分別獲取到action節(jié)點(diǎn)中的name屬性和class屬性
String name = actionnext.attributeValue("name");
String classname = actionnext.attributeValue("class");
//將以上兩個(gè)屬性保存到ActionMapping類中
ActionMapping mapp=new ActionMapping();
mapp.setClassname(classname);
mapp.setName(name);
//由于一個(gè)action節(jié)點(diǎn)下有多個(gè)result節(jié)點(diǎn) 遍歷action下所有的result節(jié)點(diǎn)
for(Iterator<Element> result=actionnext.elementIterator("result");result.hasNext();)
{
//獲取到result節(jié)點(diǎn)
Element resultnext = result.next();
//提取result節(jié)點(diǎn)的name屬性值和result節(jié)點(diǎn)中的值
String resultname = resultnext.attributeValue("name");
String resultvalue=resultnext.getText();
//將其分別存入到actionMapping中的雙列集合中去,方便調(diào)用actionMapping類(actionMapping類中就有數(shù)據(jù)了!)
mapp.addResult(resultname, resultvalue);
System.out.println(mapp.getName());
}
//得到所有action節(jié)點(diǎn)的集合
maps.put(mapp.getName(), mapp);
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
概括:
通過(guò)dom4j解析Framework.xml配置文件。從而獲取根節(jié)點(diǎn),以及actions節(jié)點(diǎn),并通過(guò)for循環(huán)遍歷actions節(jié)點(diǎn)下的action節(jié)點(diǎn)拿到name和class的屬性值,由于一個(gè)action節(jié)點(diǎn)下有多個(gè)result節(jié)點(diǎn) 及遍歷action下所有的result節(jié)點(diǎn),分別存入到actionMapping中的雙列集合中,最后得到所有action節(jié)點(diǎn)的集合。
注意:Init方法的書(shū)寫(xiě),以及ActionMappingManager帶參數(shù)組的書(shū)寫(xiě)。
5.定義ActionManager類使用反射機(jī)制根據(jù)字符串類型的類名獲取到具體的類
public class ActionManager {
public static Action getActionClass(String classname)
{
Class clazz=null;
Action action=null;
//獲取當(dāng)前線程的類加載器
try {
//如果線程中的有那么一個(gè)類,直接根據(jù)類名獲取該類的類型
clazz=Thread.currentThread().getContextClassLoader().loadClass(classname);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(clazz==null)
{
try {
//如果該線程中沒(méi)有,那么使用class.forname方法獲取
clazz=Class.forName(classname);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(action==null)
{
try {
//將獲取到的類型轉(zhuǎn)換為action,調(diào)用無(wú)參構(gòu)造函數(shù),某種程度上相當(dāng)于new,不過(guò)new需要指定類型
action=(Action)clazz.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return action;
}
}
web.xml的節(jié)點(diǎn)配置:

6.編寫(xiě)servlet進(jìn)行運(yùn)行時(shí)機(jī)的控制(servlet,初始化所有的類)
public class MyServlet extends HttpServlet {
/**
*你很菜
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}<br>
/**
*繼續(xù)努力
*/
ActionMappingManager man=null;
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//獲取ActionMapping對(duì)象
ActionMapping actionMapping = man.getActionMapping(getPath(request));
//獲取action接口反射機(jī)制
Action action = ActionManager.getActionManager(actionMapping.getClassname());
try {
String message=action.execute(request, response);
String results = actionMapping.getResults(message);
response.sendRedirect(results);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
* 獲取請(qǐng)求的路徑名
*/
public String getPath(HttpServletRequest request){
//項(xiàng)目+請(qǐng)求地址
String requestURI = request.getRequestURI();
//項(xiàng)目名稱
String contextPath = request.getContextPath();
//具體請(qǐng)求
String path = requestURI.substring(contextPath.length());
String filename = path.substring(1,path.lastIndexOf("."));
return filename;
}
/*
*重寫(xiě)init,程序運(yùn)行加載所有類
*
*/
@Override
public void init(ServletConfig config) throws ServletException {
//config對(duì)象是javax.servlet.ServletConfig的對(duì)象,功能是獲得初始化配置信息
//config.getInitParameter是取得指定名稱的初始化參數(shù)內(nèi)容
String filename = config.getInitParameter("config");
String [] filenames=null;
if(filename==null){
//如果為空 ,
filenames=new String[]{"Framework.xml"};
}else{
//若果有其他的配置參數(shù)信息,那么以,分隔存入數(shù)組中
filenames=filename.split(",");
}
//使用init方法進(jìn)行初始化
man=new ActionMappingManager(filenames);
}
}
注意:代碼的層次及注釋。
7.定義LoginAction類進(jìn)行測(cè)試
public class LoginAction implements Action{
@Override
public String execute(HttpServletRequest request,
HttpServletResponse response) throws Exception {
String name = request.getParameter("name");
String pwd = request.getParameter("pwd");
if(name.equals("1")&&pwd.equals("1")){
return SUCCESS;
}else{
return LOGIN;
}
}
}
jsp代碼:

實(shí)現(xiàn)效果:

再長(zhǎng)的路,一步步也能走完,再短的路,不邁開(kāi)雙腳也無(wú)法到達(dá)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
如何使用BigDecimal實(shí)現(xiàn)Java開(kāi)發(fā)商業(yè)計(jì)算
這篇文章主要介紹了如何使用BigDecimal實(shí)現(xiàn)Java開(kāi)發(fā)商業(yè)計(jì)算,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
Spring中如何使用@Value注解實(shí)現(xiàn)給Bean屬性賦值
這篇文章主要介紹了Spring中如何使用@Value注解實(shí)現(xiàn)給Bean屬性賦值的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
String字符串轉(zhuǎn)BigDecimal時(shí),報(bào)NumberFormatException異常的解決
這篇文章主要介紹了String字符串轉(zhuǎn)BigDecimal時(shí),報(bào)NumberFormatException異常的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
Mybatis使用@one和@Many實(shí)現(xiàn)一對(duì)一及一對(duì)多關(guān)聯(lián)查詢
本文主要介紹了Mybatis使用@one和@Many實(shí)現(xiàn)一對(duì)一及一對(duì)多關(guān)聯(lián)查詢,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
java中ArrayList和LinkedList的區(qū)別詳解
這篇文章主要介紹了java中ArrayList和LinkedList的區(qū)別詳解,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2021-01-01
利用SpringDataJPA開(kāi)啟審計(jì)功能,自動(dòng)保存操作人操作時(shí)間
這篇文章主要介紹了利用SpringDataJPA開(kāi)啟審計(jì)功能,自動(dòng)保存操作人操作時(shí)間,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
SpringBoot項(xiàng)目使用?axis?調(diào)用webservice接口的實(shí)踐記錄
這篇文章主要介紹了SpringBoot項(xiàng)目使用?axis?調(diào)用webservice接口,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06
Java concurrency線程池之Callable和Future_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了Java concurrency線程池之Callable和Future,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
Hadoop 使用IntelliJ IDEA 進(jìn)行遠(yuǎn)程調(diào)試代碼的配置方法
這篇文章主要介紹了Hadoop 使用IntelliJ IDEA 進(jìn)行遠(yuǎn)程調(diào)試代碼的配置方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04

