【转】跨域问题 之 window.name

 

很早以前  写了个  Ext XMLHttpRequest 之外的 刷新


其中  (1) iframe  动态创建  onload 读取 iframe.innerHTML

只适合 同域下 主页面 无刷新 上传文件的情况  ,  当跨域访问 时 就不行了 。

(2) script 动态创建(每次创建设置定时器)   server 调用 回调函数,摧毁定时器  则是可以跨域取得数据的,当然这是Ext

跨域的标准做法。


iframe 下 跨域 暂时 知道 有两种方法 :

1. window.name 方法 ,见 转载 ,    附件zip代码可直接本地运行

2.window.location.hash 方法 ,parent,children 设置定时器 监控 url 的 #部分 ,具体待述




ps : 转载

d

使用 window.name 解决跨域问题                        


window.name 传输技术,原本是 Thomas Frank 用于解决 cookie 的一些劣势(每个域名 4 x 20 Kb 的限制、数据只能是字符串、设置和获取 cookie 语法的复杂等等)而发明的(详细见原文:《Session variables without cookies》 ),后来 Kris Zyp 在此方法的基础上强化了 window.name 传输 ,并引入到了 Dojo dojox.io.windowName ),用来解决跨域数据传输问题。
window.name 的美妙之处:name 值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。
window.name 传输技术的基本原理和步骤为:


name 在浏览器环境中是一个全局/window对象的属性,且当在 frame 中加载新页面时,name 的属性值依旧保持不变。通过在 iframe 中加载一个资源,该目标页面将设置 frame 的 name 属性。此 name 属性值可被获取到,以访问 Web 服务发送的信息。但 name 属性仅对相同域名的 frame 可访问。这意味着为了访问 name 属性,当远程 Web 服务页面被加载后,必须导航 frame 回到原始域。同源策略依旧防止其他 frame 访问 name 属性。一旦 name 属性获得,销毁 frame 。
在最顶层,name 属性是不安全的,对于所有后续页面,设置在 name 属性中的任何信息都是可获得的。然而 windowName 模块总是在一个 iframe 中加载资源,并且一旦获取到数据,或者当你在最顶层浏览了一个新页面,这个 iframe 将被销毁,所以其他页面永远访问不到 window.name 属性。
基本实现代码,基于 YUI ,源自克军写的样例

Js代码

  1. (function(){ 
  2.    var YUD = YAHOO.util.Dom, YUE = YAHOO.util.Event; 
  3.  
  4.    dataRequest = { 
  5.        _doc: document, 
  6.        cfg: { 
  7.            proxyUrl: 'proxy.html' 
  8.        } 
  9.    }; 
  10.  
  11.    dataRequest.send = function(sUrl, fnCallBack){ 
  12.        if(!sUrl || typeof sUrl !== 'string'){ 
  13.            return; 
  14.        } 
  15.  
  16.        sUrl += (sUrl.indexOf('?') > 0 ? '&' : '?') + 'windowname=true'; 
  17.  
  18.        var frame = this._doc.createElement('iframe'), state = 0, self = this; 
  19.        this._doc.body.appendChild(frame); 
  20.        frame.style.display = 'none'; 
  21.  
  22.        var clear = function(){ 
  23.            try{ 
  24.                frame.contentWindow.document.write(''); 
  25.                frame.contentWindow.close(); 
  26.                self._doc.body.removeChild(frame); 
  27.            }catch(e){} 
  28.        }; 
  29.  
  30.        var getData = function(){ 
  31.            try{ 
  32.                var da = frame.contentWindow.name; 
  33.            }catch(e){} 
  34.            clear(); 
  35.            if(fnCallBack && typeof fnCallBack === 'function'){ 
  36.                fnCallBack(da); 
  37.            } 
  38.        }; 
  39.  
  40.        YUE.on(frame, 'load', function(){ 
  41.            if(state === 1){ 
  42.                getData(); 
  43.            } else if(state === 0){ 
  44.                state = 1; 
  45.                frame.contentWindow.location = self.cfg.proxyUrl; 
  46.            } 
  47.        }); 
  48.  
  49.        frame.src = sUrl; 
  50.    }; 
  51. })(); 

(function(){
   var YUD = YAHOO.util.Dom, YUE = YAHOO.util.Event;

   dataRequest = {
       _doc: document,
       cfg: {
           proxyUrl: 'proxy.html'
       }
   };

   dataRequest.send = function(sUrl, fnCallBack){
       if(!sUrl || typeof sUrl !== 'string'){
           return;
       }

       sUrl += (sUrl.indexOf('?') > 0 ? '&' : '?') + 'windowname=true';

       var frame = this._doc.createElement('iframe'), state = 0, self = this;
       this._doc.body.appendChild(frame);
       frame.style.display = 'none';

       var clear = function(){
           try{
               frame.contentWindow.document.write('');
               frame.contentWindow.close();
               self._doc.body.removeChild(frame);
           }catch(e){}
       };

       var getData = function(){
           try{
               var da = frame.contentWindow.name;
           }catch(e){}
           clear();
           if(fnCallBack && typeof fnCallBack === 'function'){
               fnCallBack(da);
           }
       };

       YUE.on(frame, 'load', function(){
           if(state === 1){
               getData();
           } else if(state === 0){
               state = 1;
               frame.contentWindow.location = self.cfg.proxyUrl;
           }
       });

       frame.src = sUrl;
   };
})();


Web 服务器如何提供 window.name 数据
为了让 Web 服务器实现 window.name,服务器应该只寻找请求中是否包含 windowname 参数。如果包含了 windowname 参数,服务器应该返回一个设置了 window.name 字符串值的 HTML 文档,回应此请求并传送到客户端。例如:
http://www.planabc.net/getdata.html?windowname=true
如果服务器想用 Hello 响应客服端,它应该返回一个 HTML 页面:
Html代码

  1. <html> 
  2.    <script type="text/javascript"> 
  3.        window.name="Hello"; 
  4.    </script> 
  5. </html> 

<html>
   <script type="text/javascript">
       window.name="Hello";
   </script>
</html>




同样也可以转换为 JSON 数据:

Html代码

  1. <html> 
  2.    <script type="text/javascript"> 
  3.        window.name='{"foo":"bar"}'; 
  4.    </script> 
  5. </html> 

<html>
   <script type="text/javascript">
       window.name='{"foo":"bar"}';
   </script>
</html>


如果你手动创建资源,书写大量的多行的 JSON 对象为一个引用的字符串应该是比较困难的并且易于出错的。可以使用这样的 HTML 样例简单的创建 JSON 数据,将会转换为一个 JSON 字符串而无需手动转义 JSON 为字符串:

Html代码

  1. <html> 
  2.    <script type="\'text/javascript\'"> 
  3.        window.name = document.getElementsByTagName("script")[0].innerHTML.match(/temp\s*=([\w\W]*)/)[1]; 
  4.        temp= { 
  5.            foo:"bar", // put json data here 
  6.            baz:"foo" 
  7.        } 
  8.    </script> 
  9. </html> 

<html>
   <script type="\'text/javascript\'">
       window.name = document.getElementsByTagName("script")[0].innerHTML.match(/temp\s*=([\w\W]*)/)[1];
       temp= {
           foo:"bar", // put json data here
           baz:"foo"
       }
   </script>
</html>



同样的,如果你想传递 HTML/XML 数据,这里有一个样例实现,而无需手动将这些数据转换成字符串:

Html代码

  1. <html> 
  2.    <body> 
  3.        <p id="content"> 
  4.            some <strong>html/xml-style</strong>data 
  5.        </p> 
  6.    </body> 
  7.    <script type="text/javascript"> 
  8.        window.name = document.getElementById("content").innerHTML; 
  9.    </script> 
  10. </html> 

<html>
   <body>
       <p id="content">
           some <strong>html/xml-style</strong>data
       </p>
   </body>
   <script type="text/javascript">
       window.name = document.getElementById("content").innerHTML;
   </script>
</html>



window.name 传输技术相比其他的跨域传输的一些优势:

  1. 它是安全的。也就是说,它和其他的基于安全传输的 frame 一样安全,例如 Fragment Identifier messaging (FIM)和 Subspace 。(I)Frames 也有他们自己的安全问题,由于 frame 可以改变其他 frame 的 location,但是这个是非常不同的安全溢出,通常不太严重。
  2. 它比 FIM 更快,因为它不用处理小数据包大小的 Fragment Identifier ,并且它不会有更多的 IE 上的“机关枪”声音效果。它也比 Subspace 快,Subspace 需要加载两个 Iframe 和两个本地的 HTML 文件来处理一个请求。window.name 仅需要一个 Iframe 和一个本地文件。
  3. 它比 FIM 和 Subspace 更简单和安全。FIM 稍微复杂,而 Subspace 非常复杂。Subspace 也有一些额外的限制和安装要求,如预先声明所有的目标主机和拥有针对若干不同特殊主机的 DNS 入口。window.name 非常简单和容易使用。
  4. 它不需要任何插件(比如 Flash)或者替代技术(例如 Java)。

Continue reading 【转】跨域问题 之 window.name

itsnat--自定义控件入门和友好的url

As I see that itsnat referred this post as their tutorial, so I post a copy that in english, you can view it at  itsnat -- Custom components and friendly URLs .

 

itsnat 是个很有意思的java web框架,实现了“浏览器就是服务器”(The Browser Is The Server TBITS),在服务器端模仿了一个一般概念的W3C Java 浏览器,客户端动作通过AJAX发送到服务器端,并且转换为W3C Java DOM动作,在DOM服务器端改变结果自动发送到客户端,用JavaScript 更新客户端DOM。

要自定义一个组件,需要如下步骤:

1:监听模板

Java代码

>String html = "E:/projects/ItsNat/wb/test/WebRoot/apps/pto/frontpage.html"; ItsNatDocumentTemplate docTemplate = getItsNatHttpServlet().registerItsNatDocumentTemplate("pto","text/html", html); docTemplate.addItsNatServletRequestListener(new ItsNatServletRequestListener(){

Continue reading itsnat--自定义控件入门和友好的url

wicket tapestry5 sopo 模板实现浅析

1 Wicket实现

      Wicket模板是html格式,示例:index.html
Html代码

  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
  2. <html> 
  3. <head> 
  4.    <title>Index.html</title> 
  5.    
  6.    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 
  7.    <meta http-equiv="description" content="this is my page"> 
  8.    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> 
  9.    
  10.    <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 
  11.  
  12. </head> 
  13.  
  14. <body>  
  15.    <a wicket:id="edit" href="UserEdit.html?uid=1" target="_blank" >edit form</a> 
  16. </body> 
  17. </html> 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
   <title>Index.html</title>
  
   <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
   <meta http-equiv="description" content="this is my page">
   <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
  
   <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->

</head>

<body>
   <a wicket:id="edit" href="UserEdit.html?uid=1" target="_blank" >edit form</a>
</body>
</html>


还要在后台page类Index 中手动添加进组件列表中。
Java代码

  1. public class Index extends WebPage 
  2. /**
  3. * Constructor
  4. */ 
  5. public Index() 
  6.    PageLink link = new PageLink("edit",new IPageLink()); 
  7.    add(link); 

public class Index extends WebPage
{
/**
* Constructor
*/
public Index()
{
   PageLink link = new PageLink("edit",new IPageLink());
   add(link);
}
}


add方法是继承自父类org.apache.wicket.MarkupContainer的方法会将组件添加到其字段children中去.
模板由org.apache.wicket.markup.MarkupParser解析,遇到wicket:id属性的会转换为org.apache.wicket.markup.MarkupElement,
最终将html模板解析成MarkupElement列表,添加到org.apache.wicket.markup.MarkupList<MarkupElement> markupElements集合中,在组件绘制的时候,将其
包装成org.apache.wicket.markup.MarkupStream,会遍历MarkupElement列表,依据组件id获得组件,让每个组件进行绘制--调用方法
void org.apache.wicket.Component.render(MarkupStream markupStream).
具体的主要的解析实现是由org.apache.wicket.markup.parser.XmlPullParser完成的,通过过字符串操作来解析,详见其next方法,并没有使用第三方类库.
2 tapestry实现
       tapestry5模板时xml格式,示例Index.tml
Html代码

  1. <html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"> <head> 
  2. <title>Test</title> 
  3. </head> 
  4. <body> 
  5. <h1>Test</h1> 
  6. <h1>Address Book</h1> 
  7. <t:span c="d" >${fi}</t:span> 
  8. <ul> 
  9. <li> 
  10. <a t:type="pagelink" t:page="index" >Create new address</a> 
  11. </li> 
  12. </ul> 
  13. </body> </html> 

<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"> <head>
<title>Test</title>
</head>
<body>
<h1>Test</h1>
<h1>Address Book</h1>
<t:span c="d" >${fi}</t:span>
<ul>
<li>
<a t:type="pagelink" t:page="index" >Create new address</a>
</li>
</ul>
</body> </html>


因为已经在模板中指明了这个节点是什么类型的组件,所以,tapestry5就不需要再add组件了,它本身也不提供add方法。       
public class Index
Java代码

  1. @Inject 
  2. private Logger logger; 
  3. private GridDataSource dss; 
  4. private int fi; 
  5. public Index() 
  6. super(); 
  7. System.out.println("call ctor."); 
  8. public int getFi() 
  9. return fi; 
  10. public void setFi(int fi) 
  11. this.fi = fi; 

{
@Inject
private Logger logger;
private GridDataSource dss;
private int fi;
public Index()
{
super();
System.out.println("call ctor.");
}
public int getFi()
{
return fi;
}
public void setFi(int fi)
{
this.fi = fi;
}
}


           tapastry5使用stAx实现的,这篇文章介绍了stax的用法,tapestry5通过注入的方式将org.apache.tapestry5.internal.services.TemplateParserImpl注入到                                            
           org.apache.tapestry5.internal.services.ComponentTemplateSourceImpl中的private final TemplateParser parser;字段中,TemplateParserImpl
           实际使用的是org.apache.tapestry5.internal.services.StaxTemplateParser,在这里面会使用stax对模板进行解析。它通过节点是否有t:id,t:type属性来判断
           是否是一个服务端组件。解析完模板会组建成一个节点列表,再在绘制页面的时候依据这个列表的顺序来调用相应的组件绘制。
           逻辑主要在以下的类中
           org.apache.tapestry5.internal.parser.ComponentTemplateImpl
           org.apache.tapestry5.internal.structure.PageImpl
           org.apache.tapestry5.internal.services.PageRenderRequestHandlerImpl
           org.apache.tapestry5.internal.services.PageResponseRendererImpl
           org.apache.tapestry5.internal.services.PageMarkupRendererImpl
           org.apache.tapestry5.internal.services.PageRenderQueueImpl
           Page org.apache.tapestry5.internal.pageload.PageLoaderImpl.loadPage(String logicalPageName, Locale locale)

3 sopo的实现方法

     Sopo是可由每个page类来指明模板内容,只要是html格式就可以,示例:

Html代码

  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
  2. <html> 
  3. <head> 
  4.    <title>test.html</title> 
  5.    
  6.    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 
  7.    <meta http-equiv="description" content="this is my page"> 
  8.    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> 
  9.    
  10.    <link rel="stylesheet" type="text/css" href="./styles.css"> 
  11.    <script type="text/javascript" src="js/hello.js" ></script> 
  12.    <script type="text/javascript"> 
  13.       function $(id){ 
  14.           return document.getElementById(id); 
  15.       } 
  16.       function test() 
  17.       { 
  18.           $('rst').innerHTML=reg.test($('d').value); 
  19.       } 
  20.       var reg = new RegExp("^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$"); 
  21.       //var reg = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/i; 
  22.    </script> 
  23. </head> 
  24.  
  25. <body> 
  26. h-------- 
  27. <!-- hahah  --> 
  28.    <![CDATA[jkjkjk]]> 
  29.    <form action=""> 
  30.    <label stype="s:Label" id="lab1" >Hello World1<label stype="s:Label" id="lab2" >Hello World3</label></label> 
  31.    <input type="password" />    
  32.    <label stype="s:Label" id="lab3" >Hello World2</label> 
  33.    <input stype="s:Checkbox" id="chk" name="chk" >sss</input> 
  34.    <select stype="s:Select" id="sel" name="sel" width="20px" > 
  35.        <option stype="s:Option" text="1" ></option> 
  36.        <option stype="s:Option" text="2" selected="selected" ></option> 
  37.        <option stype="s:Option" text="3" ></option> 
  38.    </select>      
  39.    <input id="d" type="text" /><button onclick="test();">Test</button> 
  40.    <span id="rst">true</span> 
  41.    <input type="radio" name="1" >1</input> 
  42.    <input type="radio" name="1" >2</input> 
  43.    <input type="radio" name="1" onclick="alert(this.value);" >3</input>3 
  44.    </form> 
  45. </body> 
  46. </html> 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
   <title>test.html</title>
  
   <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
   <meta http-equiv="description" content="this is my page">
   <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
  
   <link rel="stylesheet" type="text/css" href="./styles.css">
   <script type="text/javascript" src="js/hello.js" ></script>
   <script type="text/javascript">
      function $(id){
          return document.getElementById(id);
      }
      function test()
      {
          $('rst').innerHTML=reg.test($('d').value);
      }
      var reg = new RegExp("^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$");
      //var reg = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/i;
   </script>
</head>

<body>
h--------
<!-- hahah  -->
   <![CDATA[jkjkjk]]>
   <form action="">
   <label stype="s:Label" id="lab1" >Hello World1<label stype="s:Label" id="lab2" >Hello World3</label></label>
   <input type="password" />   
   <label stype="s:Label" id="lab3" >Hello World2</label>
   <input stype="s:Checkbox" id="chk" name="chk" >sss</input>
   <select stype="s:Select" id="sel" name="sel" width="20px" >
       <option stype="s:Option" text="1" ></option>
       <option stype="s:Option" text="2" selected="selected" ></option>
       <option stype="s:Option" text="3" ></option>
   </select>     
   <input id="d" type="text" /><button onclick="test();">Test</button>
   <span id="rst">true</span>
   <input type="radio" name="1" >1</input>
   <input type="radio" name="1" >2</input>
   <input type="radio" name="1" onclick="alert(this.value);" >3</input>3
   </form>
</body>
</html>


它和tapestry有些像,因为模板里面指明了组件类型,所以就不需要再添加了.
Java代码

  1. public class Index extends Page 
  2.    @Override 
  3.    public String getTemplate() 
  4.    { 
  5.       try 
  6.       { 
  7.           return FileUtils.readFileToString(new File(getSession().getServletContext().getRealPath("Index.html"))); 
  8.       } 
  9.       catch (IOException e) 
  10.       {          
  11.           throw new RuntimeException(e);         
  12.       }      
  13.    } 
  14.    
  15.    @Override 
  16.    public void onLoad() 
  17.    { 
  18.       Label lab = (Label)getRoot().findComponent("lab3"); 
  19.       lab.addComponent(new Literal("<a href=\"#\">hi i am dynamic!!</a>")); 
  20.       Integer count = (Integer)getViewSate().get("count"); 
  21.       if (null == count) 
  22.       { 
  23.           count = 0; 
  24.       } 
  25.       count ++; 
  26.       getViewSate().put("count", count); 
  27.       Button btn = new Button("Ok" + count);    
  28.       lab.addComponent(btn); 
  29.    }   

public class Index extends Page
{
   @Override
   public String getTemplate()
   {
      try
      {
          return FileUtils.readFileToString(new File(getSession().getServletContext().getRealPath("Index.html")));
      }
      catch (IOException e)
      {         
          throw new RuntimeException(e);        
      }     
   }
  
   @Override
   public void onLoad()
   {
      Label lab = (Label)getRoot().findComponent("lab3");
      lab.addComponent(new Literal("<a href=\"#\">hi i am dynamic!!</a>"));
      Integer count = (Integer)getViewSate().get("count");
      if (null == count)
      {
          count = 0;
      }
      count ++;
      getViewSate().put("count", count);
      Button btn = new Button("Ok" + count);   
      lab.addComponent(btn);
   }  
}



     Sopo则是由neko解析模板,生成页面的组件树,web.sopo.template这个包下面包含了所有的模板解析类。每个page都有一个根组件
ComponentRoot web.sopo.page.Page.getRoot(),当开始绘制的时候则会从跟组件开始绘制。它的特点是可以在程序逻辑阶段动态的改变组件树的构造,上面的例子可以看到动态的加了个链接和按钮。使用了它的viewstate特性—存贮页面级变量,这和asp.net很像。

比较

     这三种都支持模板(包括页面模板和组件模板),共同特点是模板是html格式,美工可以直接编辑模板,没有讨厌的jsp标签.wicket取经于 tapestry,tapestry取经于asp.net,而sopo也是学asp.net并且和它最像。Wicket需要后台add对应模板的组件,通过匹配,这样做虽然可以动态的决定绘制组件的类型但是也比较繁琐,它类似于swing的方式,但是Mode这个概念入侵很大,通过session来保持状态。tapestry通过模板和组件的绘制来展示页面,不允许你new 一个组件,并且和prototype, scriptaculous集成了,它的performance是这三个中最快的,虽然page和组件都是pojo,但是有注入依赖,到底这个特性有没有用那是见仁见智了。Sopo则是比较灵活,可以动态的修改组件树,和asp.net非常接近,写组件和tapestry一样非常清晰,概念和实现都很单,缺点是它的性能只适用于中小型应用。

Continue reading wicket tapestry5 sopo 模板实现浅析

struts2 自定义tiles.xml文件路径

struts2+tiles时,tiles.xml默认是放在文件夹/web-inf/下面,使用ServletContext的方法查找,一般不需要改动,但是遇到BT的要求需要自定义这个titles的路径查找方式时,可以使用如下方法:
1:在web.xml里面配置自定义监听器:


Xml代码

  1. <listener> 
  2.        <listener-class>demo.MyStrutsTilesListener</listener-class> 
  3.    </listener> 

2:实现demo.MyStrutsTilesListener这个类,它继承自org.apache.struts2.tiles.StrutsTilesListener,重载方法


Java代码

  1. protected ServletContext decorate(ServletContext context)  
  2.    Map<String, String> INIT = new HashMap<String, String>(); 
  3.        INIT.put(TilesContainerFactory.CONTAINER_FACTORY_INIT_PARAM,  StrutsTilesContainerFactory.class.getName()); 
  4.    ServletContext servletContext = new MyTilesContext(context,INIT); 
  5.         
  6.    return servletContext; 

3:实现MyTilesContext:

Java代码

  1. public class CyberTilesContext extends ConfiguredServletContext 
  2.    public static final String PREFIX = "file:///"; 
  3.     
  4.    public CyberTilesContext(ServletContext context, Map<String, String> initParameters) 
  5.    { 
  6.        super(context, initParameters); 
  7.    } 
  8.  
  9.    @Override 
  10.    public URL getResource(String string) throws MalformedURLException 
  11.    { 
  12.        if (!string.startsWith(PREFIX)) 
  13.        { 
  14.            return super.getResource(string);    
  15.        } 
  16.         
  17.        String path = string.substring(PREFIX.length()); 
  18.        File file = new File(path); 
  19.        if (!file.exists()) 
  20.        { 
  21.            throw new RuntimeException("file " + path + " not founded."); 
  22.        } 
  23.         
  24.        return file.toURI().toURL(); 
  25.    } 

通过重载getResource方法可以定制自己所需要的查找tiles.xml的方法,上面的例子就是实现以file:///开头查找绝对路径下的tiles.xml。

PS:很不喜欢struts2,对于我来讲,它不适合快速开发,它也不适合大型网站。

Continue reading struts2 自定义tiles.xml文件路径

【转】项目管理工具

项目管理工具(project management tool) :
用来支持软件生产中项目管理活动的软件。通常的软件项目管理活动包括项目的计划、调度、通信、费用估算、资源分配以及质量控制等。软件生产是智力密集型的活动,其产品无物理外形,生产状态也“不可见”,因而难于检查和驾驭。软件项目管理工具就是要使这种生产过程成为可见、可控的过程。使用它能帮助进行成本估算、作业调度和任务分配,并制定出成本较低、风险较小的项目开发计划;同时能设法在预计工期和经费之内适当调整项目的安排,以节省时间和人力,从而对软件生产的各个环节进行严格、科学的管理,使项目开发活动获得最佳的进程。
项目管理工具能对项目的任务调度、成本估算、资源分配、预算跟踪、人时统计、配置控制等活动给予帮助,它具有以下一些特征:

(1)覆盖整个软件生存周期;

(2)为项目调度提供多种有效手段;

(3)利用估算模型对软件费用和工作量进行估算;

(4)支持多个项目和子项目的管理;

(5)确定关键路径,松弛时间,超前时间和滞后时间;

(6)对项目组成员和项目任务之间的通信给予辅助;

(7)自动进行资源平衡;

(8)跟踪资源的使用;

(9)生成固定格式的报表和剪裁项目报告。


     项目管理工具通常都支持PERT和Gantt图。
     PERT是计划评价与评审技术。该技术把网络方法用于工作计划安排的评审和检查。通常以带箭头的边表示活动,边的起讫结点表示活动的开始事件和结束事件,边的长度表示该活动的工作量或工期,各结点的顺序反映了各个活动在时序上的制约关系。利用PERT的网络图能求出关键路径和松弛时间,并能对计划的各个活动和资源分配等进行调整。
     Gantt图是一种二维横道图,它广泛用于各种工程活动的进度计划管理。图的横坐标为时间轴,每个活动用一条水平线段表示,其起讫点对应的横坐标值即为该活动的开始和结束时间。

     尽管新的项目管理方法和技术会改变人们已经习惯的工作方式,学习和掌握新工具也要花费一些时间,但是使用自动项目管理工具比用手工方法管理有许多优点,如:
       (1)能对大型项目进行精确跟踪,使项目经理能及时掌握实际工作进展和实际资源                  消耗情况。

(2)能辅助开发PERT,CPM(关键路径方法)和WBS(工作分解结构),自动更新活动网络图和 Gantt图。

(3)能自动计算、自动积累数据、自动生成图形和报表来取代人工计算、调度、统计和文档工作,提高管理工作效率。


国内外已有许多可用于项目管理活动的通用或专用的产品,如
Microsoft公司的Project,
Lotus公司的Notes和Orgnizer,
Primavera System公司的Primavera Project Planner等

Continue reading 【转】项目管理工具

【转】深入浅出OOD(一)

深入浅出OOD(一)
撰文/透明
有物昆成,先天地生。萧呵!谬呵!独立而不改,可以为天地母。吾未知其名,字之曰
道。吾强为之名曰大,大曰逝,逝曰远,远曰反。道大,天大,地大,王亦大。
——《道德经》,第二十五章
软件不软
从 60 年代的软件危机,到今天传统软件工程方法处处碰壁的处境,都说明一个问题:
软件不软(Software is Hard)[Martin, 95]。说实话,软件是一块硬骨头,真正开发过软
件的人都会有此感觉。一个应用总是包含无数错综复杂的细节,而软件开发者则要把所
有这些细节都组织起来,使之形成一个可以正常运转的程序,这实在不是一件简单的事。
为什么会这样?举个例子来说:用户可以很轻松地说“我要一个字处理软件”,他觉得
“字处理软件”这样一个概念是再清楚不过的了,根本不需要更多的描述;而真正开发
一个字处理软件却是一件困难无比的事情——我曾经亲眼看到开发字处理软件的人们
是怎样受尽折磨的。为什么表述一个概念很容易,而实现一个概念很困难?因为人们太
擅长抽象、太擅长剥离细节问题了。
软件不软,症结就在这里:用户很容易抽象地表达自己的需求,而这种抽象却很难转化
为程序代码。软件不软,因为很简单的设想也需要大量的时间去实现;软件不软,因为
满足用户的需求和期望实在太困难;软件不软,因为软件太容易让用户产生幻想。
而另一方面,计算机硬件技术却在飞速发展。从几十年前神秘的庞然大物,到现在随身
携带的移动芯片;从每秒数千次运算到每秒上百亿次运算。当软件开发者们还在寻找能
让软件开发生产力提高一个数量级的“银弹”[Brooks, 95]时,硬件开发的生产力早已提
升了百倍千倍。这是为什么?
硬件工程师们能够如此高效,是因为他们都很懒惰。他们永远恪守“不要去重新发明轮
子”的古训,他们尽量利用别人的成果。你看到有硬件工程师自己设计拨码开关的吗?
你看到有硬件工程师自己设计低通滤波电路的吗?你看到有硬件工程师自己设计计时
器的吗?他们有一套非常好的封装技术,他们可以把电路封装在一个接插件里面,只露
出接口。别人要用的时候,只管按照接口去用,完全不必操心接插件内部的实现。
而软件工程师们呢?在 STL成为C++标准之前(甚至之后),每个C++程序员都写过自
己的排序算法和链表,并认为自己比别人写得更好⋯⋯真是令人伤心。
OOD 可以让软件稍微“软”一点
软件不软,不过OOD可以帮助它稍微“软”一点。OOD为我们提供了封装某一层面上
的功能和复杂性的工具。使用OOD,我们可以创建黑箱软件模块,将一大堆复杂的东
西藏到一个简单的接口背后。然后,软件工程师们就可以使用标准的软件技术把这些黑
箱组合起来,形成他们想要的应用程序。
Grady Booch 把这些黑箱称为类属(class category),现在我们则通常把它们称为“组件
(component)”。类属是由被称为类(class)的实体组成的,类与类之间通过关联
(relationship)结合在一起。一个类可以把大量的细节隐藏起来,只露出一个简单的接
口,这正好符合人们喜欢抽象的心理。所以,这是一个非常伟大的概念,因为它给我们
提供了封装和复用的基础,让我们可以从问题的角度来看问题,而不是从机器的角度来
看问题。
软件的复用最初是从函数库和类库开始的,这两种复用形式实际上都是白箱复用。到 90
年代,开始有人开发并出售真正的黑箱软件模块:框架(framework)和控件(control)。
框架和控件往往还受平台和语言的限制,现在软件技术的新潮流是用SOAP 作为传输介
质的Web Service,它可以使软件模块脱离平台和语言的束缚,实现更高程度的复用。
但是想一想,其实Web Service 也是面向对象,只不过是把类与类之间的关联用XML
来描述而已[Li, 02]。在过去的十多年里,面向对象技术对软件行业起到了极大的推动作
用。在可以预测的将来,它仍将是软件设计的主要技术——至少我看不到有什么技术可
以取代它的。
上面,我向读者介绍了一些背景知识,也稍微介绍了 OOD 的好处。下面,我将回答几
个常见的问题,希望能借这几个问题让读者看清OOD 的轮廓。
什么是 OOD?
面向对象设计(Object-Oriented Design,OOD)是一种软件设计方法,是一种工程化规
范。这是毫无疑问的。按照Bjarne Stroustrup 的说法,面向对象的编程范式(paradigm)
是[Stroustrup, 97]:
l 决定你要的类;
l 给每个类提供完整的一组操作;
l 明确地使用继承来表现共同点。
由这个定义,我们可以看出:OOD 就是“根据需求决定所需的类、类的操作以及类之
间关联的过程”。
OOD 的目标是管理程序内部各部分的相互依赖。为了达到这个目标,OOD要求将程序
分成块,每个块的规模应该小到可以管理的程度,然后分别将各个块隐藏在接口
(interface)的后面,让它们只通过接口相互交流。比如说,如果用OOD 的方法来设计
一个服务器-客户端(client-server)应用,那么服务器和客户端之间不应该有直接的依
赖,而是应该让服务器的接口和客户端的接口相互依赖。
这种依赖关系的转换使得系统的各部分具有了可复用性。还是拿上面那个例子来说,客
户端就不必依赖于特定的服务器,所以就可以复用到其他的环境下。如果要复用某一个
程序块,只要实现必须的接口就行了。
OOD 是一种解决软件问题的设计范式(paradigm),一种抽象的范式。使用OOD 这种
设计范式,我们可以用对象(object)来表现问题领域(problem domain)的实体,每个
对象都有相应的状态和行为。我们刚才说到:OOD 是一种抽象的范式。抽象可以分成
很多层次,从非常概括的到非常特殊的都有,而对象可能处于任何一个抽象层次上。另
外,彼此不同但又互有关联的对象可以共同构成抽象:只要这些对象之间有相似性,就
可以把它们当成同一类的对象来处理。
OOD 到底从哪儿来?
有很多人都认为:OOD是对结构化设计(Structured Design,SD)的扩展,其实这是不
对的。OOD 的软件设计观念和SD 完全不同。SD 注重的是数据结构和处理数据结构的
过程。而在OOD 中,过程和数据结构都被对象隐藏起来,两者几乎是互不相关的。不
过,追根溯源,OOD 和SD 有着非常深的渊源。
1967 年前后,OOD 和SD 的概念几乎同时诞生,它们分别以不同的方式来表现数据结
构和算法。当时,围绕着这两个概念,很多科学家写了大量的论文。其中,由Dijkstra
和Hoare 两人所写的一些论文讲到了“恰当的程序控制结构”这个话题,声称goto 语句
是有害的,应该用顺序、循环、分支这三种控制结构来构成整个程序流程。这些概念发
展构成了结构化程序设计方法;而由Ole-Johan Dahl 所写的另一些论文则主要讨论编程
语言中的单位划分,其中的一种程序单位就是类,它已经拥有了面向对象程序设计的主
要特征。
这两种概念立刻就分道扬镳了。在结构化这边的历史大家都很熟悉:NATO会议采纳了
Dijkstra 的思想,整个软件产业都同意goto 语句的确是有害的,结构化方法、瀑布模型
从70 年代开始大行其道。同时,无数的科学家和软件工程师也帮助结构化方法不断发
展完善,其中有很多今天足以使我们振聋发聩的名字,例如Constantine、Yourdon、
DeMarco 和Dijkstra。有很长一段时间,整个世界都相信:结构化方法就是拯救软件工
业的“银弹”。当然,时间最后证明了一切。
而此时,面向对象则在研究和教育领域缓慢发展。结构化程序设计几乎可以应用于任何
编程语言之上,而面向对象程序设计则需要语言的支持1,这也妨碍了面向对象技术的
发展。实际上,在60 年代后期,支持面向对象特性的语言只有Simula-67 这一种。到
70 年代,施乐帕洛阿尔托研究中心(PARC)的Alan Key 等人又发明了另一种基于面向
对象方法的语言,那就是大名鼎鼎的Smalltalk。但是,直到80 年代中期,Smalltalk 和
另外几种面向对象语言仍然只停留在实验室里。
到 90 年代,OOD突然就风靡了整个软件行业,这绝对是软件开发史上的一次革命。不
过,登高才能望远,新事物总是站在旧事物的基础之上的。70 年代和80 年代的设计方
法揭示出许多有价值的概念,谁都不能也不敢忽视它们,OOD 也一样。
OOD 和传统方法有什么区别?
还记得结构化设计方法吗?程序被划分成许多个模块,这些模块被组织成一个树型结
构。这棵树的根就是主模块,叶子就是工具模块和最低级的功能模块。同时,这棵树也
表示调用结构:每个模块都调用自己的直接下级模块,并被自己的直接上级模块调用。
那么,哪个模块负责收集应用程序最重要的那些策略?当然是最顶端的那些。在底下的
那些模块只管实现最小的细节,最顶端的模块关心规模最大的问题。所以,在这个体系
结构中越靠上,概念的抽象层次就越高,也越接近问题领域;体系结构中位置越低,概
念就越接近细节,与问题领域的关系就越少,而与解决方案领域的关系就越多。
但是,由于上方的模块需要调用下方的模块,所以这些上方的模块就依赖于下方的细节。
换句话说,与问题领域相关的抽象要依赖于与问题领域无关的细节!这也就是说,当实
现细节发生变化时,抽象也会受到影响。而且,如果我们想复用某一个抽象的话,就必
须把它依赖的细节都一起拖过去。
而在 OOD 中,我们希望倒转这种依赖关系:我们创建的抽象不依赖于任何细节,而细
节则高度依赖于上面的抽象。这种依赖关系的倒转正是OOD 和传统技术之间根本的差
异,也正是OOD 思想的精华所在。
OOD 能给我带来什么?
问这个问题的人,脑子里通常是在想“OOD 能解决所有的设计问题吗?”没有银弹。
1 我听见有人说“我可以用 C 语言实现面向对象”,不过我希望你不会说“我也喜欢这样做”。很明显,
如果没有语言特性的支持,面向对象方法将寸步难行。其实结构化设计也是一样,不过几乎所有的编
程语言都提供了对三种基本流程结构的支持,所以基本不会遇到这个问题。
OOD 也不是解决一切设计问题、避免软件危机、捍卫世界和平⋯⋯的银弹。OOD 只是
一种技术。但是,它是一种优秀的技术,它可以很好地解决目前的大多数软件设计问题
——当然,这要求设计者有足够的能力。
OOD 可能会让你头疼,因为要学会它、掌握它是很困难的;OOD甚至会让你失望,因
为它也并不成熟、并不完美。OOD 也会给你带来欣喜,它让你可以专注于设计,而不
必操心那些细枝末节;OOD 也会使你成为一个更好的设计师,它能提供给你很好的工
具,让你能开发出更坚固、更可维护、更可复用的软件。
C++是一种“真正的”面向对象编程语言吗?
最后这个问题和我们今天的主题关系不大,不过这是一个由来已久的问题,而且以后也
不一定会有合适的时机说明这个问题,所以今天一起回答了。
很多人都觉得 C++缺少“真正的”面向对象语言所必须的一些特性,例如垃圾收集
(garbage collection)、多分配(multiple-dispatch)之类的。但是,缺少这些特性并不影
响开发者们用C++实现面向对象的设计思路。
在我看来,任何语言,只要它直接支持面向对象设计的实现,那它就是“真正的”面向
对象语言。用这个标准来评价,C++是完全符合的:它直接支持继承、多态、封装和抽
象,而这些才是面向对象最重要的。而VB 和C 这样的语言不能直接支持这些(尽管可
以用特殊的技巧来实现),所以不是“真正的”面向对象语言。
参考书目
l [Brooks, 95] Frederick Brooks, The Mythical Man-Month, Addison-Wesley, 1995.
l [Li, 02] 李维,《Delphi 6/Kylix 2 SOAP/Web Service 程序设计篇》,机械工业出
版社,2002 年。
l [Martin, 95] Robert Martin, Designing Object-Oriented C++ Applications Using
the Booch Method, Prentice-Hall, 1995.
l [Stroustrup, 97] Bjarne Stroustrup, The C++ Programming Language (Special
Edition), Addison-Wesley, 1997.

Continue reading 【转】深入浅出OOD(一)

nio 和 web 线程

见文章 http://kazge.com/archives/275.html 讲得比较详细。

再看 http://www.ibm.com/developerworks/cn/java/j-nioserver/

看看 http://zddava.iteye.com/blog/835244

综上所述,我认为nio并不能对web 服务器性能提高很大因为每个servlet还是一个线程,这样与没有使用nio的情况是一样的。??

现在看看[IO 接口,设备](https://blog.kazge.com/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/2011/10/21/io-e6-8e-a5-e5-8f-a3-ef-bc-8c-e8-ae-be-e5-a4-87-ef-bc-8c-e6-93-8d-e4-bd-9c/),这篇文章分析的比较细。nio跟更像是多路io,性能还是能够提升的!

Continue reading nio 和 web 线程

【转】UML用例图中包含(include)、扩展(extend)和泛化(generalization)三种关系详解

 

共性:都是从现有的用例中抽取出公共的那部分信息,作为一个单独的用例,然后通后过不同的方法来重用这个公共的用例,以减少模型维护的工作量。

1、包含(include)

 

    包含关系:使用包含(Inclusion)用例来封装一组跨越多个用例的相似动作(行为片断),以便多个基(Base)用例复用。基用例控制与包含用例的 关系,以及被包含用例的事件流是否会插入到基用例的事件流中。基用例可以依赖包含用例执行的结果,但是双方都不能访问对方的属性。 

   包含关系对典型的应用就是复用,也就是定义中说的情景。但是有时当某用例的事件流过于复杂时,为了简化用例的描述,我们也可以把某一段事件流抽象成为一个被包含的用例;相反,用例划分太细时,也可以抽象出一个基用例,来包含这些细颗粒的用例。这种情况类似于在过程设计语言中,将程序的某一段算法封装成一个子过程,然后再从主程序中调用这一子过程。

   例如:业务中,总是存在着维护某某信息的功能,如果将它作为一个用例,那新建、编辑以及修改都要在用例详述中描述,过于复杂;如果分成新建用例、编辑用例和删除用例,则划分太细。这时包含关系可以用来理清关系。

2、扩展(extend)

扩展关系:将基用例中一段相对独立并且可选的动作,用扩展(Extension)用例加以封装,再让它从基用例中声明的扩展点(Extension Point)上进行扩展,从而使基用例行为更简练和目标更集中。扩展用例为基用例添加新的行为。扩展用例可以访问基用例的属性,因此它能根据基用例中扩展点的当前状态来判断是否执行自己。但是扩展用例对基用例不可见。

对于一个扩展用例,可以在基用例上有几个扩展点。   

例如,系统中允许用户对查询的结果进行导出、打印。对于查询而言,能不能导出、打印查询都是一样的,导出、打印是不可见的。导入、打印和查询相对独立,而且为查询添加了新行为。因此可以采用扩展关系来描述:

 

4、泛化(generalization)

 

泛化关系:子用例和父用例相似,但表现出更特别的行为;子用例将继承父用例的所有结构、行为和关系。子用例可以使用父用例的一段行为,也可以重载它。父用例通常是抽象的。在实际应用中很少使用泛化关系,子用例中的特殊行为都可以作为父用例中的备选流存在。

例如,业务中可能存在许多需要部门领导审批的事情,但是领导审批的流程是很相似的,这时可以做成泛化关系表示: 

 

上面是我参考的一篇文章,觉得将三种关系的区别讲得很清晰,在此基础上结合自己的系统,对项目(在线购物系统)的用例做了整体的描绘。

    *****************************************************************

    (1)系统整体用例图

按照先整体用例,后子系统用例来进行描绘的,欢迎大家提出好的建议!


转:UML中扩展和泛化的区别 

         泛化表示类似于OO术语“继承”或“多态”。UML中的Use Case泛化过程是将不同Use Case之间的可合并部分抽象成独立的父Use Case,并将不可合并部分单独成各自的子Use Case;包含以及扩展过程与泛化过程类似,但三者对用例关系的优化侧重点是不同的。如下:
          ●泛化侧重表示子用例间的互斥性;
          ●包含侧重表示被包含用例对Actor提供服务的间接性;
          ●扩展侧重表示扩展用例的触发不定性;详述如下:


       
既然用例是系统提供服务的UML表述,那么服务这个过程在所有用例场景中是必然发生的,但发生按照发生条件可分为如下两种情况:
         ⒈无条件发生:肯定发生的;
         ⒉有条件发生:未必发生,发生与否取决于系统状态;

         因此,针对用例的三种关系结合系统状态考虑,泛化与包含用例属于无条件发生的用例,而扩展属于有条件发生的用例。进一步,用例的存在是为Actor提供服 务,但用例提供服务的方式可分为间接和直接两种,依据于此,泛化中的子用例提供的是直接服务,而包含中的被包含用例提供的是间接服务。同样,扩展用例提供的也是直接服务,但扩展用例的发生是有条件的。

         另外一点需要提及的是:泛化中的子用例和扩展中的扩展用例均可以作为基本用例事件的备选择流而存在。


试题中抽象用例和使用关系我觉得就是指包含关系中的描述。

Continue reading 【转】UML用例图中包含(include)、扩展(extend)和泛化(generalization)三种关系详解

MySQL Workbench使用方法

要检查默认的启动/停止/状态检查命令是否是你设置的对应的mysql服务的名称 home/serveradmin/manage server instance

例如sc start mysql51 中mysql51 要对应实际的服务名称(不区分大小写)



MySQL Workbench is a visual database design tool recently released by MySQL AB. The tool is specifically for designing MySQL database.

MySQL Workbench has many functions and features; this article by Djoni Darmawikarta shows some of them by way of an example. We’ll build a physical data model for an order system where an order can be a sale order or a purchase order, and then, forward-engineer our model into an MySQL database.

MySQL Workbench is a visual database design tool recently released by MySQL AB. The tool is specifically for designing MySQL database.

What you build in MySQL Workbench is called physical data model. A physical data model is a data model for a specific RDBMS product; the model in this article will have some MySQL unique specifications. We can generate (forward-engineer) the database objects from its physical model, which in addition to tables and their columns, can also include other objects such as view.

MySQL Workbench has many functions and features; this article by Djoni Darmawikarta shows some of them by way of an example. We’ll build a physical data model for an order system where an order can be a sale order or a purchase order; and then, forward-engineer our model into an MySQL database.

The physical model of our example in EER diagram will look like in the following MySQL Workbench screenshot.

Visual MySQL Database Design in MySQL Workbench

Creating ORDER Schema

Let’s first create a schema where we want to store our order physical model. Click the + button (circled in red).

Visual MySQL Database Design in MySQL Workbench

Change the new schema’s default name to ORDER. Notice that when you’re typing in the schema name, its tab name on the Physical Schemata also changes accordingly—a nice feature.

The order schema is added to the Catalog (I circled the order schema and its objects in red).

Visual MySQL Database Design in MySQL Workbench

Close the schema window. Confirm to rename the schema when prompted.

Visual MySQL Database Design in MySQL Workbench

Creating Order Tables

We’ll now create three tables that model the order: ORDER table and its two subtype tables: SALES_ORDER and PURCHASE_ORDER, in the ORDER schema. First of all, make sure you select the ORDER schema tab, so that the tables we’ll create will be in this schema.

We’ll create our tables as EER diagram (EER = Enhanced Entity Relationship). So, double-click the Add Diagram button.

Visual MySQL Database Design in MySQL Workbench

Select (click) the Table icon, and then move your mouse onto the EER Diagram canvas and click on the location you want to place the first table.

Visual MySQL Database Design in MySQL Workbench

Visual MySQL Database Design in MySQL Workbench

Repeat for the other two tables. You can move around the tables by dragging and dropping.

Visual MySQL Database Design in MySQL Workbench

Next, we’ll work on table1, which we’ll do so using the Workbench’s table editor. We start the table editor by right-clicking the table1 and selecting Edit Table.

Visual MySQL Database Design in MySQL Workbench

Next, we’ll work on table1, which we’ll do so using the Workbench’s table editor. We start the table editor by right-clicking the table1 and selecting Edit Table.

Rename the table by typing in ORDER over table1.

Visual MySQL Database Design in MySQL Workbench

We’ll next add its columns, so select the Columns tab. Replace idORDER column name with ORDER_NO.

Visual MySQL Database Design in MySQL Workbench

Select INT as the data type from the drop-down list.

Visual MySQL Database Design in MySQL Workbench

We’d like this ORDER_NO column to be valued incrementally by MySQL database, so we specify it as AI column (Auto Increment).

AI is a specific feature of MySQL database.

Visual MySQL Database Design in MySQL Workbench

You can also specify other physical attributes of the table, such as its Collation; as well as other advanced options, such as its trigger and partioning (the Trigger and Partioning tabs).

Visual MySQL Database Design in MySQL Workbench

Notice that on the diagram our table1 has changed to ORDER, and it has its first column, ORDER_NO. In the Catalog you can also see the three tables.

The black dots on the right of the tables indicate that they’ve been included in an diagram.

Visual MySQL Database Design in MySQL Workbench

 


If you expand the ORDER folder, you’ll see the ORDER_NO column. As we define the column as a primary key, it has a key icon on its left.

Visual MySQL Database Design in MySQL Workbench

Back to the table editor, add the other columns: ORDER_DATE and ORDER_TYPE. The ORDER_TYPE can have one of two values: S for sales order, P for purchase order. As sales order is more common, we’d like to specify it as the column’s default value.

You add the next column by double-clicking the white space below the last column.

Visual MySQL Database Design in MySQL Workbench

In the same way, create the SALES_ORDER table and its columns.

Visual MySQL Database Design in MySQL Workbench

Lastly, create the PURCHASE_ORDER table and its columns.

Visual MySQL Database Design in MySQL Workbench

Create Relationships

We have now created all three tables and their columns. We haven’t done yet with our model; we still need to create the subtype relationships of our tables.

The SALES_ORDER is a subtype of ORDER, implying their relationship is 1:1 with the SALES_ORDER as the child and ORDER the parent, and also the ORDER’s key migrated to the SALES_ORDER. So, select (click) the 1:1 identifying relationship icon, and click it on the SALES_ORDER table and then ORDER table.

Visual MySQL Database Design in MySQL Workbench

Notice that the icon changes to a hand with the 1:1 relationship when you click it to the tables.

Visual MySQL Database Design in MySQL Workbench

Visual MySQL Database Design in MySQL Workbench

The 1:1 relationship is set; the ORDER_NO primary key is migrated and becomes the primary key of the SALES_ORDER table.

Visual MySQL Database Design in MySQL Workbench

Next, create the PURCHASE_ORDER to ORDER relationship, which is also 1:1 identifying relationship.

Visual MySQL Database Design in MySQL Workbench

We have now completed designing our tables and their relationships; let’s save our model as ORDER.mwb.

Visual MySQL Database Design in MySQL Workbench

Visual MySQL Database Design in MySQL Workbench

Generate DDL and Database

The final step of our data modeling in this article is generating the model into MySQL database. We’ll first generate the DDL (SQL CREATE script), and then execute the script.

From the File | Export menu, select Forward Engineer SQL CREATE Script.

Visual MySQL Database Design in MySQL Workbench

Visual MySQL Database Design in MySQL Workbench

Visual MySQL Database Design in MySQL Workbench

Lastly, execute the saved SQL CREATE script. We execute the script outside of MySQL Workbench; for example, we can execute it in a MySQL command console.

Visual MySQL Database Design in MySQL Workbench

Visual MySQL Database Design in MySQL Workbench

You can also confirm that the tables have been created.

Visual MySQL Database Design in MySQL Workbench

Summary

This article shows you how to build a MySQL physical data model visually in MySQL Workbench, and generate the model into its MySQL database.

Continue reading MySQL Workbench使用方法

【转】Apache基本配置指南

 

适合新手看的
当初学的时候做的笔记,不是很全,别笑俺。欢迎老手们修正和补充
1、如果找不到文件的具体位置,在Linux下可以用类似locate httpd.conf的指令来搜索文件的位置。如果搜索不到,可以先用updatedb指令更新索引数据库再用locate搜索。
2、apachectl configtest或apachectl –t检查配置文件是否合法。apachectl一般位于安装目录的bin目录下(如:/usr/local/apache2/bin)。不要直接调用httpd。
3、配置文件是httpd.conf;在Linux系统中,它可能存在于系统配置目录(如:/etc/httpd/conf/),也可能存在于Apache的安装目录(如:/usr/local/apache2/conf)。
4、配置文件中,一行包含一个指令,但行尾可以用\表示续行。\与下一行之间不能有其它任何字符,包括空白字符。
#表示这一行是注释。
5、指令对大小写不敏感,但是参数对大小定敏感,在Linux系统下,路径也要注意大小写。路径后不必加/。
6、类似于<Directory></Directory>表示一个配置段。大多数配置段中的指令仅针对配置段所匹配的请 求有 效。但诸如        <IfDefine>、<IfModule>、<IfVersion>之类,是在Apache启动时,如果条 件成立才有效,并且对所有请求都有效。
httpd.conf的基本配置选项
7、ServerName服务器名称。它用来创建URL的重导向。ServerName是apache服务器自身识别访问请求的标记之一,他不必与实际IP或DNS名称一致。也可以不设置,如果这样,那apache会试图用IP来作为请求的标记。端口也可以不设置。
例:ServerName www.example.com:80
8、ServerAdmin管理员的电子邮件地址。服务器的错误提示页会用到。如果ServerSignature定义为Email的话,将在错误页的页尾增加ServerAdmin的链接。
9、Listen服务器监听的地址和端口。端口一定要指定。默认情况下,服务器会监听本机的所有地址。可以同时使用多个Listen指令。
例一:同时所有接受来自端口80和8000的请求
Listen 80
Listen 8080
例二:指定地址+端口,配置虚拟主机时,会需要这样设置。详细看虚拟主机的设置。这并不是必要的。
Listen 192.168.0.2:80
Listen 192.168.0.1:8080
注意地址是本机的地址,是指客户端对本机某个地址的请求。地址可以是域名,但最好是IP地址。
例三:IPv6地址必须用方括号括起来。
Listen [2001:db8::a00:20ff:fea7:ccea]:80
例四:要使Apache只处理IPv4的请求,只需如此:
Listen 0.0.0.0:80
10、ServerRoot 服务器基础目录,一般就是Apache的安装目录,不必更改。
11、 DocumentRoot 指定主目录。不指定的话,默认目录一般是ServerRoot目录下的htdocs目录(如/usr/local/apache2/htdocs),视版 本而定;但是可能会有例外,所以最好指定。如果指定相对路径,则认为是相对于ServerRoot目录的。目录后不要加/。
12、DirectoryIndex 默认首页名称。多个默认页名称用空格隔开。
13、ErrorDocument 处理请求出错时的处理方式。未配置时只返回错误代码。
例:
ErrorDocument 500 “The server made a boo boo.”
# 指定本地URL时,该URL是相对于DocumentRoot目录的。
ErrorDocument 404 /missing.html
ErrorDocument 404 “/cgi-bin/missing_handler.pl”
# 使用绝对URL时,客户机将无法收到错误码。
ErrorDocument 402 http://www.example.com/subscription_info.html
14、ErrorLog,CustomLog 指定错误日志和访问日志。如果指定路径是相对路径,则认为是相对ServerRoot目录的。日志文件可能会很大,以至影响到其它文件的储存空间,所以有必要把日志文件放到一个单独的分区。
例一:
ErrorLog /var/log/error_log
# commom是日记文件的格式,由LogFormat定义。不可用于ErrorLog。
Customlog /var/log/access_log common
例二:管道日志,可以用Apache提供的rotatelogs来实现。rotatelogs程序一般位于安装目录的bin目录。
# 这将每24小时建立日志文件/var/log/logfile.nnnn,nnnn是日记建立时的系统时间。
CustomLog “|bin/rotatelogs /var/log/logfile 86400”common
# 日志文件达到5M时建立新日记,文件名类似于logfile.2006-12-30-24_33_12。
ErrorLog “|bin/rotatelogs /var/log/logfile.%Y-%m-%d-%H_%M_%S 5M”
15、User, Group 指定运行服务子进程的用户和组。Rpm包安装apache时会自动设置一个用户和组,但有时会设成nobody或者不设置。为了安全和方便管理,设置为用户和组为apache是很重要的。
例:User apache
Group apache
注意在Linux系统中手动添加apache用户和组时,必须把他们的shell指定为nologin
虚拟主机
16、虚拟主机通过<VirtualHost>配置段来配置,配置段里的指令对虚拟主机有效,配置段没有配置的,将采用全局的配置。检查虚拟主机的配置可用apachectl –S(可能某些版本这个参数无效)。
17、基于域名的虚拟主机在DNS把多个域名都映射到同一IP的情况下有用。典型的配置如下:
NameVirtualHost *:80
<VirtualHost *:80>
ServerAdmin [email protected]
DocumentRoot /www/docs/test.com
ServerName test.com
ErrorLog logs/dummy-host.example.com-error_log
CustomLog logs/dummy-host.example.com-access_log common
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /www/docs/test2.com
ServerName test2.com
</VirtualHost>
NameVirtualHost *:81
<VirtualHost *:81>
DocumentRoot /www/docs/test3.com
ServerName test3.com
</VirtualHost>
注意一:NameVirtualHost 指定虚拟主机所使用的IP地址或域名,但是最好是IP地址。使用基于域名的虚拟主机时,NameVirtualHost是必要的指令。NameVirtualHost可以定义多个。
注意二:所有符合NameVirtualHost或<VirtualHost>标签定义的请求,都会被作为虚拟主机处理,而主服务器将不理 会。NameVirtualHost定义了而<VirtualHost>标签没有定义的的请求,服务器会找不到相应的虚拟主机而将无法处理。 所以每个NameVirtualHost定义的参数至少要有一个<VirtualHost>相匹配。
注意三:如果设置NameVirtualHost 或<VirtualHost>为*:80的话,所有针对80端口的请求,都会被虚拟主机处理,请求会根据域名指向某个虚拟主机。如果有来自 80端口的请求,而所请求的域名没有被配置为虚拟主机,那将指向第一个虚拟主机。这样主服务器将无法收到来自80端口的任何请求。为此也要为主服务器配置 一个虚拟主机。
18、ServerAlias 虚拟主机的别名
例:
NameVirtualHost *:80
<VirtualHost *:80>
ServerName www.domain.tld
ServerAlias domain.tld *.domain.tld
DocumentRoot /www/domain
</VirtualHost>
这表示对 domain.tld和*.domain.tld的请求也由虚拟主机www.domain.tld处理。
19、ServerPath指令是用于让某些老式浏览器也访问基于域名的虚拟主机的,一般不必设置。
20、基于IP地址的虚拟主机。例:
Listen 80
<VirtualHost 172.20.30.40>
DocumentRoot /www/example1
ServerName www.example.com
</VirtualHost>
<VirtualHost 172.20.30.50 192.168.0.10:80>
DocumentRoot /www/example2
ServerName www.example.org
</VirtualHost>
每个虚拟主机可定义多个IP,之间用空格隔开。
21、各种虚拟主机的混用。例:
Listen 80
Listen 81
NameVirtualHost 172.20.30.40
<VirtualHost 172.20.30.40>
DocumentRoot /www/example1
ServerName www.example.com
</VirtualHost>
<VirtualHost 172.20.30.40>
DocumentRoot /www/example2
ServerName www.example.org
</VirtualHost>
NameVirtualHost 172.20.30.40:81
<VirtualHost 172.20.30.40:81>
DocumentRoot /www/example3
ServerName www.example3.net
</VirtualHost>
# IP-based
<VirtualHost 172.20.30.50>
DocumentRoot /www/example4
ServerName www.example4.edu
</VirtualHost>
<VirtualHost 172.20.30.60:81 172.20.30.40:81>
DocumentRoot /www/example5
ServerName www.example5.gov
</VirtualHost>
22、虚拟主机混用时的问题:
一、虚拟主机混用可以这样理解:一行NameVirtualHost指令定义的所有虚拟主机为一组;该组与一个基于IP的虚拟主机平级。即把一行NameVirtualHost定义的整个组看作是一个基于IP的虚拟主机。
二、虚拟主机指定的端口必须是Listen定义的。如果虚拟主机没有指定端口,则认为是80端口。如果NameVirtualHost * 这样定义,是指所有地址的所有已定义端口。
三、更具体的地址定义优先。比如NameVirtualHost指令定义了*:80,而某个基于IP的虚拟主机定义为192.168.0.1:80,那么 此时如有对192.168.0.1:80的请求,那请求会被优先指向192.168.0.1:80定义的虚拟主机。所以为了避免混乱,不要定义相互有交叉 或包含的地址区间。
四、一个虚拟主机,可以同时为基于域名和基于IP的。如上一例中最后一个虚拟主机。这样符合两种定义的请求都会被指同一个虚拟主机。有时要区别内外网对虚拟主机的访问时可以这样,因为来自内网的请求可能和来自外网的请求可能不一样,但是它们需要指向同一个虚拟主机。
23、使用”_default_”虚拟主机,这个虚拟主机可以理解成基于IP的虚拟主机。例:
<VirtualHost _default_:*>
DocumentRoot /www/default
</VirtualHost>
这个虚拟主机将接管与其它虚拟主机IP和端口不匹配的请求。不过如此一来,主服务器将不会处理任何请求。因此把主服务器配置成一个虚拟主机是必要的。
24、本地机器代理在其它机器上运行的虚拟主机。例:
<VirtualHost 158.29.33.248>
ProxyPreserveHost On
ProxyPass /foo/no !
ProxyPass /foo http://192.168.111.2
ProxyPassReverse /foo http://192.168.111.2
ServerName hostname.example.com
</VirtualHost>
一、首先这是一个基于IP的虚拟主机,它接收并处理对IP地址158.29.33.248的请求。
二、ProxyPass /foo http://192.168.111.2 将把对http://158.29.33.248/foo的请求转换为一个代理请求,该请求指向http://192.168.111.2
三、ProxyPass /foo/no ! 不代理针对/foo/no的请求。这个必须放在正常代理指令之前。
四、ProxyPreserveHost On 意思是传送原始请求的Host信息给被代理的机器。
五、ProxyPassReverse /foo http://192.168.111.2 可以保证请求URL在其它机器上被重定向后,本机处理时也可以保持一致。具体看手册关于反向代理的部分。
六、基于域名的虚拟主机也是同样的道理。不管是什么类型的虚拟主机,它只是处理归它处理的请求而已。
配置段
25、<IfDefine> 只有在用httpd命令行启动服务器时(最好不要直接使用httpd,用apachectl代替),使用了-D参数定义了相应参数时才生效。如服务器用 apachectl –D test启动时,<IfDefine test>配置段生效。
26、<IfVersion> 例如:<IfVersion >= 2.0.55> 当Apache版本不低于2.0.55时生效。
27、<IfModule> 服务器启用了指定的模块后才生效。这是最常用的。例如<IfModule mod_mine_magic.c>。
28、<Directory> 用于封装一组指令,使之对某个目录和下属的子目录有效。
例:
<Directory />
Options FollowSymLinks Indexes
AllowOverride None
Order Deny,Allow
Deny from All
Allow from example.com
</Directory>
该配置段对整个根目录树有效。
一、 Options 常用选项:FollowSymlinks允许在此目录中使用符号链接;Indexes允许目录列表,即在该目录没有默认页时服务器返回该目录的列表给客户 机;SymLinksIfOwnerMatch只有符号链接与其目的目录或文件属于同一用户时才有效。
注意:对同一目录,只有一行Options有效,如果定义某个目录的Options同时要继承上级目录的定义,可以这样:Options +Indexes。如果这样:Options +Indexes –FollowSymLinks,这将为本级目录增加Indexes,取消FollowSymLinks。
二、AllowOverride 常用选项:None 不允许使用.htaccess;All允许在.htaccess中使用所有的指令。一般不必使用.htaccess,而且为了安全和效率起见,设置为None比较好。
三、Order 访问控制,控制条件由Deny行和Allow行定义。Order指令常用选项:Deny,Allow 除了符合条件的外,其它的也允许访问;Allow,Deny 除了符合条件的外,其它的不允许访问。
Deny from All是拒绝所有的访问,Allow from example.com是允许example.com域访问该目录(意思是如果该服务器上有多个虚拟主机的话,只有example.com可以访问该目 录)。三行合起来的意思就是只允许example.com域访问根目录。当然这只是个例子,应该禁止所有域对根目录的访问。注意:Deny,Allow指 令生效的顺序取决于Order中Deny和Allow的顺序。
注意<Directory>不能嵌套。
这样为了安全起见常常需要设置:
#拒绝对所有目录的访问,注意这里的/是指操作系统的根目录,而非DocumentRoot目录。
<Directory />
Options –Indexes -FollowSymLinks
AllowOverride None
Order Allow,Deny
</Directory>
#允许所有对/var/htdocs的访问,允许对/var/htdocs的文件列表。
<Directory /var/htdocs>
Options +Indexes
Order Deny,Allow
</Directory>
29、<Files> 和<Directory>类似,不过它定义的是对文件的访问控制。它们都可以接受正则表达式为参数, 格式 如<Files ~ “\.(gif|jpe?g|png)$”>或者<FilesMatch “\.(gif|jpe?g|png)$”>。
30、<Location>与<Files>和<Directory>同,不过它定义的是对URL的访问控制。
PHP配置
31、加载php模块:LoadModule php5_module modules/libphp5.so
32、AddModule mod_php5.c (不是必须的)
33、哪种后缀的文件作为php脚本来解析:AddType application/x-httpd-php .php (这是必须的,但是可以用下面的配置代替):
<Files *.php>
SetOutputFilter PHP
SetInputFilter PHP
</Files>
这种方法还可以为.php文件专门设置更多的配置。
34、哪种后缀的文件是php源文件:Addtype application/x-httpd-php-source .phps (不是必须的)
35、添加index.php为目录首页:DirectoryIndex index.php(视情况而定)
36、 ScriptAlias /php/ /usr/local/php/ 对类似http://example/php/abc.php的请求将引导执行/usr/local/php/abc.php脚本。(一些所谓配置指南里 有,事实上完全没有这个必要。并且ScriptAlias这个指令是针对CGI脚本的。他会把php脚本也当作已定义的cgi脚本处理)。
37、 Action application/x-httpd-php “C:/PHP/php.exe” 所有application/x-httpd-php类型的文件都由C:/PHP/php.exe来处理,注意application/x-httpd- php必须是已经定义的文件类型。(只有在windows中以CGI模式安装PHP时才有用)。
38、事实上,必要的配置只有这么两条:
LoadModule php5_module modules/libphp5.so
AddType application/x-httpd-php .php
可以把相关php的配置语句都放在一起便于管理。简单至此,不要被一些配置指南吓住了

Continue reading 【转】Apache基本配置指南

Pagination


Total views.

© 2013 - 2019. All rights reserved.

Powered by Hydejack v6.6.1