2010 (gwt study)

本文介绍了GWT应用开发的核心概念和技术细节,包括模块定义、样式表使用、资源自动包含机制、RPC框架、JSNI特性及国际化策略等内容。

In the module XML file, you specify your application's entry point class. In order to compile, a GWT module must specify an entry point. If a GWT module has no entry point, then it can only be inherited by other modules. It is possible to include other modules that have entry points specified in their module XML files. If so, then your module would have multiple entry points. Each entry point is executed in sequence.


By default, StockWatcher uses two style sheets: the default GWT style sheet, standard.css (which is referenced via the inherited theme), and the application style sheet, StockWatcher.css which was generated by webAppCreator.


The host page references the path of JavaScript source code (generated by GWT) responsible for the dynamic elements on the page. The contents of the entire body element can be generated dynamically, for example, as it is with starter application.


The StockWatcher class implements the GWT interface EntryPoint. It contains the method onModuleLoad. Because the StockWatcher class is specified as the entry point class in StockWatcher's module definition, when you launch StockWatcher the onModuleLoad method is called.


The StockWatcher class inherits functionality via other GWT modules you included in StockWatcher's module definition (StockWatcher.gwt.xml). For example, when building the user interface, you'll be able to include types and resources from the package com.google.gwt.user.client.ui because it is part of the GWT core functionality included in the GWT module com.google.gwt.user.User.


A Root panel is the container for the dynamic elements of your application. It is at the top of any GWT user interface hierarchy. There are two ways you can use a Root panel, either to generate the entire body of the page or to generate specific elements embedded in the body.
The Root panel works by wrapping an element in the HTML host page. By default (that is, if you don't add any placeholders in the host page) the Root panel wraps the body element. However, you can wrap any element if you name it and then, when you call the Root panel, pass the name as a parameter.
RootPanel.get()             // Default. Wraps the HTML body element.
RootPanel.get("stockList")  // Wraps any HTML element with an id of "stockList"


For StockWatcher, you'll follow the preferred strategy. Rather than put links to the style sheets in the HTML host page, you'll use the module XML file. Then, when you compile StockWatcher, the GWT compiler will bundle all the static resources required to run your application including the style sheets. This mechanism is called Automatic Resource Inclusion.


In GWT, each class of widget has an associated style name (like gwt-Button) that binds it to a CSS style rule. This is the widget's primary style. Default values are defined for the primary style in the theme style sheet.
Type of Element            HTML Tag         CSS Selector
Buttons in static HTML and GWT-generated buttons    <button>         button
Only GWT-generated buttons          <button class="gwt-Button">    button.gwt-Button
Only my special GWT-generated button       <button class="gwt-Button my-button">  button.my-button


Dependent styles are powerful because they are automatically updated whenever the primary style name changes. In contrast, secondary style names that are not dependent style names are not automatically updated when the primary style name changes.
To do this, you'll use the addStyleDependentName method instead of the addStyleName method


If you launched the development mode server, you can run your application in production mode (after compiling it) by removing the gwt.codesvr parameter from the URL before loading the application.


The GWT RPC framework makes it easy for the client and server components of your web application to exchange Java objects over HTTP. The server-side code that gets invoked from the client is often referred to as a service. The implementation of a GWT RPC service is based on the well-known Java servlet architecture. Within the client code, you'll use an automatically-generated proxy class to make calls to the service. GWT will handle serialization of the Java objects passing back and forth—the arguments in the method calls and the return value.


In order to define your RPC interface, you need to write three components:


Define an interface (StockPriceService) for your service that extends RemoteService and lists all your RPC methods.
Create a class (StockPriceServiceImpl) that extends RemoteServiceServlet and implements the interface you created above.
Define an asynchronous interface (StockPriceServiceAsync) to your service to be called from the client-side code.


Every service implementation is ultimately a servlet, but rather than extending HttpServlet, it extends RemoteServiceServlet instead. RemoteServiceServlet automatically handles serialization of the data being passed between the client and the server and invoking the intended method in your service implementation.


Notice the @RemoteServiceRelativePath annotation. This associates the service with a default path relative to the module base URL.
In the <servlet-mapping> element, the url-pattern can be in the form of an absolute directory path (for example, /spellcheck or /common/login). If you specify a default service path with a @RemoteServiceRelativePath annotation on the service interface (as you did with StockPriceService), then make sure the url-pattern matches the annotation value.


To add an AsyncCallback parameter to all of our service methods, you must define a new interface as follows:


It must have the same name as the service interface, appended with Async (for example, StockPriceServiceAsync).
It must be located in the same package as the service interface.
Each method must have the same name and signature as in the service interface with an important difference: the method has no return type and the last parameter is an AsyncCallback object.


Often, you will need to integrate GWT with existing handwritten JavaScript or with a third-party JavaScript library. Occasionally you may need to access low-level browser functionality not exposed by the GWT class API's. The JavaScript Native Interface (JSNI) feature of GWT can solve both of these problems by allowing you to integrate JavaScript directly into your application's Java source code.


JSNI methods are declared native and contain JavaScript code in a specially formatted comment block between the end of the parameter list and the trailing semicolon. A JSNI comment block begins with the exact token /*-{ and ends with the exact token }-*/. JSNI methods are called just like any normal Java method. They can be static or instance methods.


generated GWT files. At compile time, the GWT compiler performs some syntax checks on the JavaScript inside the method, then generates interface code for converting method arguments and return values properly.


As of the GWT 1.5 release, the Java varargs construct is supported. The GWT compiler will translate varargs calls between 2 pieces of Java code. However, calling a varargs JavaScript method from Java will result in the callee receiving the arguments in an array.


When accessing the browser's window and document objects from JSNI, you must reference them as $wnd and $doc, respectively. Your compiled script runs in a nested frame, and $wnd and $doc are automatically initialized to correctly refer to the host page's window and document.


Calling Java methods from JavaScript is somewhat similar to calling Java methods from C code in JNI. In particular, JSNI borrows the JNI mangled method signature approach to distinguish among overloaded methods. JavaScript calls into Java methods are of the following form:
[instance-expr.]@class-name::method-name(param-signature)(arguments)
instance-expr. : must be present when calling an instance method and must be absent when calling a static method
class-name : is the fully-qualified name of the class in which the method is declared (or a subclass thereof)
param-signature : is the internal Java method signature as specified here but without the trailing signature of the method return type since it is not needed to choose the overload
arguments : is the actual argument list to pass to the called method


Calling Java constructors from JavaScript is identical to the above use case, except that the method name is alway new.


someTopLevelInstance.new InstanceInner(123) becomes @pkg.TopLevel.InstanceInner::new(Lpkg/TopLevel;I)(someTopLevelInstance, 123)
The enclosing instance of a non-static class is implicitly defined as the first parameter for constructors of a non-static class. Regardless of how deeply-nested a non-static class is, it only needs a reference to an instance of its immediately-enclosing type.


Static and instance fields can be accessed from handwritten JavaScript. Field references are of the form
[instance-expr.]@class-name::field-name


public class JSNIExample {
 
  String myInstanceField;
  static int myStaticField;
 
  void instanceFoo(String s) {
    // use s
  }
 
  static void staticFoo(String s) {
    // use s
  }
 
  public native void bar(JSNIExample x, String s) /*-{
    // Call instance method instanceFoo() on this
    this.@com.google.gwt.examples.JSNIExample::instanceFoo(Ljava/lang/String;)(s);
 
    // Call instance method instanceFoo() on x
    x.@com.google.gwt.examples.JSNIExample::instanceFoo(Ljava/lang/String;)(s);
 
    // Call static method staticFoo()
    @com.google.gwt.examples.JSNIExample::staticFoo(Ljava/lang/String;)(s);
 
    // Read instance field on this
    var val = this.@com.google.gwt.examples.JSNIExample::myInstanceField;
 
    // Write instance field on x
    x.@com.google.gwt.examples.JSNIExample::myInstanceField = val + " and stuff";
 
    // Read static field (no qualifier)
    @com.google.gwt.examples.JSNIExample::myStaticField = val + " and stuff";
  }-*/;
}


Sometimes you need to access a method or constructor defined in GWT from outside JavaScript code. This code might be hand-written and included in another java script file, or it could be a part of a third party library. In this case, the GWT compiler will not get a chance to build an interface between your JavaScript code and the GWT generated JavaScript directly.
A way to make this kind of relationship work is to assign the method via JSNI to an external, globally visible JavaScript name that can be referenced by your hand-crafted JavaScript code.


package mypackage;
 
public MyUtilityClass
{
    public static int computeLoanInterest(int amt, float interestRate,
                                          int term) { ... }
    public static native void exportStaticMethod() /*-{
       $wnd.computeLoanInterest =
          $entry(@mypackage.MyUtilityClass::computeLoanInterest(IFI));
    }-*/;
}
Notice that the reference to the exported method has been wrapped in a call to the $entry function. This implicitly-defined function ensures that the Java-derived method is executed with the uncaught exception handler installed and pumps a number of other utility services. The $entry function is reentrant-safe and should be used anywhere that GWT-derived JavaScript may be called into from a non-GWT context.
On application initialization, call MyUtilityClass.exportStaticMethod() (e.g. from your GWT Entry Point). This will assign the function to a variable in the window object called computeLoanInterest.


Static String Internationalization
Static string initialization requires very little overhead at runtime and therefore is a very efficient technique for translating both constant and parameterized strings. It is also the simplest technique to implement. Static string internationalization uses standard Java properties files to store translated strings and parameterized messages, then implements strongly-typed Java interfaces to retrieve their values.


Dynamic String Internationalization
Dynamic string internationalization is slower than static string internationalization, but is very flexible. Applications using this technique look up localized strings in the module's host page; therefore, they do not need to be recompiled when you add a new locale. If you need to integrate a GWT application with an existing server-side localization system, dynamic string internationalization is the option to consider.


Localizable Interface
The most powerful technique is to implement the Localizable interface. Implementing Localizable allows you to go beyond simple string substitution and create localized versions of custom types. It's an advanced internationalization technique that you probably won't have to use very often.


First create the Java interface (StockWatcherConstants) that accesses the properties files which hold each translation. The interface uses annotations to specify the default translation. This interface implements the GWT Constants interface. This interface is bound automatically to any StockWatcherConstants*.properties files you create because of its name.


First create the Java interface (StockWatcherMessages). It accesses the properties files which hold the translations of each parameterized message. This interface implements the GWT Messages interface. Unlike the StockWatcherConstants interface, the methods in this interface contain parameters. When you call these methods, the arguments you pass will replace the placeholders you left in the strings in the properties files. This interface is bound automatically to any StockWatcherMessages*.properties files you create because of its name.

 

 

 

 

 

采用PyQt5框架与Python编程语言构建图书信息管理平台 本项目基于Python编程环境,结合PyQt5图形界面开发库,设计实现了一套完整的图书信息管理解决方案。该系统主要面向图书馆、书店等机构的日常运营需求,通过模块化设计实现了图书信息的标准化管理流程。 系统架构采用典型的三层设计模式,包含数据存储层、业务逻辑层和用户界面层。数据持久化方案支持SQLite轻量级数据库与MySQL企业级数据库的双重配置选项,通过统一的数据库操作接口实现数据存取隔离。在数据建模方面,设计了包含图书基本信息、读者档案、借阅记录等核心数据实体,各实体间通过主外键约束建立关联关系。 核心功能模块包含六大子系统: 1. 图书编目管理:支持国际标准书号、中国图书馆分类法等专业元数据的规范化著录,提供批量导入与单条录入两种数据采集方式 2. 库存动态监控:实时追踪在架数量、借出状态、预约队列等流通指标,设置库存预警阈值自动提醒补货 3. 读者服务管理:建立完整的读者信用评价体系,记录借阅历史与违规行为,实施差异化借阅权限管理 4. 流通业务处理:涵盖借书登记、归还处理、续借申请、逾期计算等标准业务流程,支持射频识别技术设备集成 5. 统计报表生成:按日/月/年周期自动生成流通统计、热门图书排行、读者活跃度等多维度分析图表 6. 系统维护配置:提供用户权限分级管理、数据备份恢复、操作日志审计等管理功能 在技术实现层面,界面设计遵循Material Design设计规范,采用QSS样式表实现视觉定制化。通过信号槽机制实现前后端数据双向绑定,运用多线程处理技术保障界面响应流畅度。数据验证机制包含前端格式校验与后端业务规则双重保障,关键操作均设有二次确认流程。 该系统适用于中小型图书管理场景,通过可扩展的插件架构支持功能模块的灵活组合。开发过程中特别注重代码的可维护性,采用面向对象编程范式实现高内聚低耦合的组件设计,为后续功能迭代奠定技术基础。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值