Java to JavaScript Compilation with AJAX and Spring Integration 是一种将 Java 后端与前端 JavaScript AJAX

本文探讨了Java2Script Pacemaker(J2S),一个开源的Java到JavaScript编译器,它提供了一种透明的开发环境,使Java代码能在浏览器中运行。文章对比了J2S与GWT和OpenLaszlo,并详细介绍了J2S的特点,包括其与Spring框架的集成,以及如何使用J2S进行AJAX远程调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java to JavaScript Compilation with AJAX and Spring Integration 是一种将 Java 后端与前端 JavaScript 通过 AJAX 和 Spring 框架集成的技术。这种技术允许开发者使用 Java 编写服务器端逻辑,而前端则使用 JavaScript 来处理用户界面和交互。通过 AJAX,前端可以在不重新加载整个页面的情况下与服务器通信,从而提高用户体验和应用性能。

Spring 是一个强大的 Java 框架,它提供了一整套解决方案来简化企业级应用的开发,包括依赖注入、面向切面编程、数据访问、事务管理等。通过 Spring 的 MVC(Model-View-Controller)模式,可以很容易地将 Java 后端与前端 JavaScript 进行整合。

在整合过程中,通常会使用 Spring Boot 来快速搭建项目骨架,并利用 Spring MVC 来处理 HTTP 请求。前端可以通过 AJAX 发送请求到后端的控制器(Controller),控制器再调用相应的服务层(Service)处理业务逻辑,最后返回 JSON 或其他格式的数据给前端。

此外,还可以使用 Spring Security 来添加安全性控制,确保只有授权用户才能访问特定的资源。通过这种方式,可以实现一个高效、安全且易于维护的 Java to JavaScript Compilation with AJAX and Spring Integration 的应用架构。
在 Spring Boot 项目中配置 CORS(跨源资源共享)可以通过以下几种方式实现:

  1. 使用注解:

    • 可以在控制器类或方法上使用 @CrossOrigin 注解。例如,允许所有来源访问:
      @CrossOrigin(origins = "*")
      @GetMapping("/example")
      public String example() {
          return "Hello, World!";
      }
      
    • 可以进一步配置请求方法和是否允许凭证等:
      @CrossOrigin(origins = "http://example.com", allowedHeaders = "*", methods = {RequestMethod.GET, RequestMethod.POST}, allowCredentials = "true")
      @GetMapping("/example")
      public String example() {
          return "Hello, World!";
      }
      
  2. 全局配置:

    • 通过创建一个配置类并注册一个 WebMvcConfigurer bean 来全局配置 CORS:
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.web.servlet.config.annotation.CorsRegistry;
      import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
      
      @Configuration
      public class MyConfig {
          @Bean
          public WebMvcConfigurer corsConfigurer() {
              return new WebMvcConfigurer() {
                  @Override
                  public void addCorsMappings(CorsRegistry registry) {
                      registry.addMapping("/**") // 允许所有路径
                              .allowedOrigins("*") // 允许所有来源
                              .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允许的请求方法
                              .allowedHeaders("*") // 允许的请求头
                              .allowCredentials(true); // 是否允许发送 Cookie 信息
                  }
              };
          }
      }
      
  3. 使用过滤器:

    • 如果需要更复杂的 CORS 配置,可以使用过滤器来实现:
      import org.springframework.stereotype.Component;
      import javax.servlet.*;
      import javax.servlet.http.HttpServletResponse;
      import java.io.IOException;
      
      @Component
      public class CorsFilter implements Filter {
          @Override
          public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
              HttpServletResponse response = (HttpServletResponse) res;
              response.setHeader("Access-Control-Allow-Origin", "*");
              response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
              response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
              response.setHeader("Access-Control-Allow-Credentials", "true");
              response.setHeader("Access-Control-Max-Age", "3600");
              chain.doFilter(req, res);
          }
      }
      

Java to JavaScript Compilation with AJAX and Spring Integration
Engineering
Ben Alex
January 22, 2007

For some time I have been interested in client-centric, web-based user interfaces. These Generation IV frameworks are characterised by their component-based, event-driven programming model, and focus on the presentation logic residing entirely on the client. Targeting a web browser in this manner typically necessitates the use of JavaScript or Flash, which in itself imposes a number of unique challenges.

It is possible to address many of these challenges if we can program in Java and automatically produce a JavaScript or Flash runtime module. Two well-known products for achieving this today are Google Web Toolkit (GWT) and Open Laszlo respectively. Both are available under OSI-approved licenses and have active communities, together with their own unique complexity. One consideration is to what extent they fulfil an objective of providing a transparent Java-based development environment that targets web browser deployment. This consideration has several facets, including IDE support, debugging integration, reflective capabilities, runtime widget binding and alike. All of these are normal considerations when developing rich clients using traditional Java technologies such as Swing and Standard Widget Toolkit (SWT).

The purpose of this blog entry is not to critique GWT or Open Laszlo. Instead I would like to explore an open source Java to JavaScript compiler named Java2Script Pacemaker (J2S) and present an initial Spring integration. This interesting project is not widely known, yet addresses transparent Java to JavaScript development in an encouraging manner. J2S ships with an incremental compiler, virtually complete JavaScript version of the java.lang, java.io and java.util packages, a JavaScript version of Junit, an Eclipse SWT JavaScript implementation, plus an AJAX library. More importantly, J2S can convert any existing Java code into JavaScript, subject to the availability of source code and dependencies also being similarly converted into JavaScript.

Focusing on technical considerations, J2S is currently differentiated from GWT in several broad ways. The first is its compiler technology, which builds on Eclipse Abstract Syntax Tree (AST) and therefore requires Eclipse. However, Eclipse JDT Core supports a headless mode and thus it wouldn’t be difficult to execute J2S compilation from an Ant plugin or Maven mojo. The second difference is that J2S provides comprehensive runtime reflection and widget binding capabilities. GWT prefers compile-time JavaScript optimisations, at the expense of these runtime services. J2S – on the other hand – recognises that a combination of Moore’s Law, improved browser JavaScript interpreters and JNI-like JavaScript optimisations collectively provide scope for adequate performance, whilst still enjoying fuller JRE emulation and other runtime services.

Perhaps the biggest technical differentiator relates to the user interface approach. GWT provides its own Swing-like API that was designed for web browser integration. On the other hand, J2S aims to provide an implementation of SWT. There are a number of benefits evident in J2S’ approach:

Your application can target both a rich client (in a JVM) and a web UI (in a web browser), with little to no recoding;

To develop and debug a J2S application is largely the same as developing and debugging an ordinary SWT application, which greatly reduces the learning curve for new developers;

Organisations have a good chance of engaging people with SWT skills;

Plenty of literature and community resources are available for SWT;

SWT is a stable and production-proven API; and

Both open source and commercial tools are available to help you build SWT applications.

J2S does have some limitations to consider, though. These include:

Download speed across the Internet can be slow. Given the majority of JEE applications are for intranet deployment, I am uncertain whether this should represent a major obstacle. Further, JavaScript compression and client caching minimise these delays.

Execution speed can be slow, although I haven’t found it too bad once the code has downloaded. There are various optimisations available to improve speed. There is also the option of power users downloading a JVM-hosted SWT version of the user interface, which should impose limited additional development cost due to the shared SWT codebase.

JFace is currently unsupported, and the full JRE is not emulated. A notable exception is java.io.File. If you depend on this class, your application will not compile natively to JavaScript. Instead you’ll need to use J2S’ @j2sNative capability to compile the relevant classes to JavaScript. I have also encountered a couple of minor issues with the SWT implementation, but nothing too serious.

The J2S community is relatively small, and the framework hasn’t seen wide usage to date. Still, every open source project starts small and needs to be given a chance to grow.

Users of IDEs other than Eclipse will be unable to use J2S in its present form. As mentioned earlier, the AST compilation model allows Eclipse JDT headless support, so this is not a major issue.

The Spring community would also understandably be interested in knowing, “does it work with Spring?”. The answer really depends on what you are trying to achieve. If you’re aiming to build a standard SWT or Swing application, you would generally be using those technologies in the user interface layer to access a remote services layer. As such, your main Spring integration question concerns the availability of a suitable remoting mechanism. Spring offers you a broad choice of proven infrastructure for Java-to-Java remoting, with most projects opting for synchronous HttpInvoker, RMI or SOAP.

By generating a JavaScript-based client, J2S clearly requires some form of Java-to-JavaScript remoting. It is commonplace for Java-to-JavaScript remoting implementations to adopt an asynchronous approach, which means that execution continues immediately after a remoting invocation and there is a separate callback to handle the result of the invocation upon receipt. The two major approaches for Java-to-JavaScript remoting are DWR and JSON-RPC, although both GWT and J2S offer their own independent remoting approaches. Neither the GWT nor J2S approaches offer Spring integration out-of-the-box, although Spring’s flexible architecture makes it quite easy to do so (as I’ll show you in the case of J2S below).

Before we look at the Spring implementation, let’s review how the J2S AJAX remoting protocol operates. J2S adopts a quasi command pattern for each potential remote call. The SimpleRPCRunnable superclass provides JavaScript-to-Java and Java-to-JavaScript serialization, with the subclass indicating the remote URL, fields to serialize and logic to execute remotely:

public class LZ77JSSimpleRPCRunnable extends SimpleRPCRunnable {

private transient SomeServicesLayer servicesLayer; // setter omitted
public String jsContent;
public String result;

public String getHttpURL() {
return “http://localhost:8080/echotest/simplerpc”;
}

public void ajaxRun() {
result = servicesLayer.computeTheAnswer(jsContent);
jsContent = null;
}
}

The field declarations are important. Every public non-transient field will be serialized by SimpleRPCRunnable. The getHttpURL() specifies the URL of the J2S servlet. The same URL can be used for any J2S command, making it the J2S front controller for your application. The ajaxRun() method contains the logic that will be executed on the server side. In this case, our ajaxRun() method is accessing a local (server-side) Spring bean. Note the servicesLayer field is declared transient, which means that SimpleRPCRunnable will not serialize it. Instead the Spring IoC container will dependency inject the SomeServicesLayer instance into our server-side command object. Thus, servicesLayer is always null on the J2S client side. For a client to asynchronously invoke the command, they would use code such as:

SimpleRPCSWTRequest.swtRequest(new LZ77JSSimpleRPCRunnable() {

public void ajaxIn() {
jsContent = sourceText.getText();
}

public void ajaxOut() {
resultText.setText(result);
}
});

As shown, the ajaxIn() method is used to set the public fields to acceptable values on the client side. The ajaxOut() method is the asynchronous callback handler, meaning it is executed once the command object is returned from the server and deserialized. In this case, the command is updating a UI widget. The screen shot below shows the result of executing the command as a JVM-hosted SWT application:
Figure 1

The next screen shot shows the result of executing the same command as a Firefox-hosted SWT application. No code or remoting configuration needed to change between these runtime targets, illustrating the flexibility and appeal of J2S’ approach:
Figure 2

SimpleRPCSWTRequest also offers two static methods for declaring whether an invocation should actually occur across the wire. SimpleRPCSWTRequest.switchToLocalJavaThreadMode() will cause the ajaxRun() method to be invoked locally, which may be appropriate if you are running in a JVM-hosted SWT application. To cause invocations to be serialized across the wire (and thus ajaxRun() to execute on the server), simply invoke SimpleRPCSWTRequest.switchToAJAXMode(). This mode is compatible with both browser and JVM target platforms, so using J2S to build multi-target user interfaces does not necessitate the use of an additional remoting protocol (eg HttpInvoker or RMI) for the JVM target.

Over on the server-side, we are not using the normal J2S SimpleRPCHttpServlet. Instead we are using a new class called SpringRpcHttpServlet (which is available as a ZIP attachment, along with the rest of the code referred to in this blog entry). SpringRpcHttpServlet operates the same as the normal SimpleRPCHttpServlet, except it sources server-side command objects from the Spring application context. The code is well documented, so take a look in the ZIP attachment if you are interested in understanding how it works in detail. Essentially it allows you to define the commands and their dependencies in a Spring application context file.

If your application requires additional commands, it’s simply a case of creating a SimpleRPCRunnable subclass and then adding it to your application context. Those following my work on ROO may be interested to hear I intend to provide J2S remoting integration, freeing you from the need to write command objects or invoke via SimpleRPCSWTRequest.

In conclusion, J2S promises some attractive benefits for projects that require JavaScript compilation or a web browser implementation of SWT. It also interoperates successfully with a Spring backend. J2S’ deliberate choice to leverage proven existing technologies such as AST and SWT make it a good example of reusing existing code and developer skills, in turn lowering adoption barriers and the prospect of material API change. If you consider yourself an early adopter, SWT devotee, or need a client-centric, web-based user interface that is built upon the mature SWT UI framework, it is definitely worth taking a closer look at J2S.
comments powered by Disqus
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值