開發環境必備軟件:
composer-cli
generator-hyperledger-composr
composer-rest-server
Yeoman
安裝playground
1,playground 的Web Browser區域提供了在頁面定義模型、測試模型的能力。并不保存。但可以導出bna文件
2,connection區域提供了在開發環境布署合約,會生成一個智能合約的docker運行環境.
3,可以在上圖中上部分的My Business Networks 工作區點擊虛業部分Deploy a new business network
4,在接下來頁面中選中一個示例。如 marble neetworkd. 選擇 ID and Secret 填入admin 和 adminpw
5,點擊Deploy按鈕后會發布一個合約.并跳到測試頁如下圖:
6,在上圖中 Test Tab頁可以進行測試 ,在Define Tab頁可以導出bna文件.
7,在第一幅圖中點擊下載按鈕,會下載一個 .card文件,描述了連接fabric peer節點等相關連接信息.記得要導 PeerAdmin@hlfv1的card和你自己測試用的card,及bna文件
8,分別執行 composer card import -f PeerAdmin.card ,composer card import -f admin.card .composer card list 可以查看你導入的card的name信息.
9,composer-rest-server -c admin@empty-business-network -n always -w true 啟動rest服務默認端口3000.
10,好了,可以體驗一下fabric是個什么玩意了。:) 88!
一,需求收集,分析。
此處省略2000字。。。 見前篇 《需求收集、分析小結》http://m.tkk7.com/fool/archive/2017/04/28/432489.html
二,概念架構/概念模型
從需求中找出關健、重大需求,進行概念建模.下面三個圖稱之魯棒圖。其中控制對象理解為mvc模式中的控制器和model。使用魯棒圖可以建立概念模型,約等于初步設計。初步設計并不關心細節。
魯棒圖建立概念模型語法:
概念設計舉例:
上次談到超市小票如何分析實體對象,本次接著舉例如何對收銀進行概念建模
如上圖:具備基本收銀功能的概念模型。概念模型建模可以是增量的。比如商品折扣或其它
促銷活動等。
概念架構的用途:
1) 可以幫助我們找出領域模型中的實體對象。
2) 檢查需求用例是否正確和完善。
3)初步設計,魯棒圖是一種初步設計技術。
4)根據用例和概念設計劃分系統、子系統、模塊或者包。借助魯棒圖,初步識別功能背后的職責,規劃切分系統的方式。
三,關注非功能性需求,包括運行期質量和開發期質量。
運用目標—場景—決策表對非功能性需求作出決策.小舉例:
目標 | 場景 | 決策 |
易用性 | 銷售員需要輸入條碼檢索商品,繁瑣且速度慢 | 根據條碼,品名模糊匹配檢索商品,提供輔助錄入。 |
性能 | 長時間穩定運行 | 數據庫集群,服務應用集群 |
四,細化架構。RUP 4+1視圖法則將架構需要關注的不同的點使用不同的視圖表示.從不同的維度對系統進行解讀,從而形成統一軟件過程架構描述。
運行架構:
關心進程、線程、同步的相關設計,捕捉并發和同步特征
邏輯架構:
關心邏輯層(layer)的劃分,系統/子系統的劃分,劃分模塊及其接口的定義。功能組劃分也屬于邏輯架構.功能:不僅包括用戶可見的功能,還包括為實現用戶功能而必須提供的"輔助功能模塊";它們可能是邏輯層、功能模塊等。
物理架構:
關心服務器選型,物理層劃分(tier)。 描述如何部署機器和網絡來配合軟件系統的可靠性、可伸縮性等要求.layer就運行在tier上。Tier反映系統伸縮能力。
開發架構:
描述了在開發環境中軟件的靜態組織結構。即開發工具下的開發視圖,描述文件編譯及其依賴關系。而使用maven管理開發的項目編譯及依賴關系結構更加分明。
數據架構:
關心數據的存儲、分布和文件的存放及數據的復制,傳遞,同步。數據的存放包括sql,內存數據庫,nosql數據庫等.
邏輯架構設計舉例:
還是用收銀系統簡單舉例,收銀系統邏輯架構圖如下:
整個系統劃系統為系統,切為兩個系統,一個收銀員角色處理的業務,收銀系統。
一個后臺管理系統。后臺管理系統包括用戶管理模塊,基礎資料模塊(產品資料等)
銷售模塊(本例對銷售單)。另外,因為收銀系統需要和后臺系統交互,把收銀系統需要使用到的相關的各模塊封裝成一個接口模塊,專門處理和收銀系統交互的模塊。系統、模塊之間的通訊方式應當盡量避免雙向。相互依賴可能會引發很多問題。
物理架構設計舉例:
物理架構和邏輯架構可以相互印證。描述軟件系統的物理布署。
如果考慮運行期質量比如長時間運行布署圖可能應用做集群。數據庫做集群等。邏輯層layer運行在物理層tier之上
運行架構和數據架構視圖根據實際情況可選設計
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="filterChainProxy"
class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
</value>
</property>
</bean>
<bean id="authenticationManager"
class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<!-- 自己寫一個認證提供者類 我加的-->
<ref local="activeDirectoryProvider" />
<ref local="daoAuthenticationProvider" />
<ref local="anonymousAuthenticationProvider" />
<ref local="rememberMeAuthenticationProvider" />
</list>
</property>
</bean>
<!-- 認證提供者類的配置 我加的-->
<bean id="activeDirectoryProvider"
class="net.omw.utility.AcegiTestProvider">
<property name="url" value="ldap://172.108.4.2"> </property>
<property name="port" value="389"> </property>
<!--domain取值域服務器的配置-->
<property name="domain" value="SUNTECH"> </property>
<!-- <property name="sessionController" ref="concurrentSessionController"></property> -->
</bean>
<bean id="jdbcDaoImpl"
class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource">
<ref bean="coreDataSource" />
</property>
<property name="usersByUsernameQuery">
<value>
select C_OPER_ID,C_PASSWORD,1 from Operator where
C_OPER_ID = ? and C_STATUS='Y'
</value>
</property>
<property name="authoritiesByUsernameQuery">
<value>
select C_OPER_ID,C_PASSWORD,1 from Operator where
C_OPER_ID = ? and C_STATUS='Y'
</value>
</property>
</bean>
<bean id="passwordEncoder"
class="org.acegisecurity.providers.encoding.Md5PasswordEncoder">
<property name="encodeHashAsBase64" value="false"></property>
</bean>
<bean id="daoAuthenticationProvider"
class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
<property name="userDetailsService">
<ref local="jdbcDaoImpl" />
</property>
<!-- <property name="userCache">
<ref local="userCache" />
</property>-->
<property name="passwordEncoder">
<ref local="passwordEncoder" />
</property>
</bean>
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
<bean id="userCacheBackend"
class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager">
<ref local="cacheManager" />
</property>
<property name="cacheName">
<value>userCache</value>
</property>
</bean>
<bean id="userCache"
class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
<property name="cache">
<ref local="userCacheBackend" />
</property>
</bean>
<bean id="loggerListener"
class="org.acegisecurity.event.authentication.LoggerListener" />
<bean id="anonymousProcessingFilter"
class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
<property name="key">
<value>foobar</value>
</property>
<property name="userAttribute">
<value>anonymousUser,ROLE_ANONYMOUS</value>
</property>
</bean>
<bean id="anonymousAuthenticationProvider"
class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
<property name="key">
<value>foobar</value>
</property>
</bean>
<bean id="httpSessionContextIntegrationFilter"
class="org.acegisecurity.context.HttpSessionContextIntegrationFilter">
</bean>
<bean id="rememberMeProcessingFilter"
class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
<property name="authenticationManager">
<ref local="authenticationManager" />
</property>
<property name="rememberMeServices">
<ref local="rememberMeServices" />
</property>
</bean>
<bean id="rememberMeServices"
class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService">
<ref local="jdbcDaoImpl" />
</property>
<property name="key">
<value>springRocks</value>
</property>
</bean>
<bean id="rememberMeAuthenticationProvider"
class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
<property name="key">
<value>springRocks</value>
</property>
</bean>
<bean id="logoutFilter"
class="org.acegisecurity.ui.logout.LogoutFilter">
<constructor-arg value="/login/loginPage.jsp" />
<constructor-arg>
<list>
<ref bean="rememberMeServices" />
<bean
class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler" />
</list>
</constructor-arg>
</bean>
<bean id="securityContextHolderAwareRequestFilter"
class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter" />
<bean id="exceptionTranslationFilter"
class="org.acegisecurity.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
<ref local="authenticationProcessingFilterEntryPoint" />
</property>
<property name="accessDeniedHandler">
<bean
class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
<property name="errorPage"
value="/common/AccessDenied.jsp" />
</bean>
</property>
</bean>
<bean id="authenticationProcessingFilter"
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="authenticationManager">
<ref bean="authenticationManager" />
</property>
<property name="authenticationFailureUrl">
<value>/login/Login.action?login_msg=1</value>
</property>
<property name="defaultTargetUrl">
<value>/login/Login.action?login_msg=0</value>
</property>
<property name="filterProcessesUrl">
<value>/j_acegi_security_check</value>
</property>
<property name="rememberMeServices">
<ref local="rememberMeServices" />
</property>
</bean>
<bean id="authenticationProcessingFilterEntryPoint"
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl">
<value>/login/loginPage.jsp</value>
</property>
<property name="forceHttps">
<value>false</value>
</property>
<property name="serverSideRedirect" value="false"></property>
</bean>
<bean id="httpRequestAccessDecisionManager"
class="org.acegisecurity.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions">
<value>false</value>
</property>
<property name="decisionVoters">
<list>
<ref bean="roleVoter" />
</list>
</property>
</bean>
<bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter" />
<bean id="filterInvocationInterceptor"
class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="validateConfigAttributes" value="true" />
<property name="authenticationManager">
<ref bean="authenticationManager" />
</property>
<property name="accessDecisionManager">
<ref local="httpRequestAccessDecisionManager" />
</property>
<property name="objectDefinitionSource"
ref="rdbmsFilterInvocationDefinitionSource" />
</bean>
<bean id="rdbmsFilterInvocationDefinitionSource"
class="net.omw.utility.acegi.interceptor.RdbmsFilterInvocationDefinitionSource">
<property name="dataSource">
<ref bean="coreDataSource" />
</property>
<property name="webresdbCache" ref="webresCacheBackend" />
</bean>
<bean id="webresCacheBackend"
class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager">
<ref local="cacheManager" />
</property>
<property name="cacheName">
<value>webresdbCache</value>
</property>
</bean>
<!--
<bean id="switchUserProcessingFilter" class="org.acegisecurity.ui.switchuser.SwitchUserProcessingFilter">
<property name="userDetailsService" ref="jdbcDaoImpl" />
<property name="switchUserUrl"><value>/j_acegi_switch_user</value></property>
<property name="exitUserUrl"><value>/j_acegi_exit_user</value></property>
<property name="targetUrl"><value>/secure/index.htm</value></property>
</bean>
-->
<bean id="authenticationLoggerListener"
class="org.acegisecurity.event.authentication.LoggerListener" />
<bean id="authorizationLoggerListener"
class="org.acegisecurity.event.authorization.LoggerListener" />
</beans>
AcegiTestProvider類從AbstractUserDetailsAuthenticationProvider繼承,有兩個方法必須實現
additionalAuthenticationChecks()和retrieveUser()方法.retrieveUser返回UserDetails,UserDetails的實現可以包裝更多的信息.但在本例中幾乎沒什么太大的作用,僅僅是為了返回而重新定義了一個類
真正的驗證邏輯發生在additionalAuthenticationChecks方法里拋出異常就算用戶登錄失敗
package net.omw.utility;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.ldap.InitialLdapContext;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider;
import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UsernameNotFoundException;
public class AcegiTestProvider extends
AbstractUserDetailsAuthenticationProvider {
private String url;
private String port;
private String domain;
/*
* 驗證邏輯
* @see org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider#additionalAuthenticationChecks(org.acegisecurity.userdetails.UserDetails, org.acegisecurity.providers.UsernamePasswordAuthenticationToken)
*
*/
@Override
protected void additionalAuthenticationChecks(UserDetails arg0,
UsernamePasswordAuthenticationToken arg1)
throws AuthenticationException {
// TODO Auto-generated method stub
String URL = url+":"+port;
String username=domain+"\\"+arg0.getUsername();
String password = arg0.getPassword();
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL,"ldap://172.18.0.42:389");
env.put(Context.SECURITY_AUTHENTICATION,"simple");
env.put(Context.SECURITY_PRINCIPAL,
username);
env.put(Context.SECURITY_CREDENTIALS,password);
env.put("com.sun.jndi.ldap.connect.pool","true");
env.put("java.naming.referral","follow");
try{
new InitialLdapContext(env,null);
}
catch(NamingException e){
// Authentication failed
throw new UsernameNotFoundException(e.toString());
}
}
@Override
protected UserDetails retrieveUser(String arg0,
UsernamePasswordAuthenticationToken arg1)
throws AuthenticationException {
// TODO Auto-generated method stub
GrantedAuthority[] authorities = new GrantedAuthority[1];
authorities[0] = new GrantedAuthorityImpl("ROLE_SUPERVISOR");
String password = (String) arg1.getCredentials();
/*String username = "";
Object obj = arg1.getPrincipal();
if (obj instanceof UserDetails) {
username = ((UserDetails) obj).getUsername();
} else {
username = obj.toString();
}
*/
UserDetails userDetails = new UserDetailsImpl(authorities, password,
arg1.getName(), true, true, true, true);
//if(true)
// throw new AuthenticationCredentialsNotFoundException("t");
return userDetails;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
}
package net.omw.utility;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.userdetails.UserDetails;
public class UserDetailsImpl implements UserDetails {
GrantedAuthority[] authorities;
String password;
String username;
boolean isAccountNonExpired;
boolean isAccountNonLocked;
boolean isCredentialsNonExpired;
boolean isEnabled;
UserDetailsImpl(GrantedAuthority[] authorities, String password,
String username, boolean isAccountNonExpired,
boolean isCredentialsNonExpired, boolean isEnabled,
boolean isAccountNonLocked) {
this.authorities = authorities;
this.isAccountNonExpired = isAccountNonExpired;
this.isAccountNonLocked = isAccountNonLocked;
this.isEnabled = isEnabled;
this.password = password;
this.username = username;
this.isCredentialsNonExpired = isCredentialsNonExpired;
}
@Override
public GrantedAuthority[] getAuthorities() {
// TODO Auto-generated method stub
return authorities;
}
@Override
public String getPassword() {
// TODO Auto-generated method stub
return password;
}
@Override
public String getUsername() {
// TODO Auto-generated method stub
return username;
}
@Override
public boolean isAccountNonExpired() {
// TODO Auto-generated method stub
return isAccountNonExpired;
}
@Override
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return isAccountNonLocked;
}
@Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return isCredentialsNonExpired;
}
@Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return isEnabled;
}
}
??? public static void main(String[] args){
????? Mozi mozi=new Mozi();
????? Horse w=new WhiteHorse();
????? Horse b=new BlackHorse();
????? mozi.ride(w);
????? mozi.ride(b);
??? }
}?
程序打印輸出:
ridding a horse
ridding a horse
原因就是對兩次ride方法的調用傳入的參量不同,但是它們的靜態類型是一樣的,都是 Horse;
這個過程在編譯時期就完成了。
java通過方法置換支持動態分派。比如 String s1="ab"; Object o=s1+"c"; String s="abc";
o.equals(s) 打印true? o.equals()方法執行的是String類的equals()方法.java調用對象的
真實類型的方法,這就是動態分派。
雙重分派:
public abstract class Vistor{
protected void processStrig(Object e){
?if(e instanceof String){
???? String tmp=(String) e;
???? String need="'"+e+"'";
???? System.out.println(nedd);
?? }else if(e instanceof Integer){
?????? String need=e.toString();
?????? System.out.println(need);
??? }else if(e instanceof Date){
???????????? Date tmp=(Date) e;
???????????? String need="'"+tmp.toString()+"'";
??????? }
????? ....
??? }
}
public class ConcreteVisitor extends Visitor{
protected void processString(Object e){
???? super.processString(e);
?? }??
}
方法的調用Visitor v=new ConcreteVisitor(); v.processString(new String("tt"));
v.processString()方法在調用的時候會檢察v的真實類型,調用真實類型的方法,這個時候就
發生了一動態的單分派過程.當子類調用超類的方法的時候明顯的根據instanceof判斷的真實類
型去執行不同的方法,又發生了一次動態分派的過程.這個就是雙重分派的實現。這種方法實現的
程序比較冗長和容易出錯.
“返傳球”方案:
public abstract class Vistor{
?? public abstract String processStrig(Object e);
}
public class ConcreteVisitor extends Visitor{
? public String processString(WrapperString e){
??? String tmp= t.toString();
??? System.out.println(tmp);
?? }??
? public String processInteger(WrapperInteger e){
??? String tmp=e.toString();
??? System.out.println(tmp);
?? }
}
public class abstract Wrapper{
? public abstract String processString(Vistor v);
}
public class WrapperString extends Wrapper{
? public String processString(Vistor v){
??? v.processString(this);
?? }
? public String toString(){
?? ...
?? }
}
public class WrapperInteger extends Wrapper{
??? public String processInteger(Visitor v){
???? v.processString(this);
??? }
??? public String toString(){
???? ...
??? }
?}
方法的調用:
Visitor v = new ConcreteVisitor();
Wrapper wrapper= new WrapperString();
wrapper.processString(v);
當wrapper.processString()方法執行的時候會檢察wrapper的真實類型,這個就產生了一次
動態單分派,processString()里面的語句v.processString()在執行的時候也會檢察v的真
實類型,動態雙重分派就發生了。
訪問者模式的核心就是“返傳球“方案的雙重分派。其示意性類圖:(注:虛線箭頭劃錯了)
在一個方法內實現向不同的表插入不同數據的具體實現方案(簡化了的):因為整個方案里只需
要一個訪問者對象,因此使用簡化了的訪問者模式。因為java基本類型及對應的類是不變模式的
實現:因此包裝一下這些基本類型和類并實現訪問者模式需要的方法。
public abstract class Wrapper {
??? public Wrapper() {
??? }
??? public abstract String action(Visitor visitor);
}
包裝Date類:
import java.util.Date;
public class WrapperDate extends Wrapper {
??? private Date date;
??? public WrapperDate(Date date) {
??????? this.date=date;
??? }
??? public String action(Visitor visitor){
???????? return( visitor.visit(this));
??? }
??? public String toString(){
??????? if (date==null){
??????????? return "null";
??????? }
??????? return "'"+date.toString()+"'";
??? }
}
包裝Integer類:
public class WrapperInteger extends Wrapper {
??? private Integer value;
??? public WrapperInteger(Integer value) {
??????? this.value=value;
??? }
??? public WrapperInteger(int value){
??????? this.value=new Integer(value);
??? }
??? public WrapperInteger(String value){
????? this.value=new Integer(value);
??? }
??? public String action(Visitor visitor){
?????? return( visitor.visit(this));
??? }
??? public String toString(){
??????? if(value==null){
??????????? return "null";
??????? }
??????? return value.toString();
??? }
}
包裝String類:
public class WrapperString extends Wrapper {
??? private String wrapper;
??? public WrapperString( String wrapper) {
??????? this.wrapper = wrapper;
??? }
??? public WrapperString( char[] wrap) {
??????? wrapper = new String(wrap);
??? }
??? public String action(Visitor visitor) {
??????? return (visitor.vistit(this));
??? }
??? public String toString() {
??????? if(wrapper==null){
??????????? return "null";
??????? }
??????? return "'" + wrapper + "'";
??? }
}
具體訪問者的實現:
public class Visitor {
??? public Visitor() {
??? }
??? public String vistit(WrapperString wrap){
?????? return wrap.toString();
??? }
??? public String visit(WrapperInteger value){
??????? return value.toString();
??? }
??? public String visit(WrapperDate date){
??????? return date.toString();
??? }
}
具體應用類的實現:
import java.util.*;
public class Test {
??? private Visitor visitor = new Visitor();
??? public Test() {
??? }
??? public Visitor getVisitor() {
??????? return visitor;
??? }
??
??? public int insertData(String tablename, List columNameCollection,
????????????????????????? List values) {
??????? StringBuffer query = new StringBuffer("insert into " + tablename + " (");
??????? int count = 0;
??????? for (Iterator it = columNameCollection.iterator(); it.hasNext(); ) {
??????????? String columName = (String) it.next();
??????????? query.append(columName);
??????????? query.append(",");
??????? }
??????? query.deleteCharAt(query.length() - 1);
??????? query.append(") values(");
??????? for (Iterator it = values.iterator(); it.hasNext(); ) {
??????????? Wrapper wrapper = (Wrapper) it.next();
??????????? String tmp = wrapper.action(getVisitor());
??????????? query.append(tmp);
??????????? query.append(",");
??????? }
??????? query.deleteCharAt(query.length() - 1);
??????? query.append(")");
??????? System.out.println(query.toString());
??????? return count;
??? }
??? public static void main(String[] args) {
??????? Test test = new Test();
??????? String tableName = "cutomer";
??????? List columNameCollection = new ArrayList();
??????? String columName = "name";
??????? String columAge = "age";
??????? String columFunctionTime="fuctiontime";
??????? columNameCollection.add(columName);
??????? columNameCollection.add(columAge);
??????? columNameCollection.add(columFunctionTime);
??????? List values = new ArrayList();
??????? String name=null;
??????? Wrapper wrapper1 = new WrapperString(name);
??????? Wrapper wrapper2 = new WrapperInteger(1);
??????? Wrapper wrapper3= new WrapperDate(new java.util.Date());
??????? values.add(wrapper1);
??????? values.add(wrapper2);
??????? values.add(wrapper3);
??????? test.insertData(tableName,columNameCollection,values);
???????
??? }
}
程序打印結果:
insert into cutomer (name,age,fuctiontime) values(null,1,'Sat Aug 12 13:46:58 CST 2006')
這個輸出是滿足MSSQL執行插入的語法要求的.雖然這樣就實現了想要的結果,
但是insertData(String tablename, List columNameCollection, List values) 方法在每次調
用的時候需要輸入表名跟該表的列的集合,還是很麻煩,不盡人意,而且不同的數
據庫的表名是不一樣的,因此最好用配置文件來解決這一個問題.
歡迎加入QQ群:30406099?
?
?
參數:
c - 要為其繪制邊框的組件
g - 繪制的圖形
x - 所繪制邊框的 x 坐標位置
y - 所繪制邊框的 y 坐標位置
width - 所繪制邊框的寬度
height - 所繪制邊框的高度
//附注:邊框就是在這個方法中給畫出來的
--------------------------------------------------------------------------------
Insets getBorderInsets(Component c)返回該邊框的 insets。
//附注一下:該類是容器邊界的表示形式。它指定容器必須在其各個邊緣留出的空間。這個空間可以是邊
//界、空白空間或標題。
參數:
c - 要應用此邊框 insets 值的組件
--------------------------------------------------------------------------------
isBorderOpaque
boolean isBorderOpaque()返回此邊框是否透明。如果邊框為不透明,則在繪制它時將用自身的背景來填充。
接口的實現類? 至于畫圖用到的方法,詳見JAVA API.
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.border.*;
public class MyBorder implements Border
{
?//設置邊框四周留出的空間
? protected int m_w=6;??
? protected int m_h=6;
? protected int m_left=16;
//設置邊框的前景色跟背景色
? protected Color m_topColor = Color.white;
? protected Color m_bottomColor = Color.gray;
? public MyBorder() {
??? m_w=6;
??? m_h=6;
??? m_left=16;
? }
? public MyBorder(int w, int h) {
??? m_w=w;
??? m_h=h;
? }
? public MyBorder(int w, int h, Color topColor,
?? Color bottomColor) {
??? m_w=w;
??? m_h=h;
??? m_topColor = topColor;
??? m_bottomColor = bottomColor;
? }
? public Insets getBorderInsets(Component c) {
??? return new Insets(m_h, m_left, m_h, m_w);
? }
? public boolean isBorderOpaque() { return true; }
? public void paintBorder(Component c, Graphics gd,
?? int x, int y, int w, int h) {
??? Graphics2D g = (Graphics2D) gd;
??? w--;
??? h--;
??? g.setColor(m_topColor);
??? g.drawLine(x, y+h, x, y+m_h);
??? g.drawArc(x, y, 2*m_w, 2*m_h, 180, -90);
??? g.drawLine(x, y, x+w-m_w, y);
??? g.drawArc(x+w-2*m_w, y, 2*m_w, 2*m_h, 90, -90);
??? int stringHeitht = y+h-5;
??? Point2D.Float? p1 = new Point2D.Float(x,y+h);
??? Point2D.Float p2 = new Point2D.Float(x,y);
??? GradientPaint gradient = new GradientPaint(p1,Color.blue,p2,Color.gray,false);
??? //g.setColor(Color.YELLOW);
??? //g.drawRect();
??? g.setPaint(gradient);
??? g.fillRect(x,y,x+m_left,y+h);
??? g.setColor(Color.GRAY);
??? g.drawString("瓜",((x+m_left)-g.getFontMetrics().charWidth('傻'))/2,stringHeitht);
??? int simpleFontHeitht = g.getFontMetrics().getHeight();
??? stringHeitht-=simpleFontHeitht;
??? g.drawString("傻",((x+m_left)-g.getFontMetrics().charWidth('傻'))/2,stringHeitht);
??? g.setColor(m_bottomColor);
??? g.drawLine(x+w, y+m_h, x+w, y+h);
?? // g.drawArc(x+w-2*m_w, y+h-2*m_h, 2*m_w, 2*m_h, 0, -90);
?? g.drawLine(x, y+h, x+w, y+h);
??? //g.drawArc(x, y+h-2*m_h, 2*m_w, 2*m_h, -90, -90);
? }
}
剩下的就是把這個邊框給它裝上去了.在JMenu中有一個方法getPopupMenu()得到彈出菜單對象JPopupMenu;
然后調用這個JPopupMenu對象的setBorder方法就行了.下面是完整的測試程序
import java.awt.Toolkit;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import java.awt.Dimension;
public class Application1 {
? boolean packFrame = false;
? /**
?? * Construct and show the application.
?? */
? public Application1() {
??? MenuFaces frame = new MenuFaces();
??? // Validate frames that have preset sizes
??? // Pack frames that have useful preferred size info, e.g. from their layout
??? if (packFrame) {
????? frame.pack();
??? }
??? else {
????? frame.validate();
??? }
??? // Center the window
??? Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
??? Dimension frameSize = frame.getSize();
??? if (frameSize.height > screenSize.height) {
????? frameSize.height = screenSize.height;
??? }
??? if (frameSize.width > screenSize.width) {
????? frameSize.width = screenSize.width;
??? }
??? frame.setLocation( (screenSize.width - frameSize.width) / 2,
????????????????????? (screenSize.height - frameSize.height) / 2);
??? frame.setVisible(true);
? }
? /**
?? * Application entry point.
?? *
?? * @param args String[]
?? */
? public static void main(String[] args) {
??? SwingUtilities.invokeLater(new Runnable() {
????? public void run() {
??????? try {
????????? UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
??????? }
??????? catch (Exception exception) {
????????? exception.printStackTrace();
??????? }
??????? new Application1();
????? }
??? });
? }
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MenuFaces
??? extends JFrame {
? JPanel contentPane;
? BorderLayout borderLayout1 = new BorderLayout();
? JMenuBar jMenuBar1 = new JMenuBar();
? JMenu jMenuFile = new JMenu();
? JMenuItem jMenuFileExit = new JMenuItem();
? JMenuItem jMenuItem1 = new JMenuItem();
? JMenuItem jMenuItem2 = new JMenuItem();
? JMenuItem jMenuItem3 = new JMenuItem();
? JMenu jMenu1 = new JMenu();
? JMenuItem jMenuItem4 = new JMenuItem();
? public MenuFaces() {
??? try {
????? setDefaultCloseOperation(EXIT_ON_CLOSE);
????? jbInit();
??? }
??? catch (Exception exception) {
????? exception.printStackTrace();
??? }
? }
? /**
?? * Component initialization.
?? *
?? * @throws java.lang.Exception
?? */
? private void jbInit() throws Exception {
??? contentPane = (JPanel) getContentPane();
??? contentPane.setLayout(borderLayout1);
??? setSize(new Dimension(400, 300));
??? setTitle("Frame Title");
??? jMenuFile.setText("File");
??? jMenuFileExit.setText("Exit");
??? jMenuFileExit.addActionListener(new MenuFaces_jMenuFileExit_ActionAdapter(this));
??? jMenuItem1.setText("open");
??? jMenuItem2.setText("save");
??? jMenuItem3.setText("save as");
??? jMenu1.setText("other");
??? jMenuItem4.setText("tt");
??? jMenuBar1.add(jMenuFile);
??? jMenuBar1.add(jMenu1);
??? jMenuFile.add(jMenuItem3);
??? jMenuFile.add(jMenuItem2);
??? jMenuFile.add(jMenuItem1);
??? jMenuFile.add(jMenuFileExit);
??? jMenu1.add(jMenuItem4);
??? JPopupMenu tt = jMenuFile.getPopupMenu();
??? MyBorder myBorder = new MyBorder();
??? tt.setBorder(myBorder);
??? setJMenuBar(jMenuBar1);
? }
? /**
?? * File | Exit action performed.
?? *
?? * @param actionEvent ActionEvent
?? */
? void jMenuFileExit_actionPerformed(ActionEvent actionEvent) {
??? System.exit(0);
? }
}
class MenuFaces_jMenuFileExit_ActionAdapter
??? implements ActionListener {
? MenuFaces adaptee;
? MenuFaces_jMenuFileExit_ActionAdapter(MenuFaces adaptee) {
??? this.adaptee = adaptee;
? }
? public void actionPerformed(ActionEvent actionEvent) {
??? adaptee.jMenuFileExit_actionPerformed(actionEvent);
? }
}
歡迎加入QQ群:30406099?
?