SeamFramework.orgCommunity Documentation
Web Bean参考实现由Seam项目开发。你可以从the downloads page下载最新的开发者版本。
Web Beans RI自带了两个例子:webbeans-numberguess
(一个仅包含一个简单Bean的WAR应用例子)和webbeans-translator
(一个包含企业Bean的EAR应用例子)。为了运行例子,你需要:
最新的Web Bean参考实现版本,
JBoss AS 5.0.0.GA, 和
Apache Tomcat 6.0.X,和
Ant 1.7.0.
当前,Web Beans参考实现只能运行在JBoss AS 5之上。你需要从jboss.org下载JBoss AS 5.0.0.GA, 然后解压。例如:
$ cd /Applications $ unzip ~/jboss-5.0.0.GA.zip
然后从seamframework.org下载Web Beans的参考实现,然后解压。例如:
$ cd ~/ $ unzip ~/webbeans-1.0.0.ALPHA1.zip
然后,我们需要告诉Web Beans JBoss的位置。编辑jboss-as/build.properties
,设置jboss.home
属性。例如:
jboss.home=/Applications/jboss-5.0.0.GA
为了安装更新,你需要安装Ant 1.7.0,设置ANT_HOME
环境变量。例如:
JBoss 5.1.0 comes with Web Beans built in, so there is no need to update the server.
$ unzip apache-ant-1.7.0.zip $ export ANT_HOME=~/apache-ant-1.7.0
然后,你需要安装更新,更新脚本使用Maven来自动下载Web Beans和EJB3。
$ cd webbeans-1.0.0.ALPHA1/jboss-as $ ant update
现在,你可以部署你的第一个例子了!
例子的构建脚本包含多个目标:
ant restart
- 以exploded形式部署例子
ant explode
- 无需重新部署,更新一个exploded形式部署的例子
ant deploy
- 以压缩jar包形式部署例子
ant undeploy
- 将例子从服务器中移除
ant clean
- 清除例子
部署猜数字(numberguess)例子:
$ cd examples/numberguess ant deploy
启动 JBoss AS:
jboss.home=/Applications/jboss-5.0.0.GA
如果你使用Windows操作系统,则使用run.bat
脚本。
等待应用部署完毕,好好体验一下http://localhost:8080/webbeans-numberguess!
Web Bean参考实现的第二个简单例子能够将你的文本翻译为拉丁文。猜数字例子是一个WAR应用,仅仅使用了一个简单Beans;翻译器例子是一个EAR应用,包含了打包在EJB模块中的企业Beans。试一下:
$ cd examples/traslator ant deploy
等待应用部署,试一下http://localhost:8080/webbeans-translator!
然后从seamframework.org下载Web Beans的参考实现,然后解压。例如:
$ cd /Applications $ unzip ~/jboss-5.0.0.GA.zip
然后从seamframework.org下载Web Beans的参考实现,然后解压。例如:
$ cd ~/ $ unzip ~/webbeans-1.0.0.ALPHA1.zip
然后,我们需要告诉Web Beans JBoss的位置。编辑jboss-as/build.properties
,设置jboss.home
属性。例如:
jboss.home=/Applications/jboss-5.0.0.GA
例子的构建脚本包含多个目标:
ant restart
- 以exploded形式部署例子
ant explode
- 无需重新部署,更新一个exploded形式部署的例子
ant deploy
- 以压缩jar包形式部署例子
ant undeploy
- 将例子从服务器中移除
ant clean
- 清除例子
部署猜数字(numberguess)例子:
$ cd examples/traslator ant deploy
启动Tomcat:
jboss.home=/Applications/jboss-5.0.0.GA
如果你使用Windows操作系统,则使用run.bat
脚本。
等待应用部署完毕,好好体验一下http://localhost:8080/webbeans-numberguess!
在猜数字应用中,你有十次机会来猜一个1到100之间的数字。每次猜测之后,应用都会告诉你你猜的数字是高了还是低了。
猜数字应用由Web Beans,配置文件,Facelete JSF页面组成,打包为一个WAR。我们先看一下配置文件。
猜数字应用的所有的配置文件位于WEB-INF/
,这个目录位于源码树的WebContent
中。首先,我们在faces-config.xml文件中告诉JSF使用Faceletes:
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="1.2"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
<application>
<view-handler
>com.sun.facelets.FaceletViewHandler</view-handler>
</application>
</faces-config
>
这有一个空的web-beans.xml
文件,标识这个应用是一个Web Beans应用。
最后,这有一个 web.xml
:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name >Web Beans Numbergues example</display-name> <!-- JSF --><servlet> <servlet-name >Faces Servlet</servlet-name> <servlet-class >javax.faces.webapp.FacesServlet</servlet-class> <load-on
-startup >1</load-on-startup> </servlet> <servlet-mapping> <servlet
-name >Faces Servlet</servlet-name> <url-pattern >*.jsf</url-pattern> </servlet-mapping>
<context-param> <param-name >javax.faces.DEFAULT_SUFFIX</param-name> <param-v
alue >.xhtml</param-value> </context-param> <session-config> <session-timeout >10</session-timeout> </session-config> </web-app >
![]() | Enable and load the JSF servlet |
![]() | Configure requests to |
![]() | Tell JSF that we will be giving our source files (facelets) an extension of |
![]() | Configure a session timeout of 10 minutes |
Whilst this demo is a JSF demo, you can use Web Beans with any Servlet based web framework.
Let's take a look at the Facelet view:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:s="http://jboss.com/products/seam/taglib"> <ui:composition template="template.xhtml"> <ui:define name="content"> <h1 >Guess a number...</h1> <h:form
id="NumberGuessMain"> <div style="color: red"> <h:messages id="messages" globalOnly="false"/> <h:outputText id="Higher" value="Higher!" rendered="#{game.number gt game.guess and game.guess ne 0}"/> <h:outputText id="Lower" value="Lower!" rendered="#{game.number lt game.guess and game.guess ne 0}"/> </div> <div
> I'm thinking of a number between #{game.smallest} and #{game.biggest}. You have #{game.remainingGuesses} guesses. </div> <div> Y
our guess: <h:inputText id="inputGuess" value="#{game.guess}" required="true" size="3"
disabled="#{game.number eq game.guess}"> <f:validateLongRange maximum="#{game.biggest}" minimum="#{game.smallest}"/> <
/h:inputText> <h:commandButton id="GuessButton" value="Guess" action="#{game.check}" disabled="#{game.number eq game.guess}"/> </div> <div> <h:commandButton id="RestartButton" value="Reset" action="#{game.reset}" immediate="true" /> </div> </h:form> </ui:define> </ui:composition> </html >
![]() | Facelets is a templating language for JSF, here we are wrapping our page in a template which defines the header. |
![]() | There are a number of messages which can be sent to the user, "Higher!", "Lower!" and "Correct!" |
![]() | As the user guesses, the range of numbers they can guess gets smaller - this sentance changes to make sure they know what range to guess in. |
![]() | This input field is bound to a Web Bean, using the value expression. |
![]() | A range validator is used to make sure the user doesn't accidentally input a number outside of the range in which they can guess - if the validator wasn't here, the user might use up a guess on an out of range number. |
![]() | And, of course, there must be a way for the user to send their guess to the server. Here we bind to an action method on the Web Bean. |
这个例子包括4个类,前面两个是绑定类型。首先,这有一个@Random
绑定类型,用来注入一个随机数:
@Target( { TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
@BindingType
public @interface Random {}
这还有一个@MaxNumber
绑定类型,用来注入一个最大值:
@Target( { TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
@BindingType
public @interface MaxNumber {}
Generator
类通过一个生产者(producer)方法创建一个随机数。它也通过一个生产者方法暴露可能的最大值:
@ApplicationScoped
public class Generator {
private java.util.Random random = new java.util.Random( System.currentTimeMillis() );
private int maxNumber = 100;
java.util.Random getRandom()
{
return random;
}
@Produces @Random int next() {
return getRandom().nextInt(maxNumber);
}
@Produces @MaxNumber int getMaxNumber()
{
return maxNumber;
}
}
你会注意到Generator
是应用范围的;因此我们不会每次都得到一个不同的随机对象。
最终的应用中的Web Bean是会话范围的 Game
。
你也许注意到我们使用了 @Named
注释,以便我们能够通过EL(表达式语言)在JSF页面中使用Bean。最后,我们通过构造器注入来初始化猜数字游戏并给它设一个随机数。当然,在玩家猜对数字后,我们需要告诉玩家他赢了,所以我们通过FacesMessage
反馈给玩家一条信息。
package org.jboss.webbeans.examples.numberguess;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.webbeans.AnnotationLiteral;
import javax.webbeans.Current;
import javax.webbeans.Initializer;
import javax.webbeans.Named;
import javax.webbeans.SessionScoped;
import javax.webbeans.manager.Manager;
@Named
@SessionScoped
public class Game
{
private int number;
private int guess;
private int smallest;
private int biggest;
private int remainingGuesses;
@Current Manager manager;
public Game()
{
}
@Initializer
Game(@MaxNumber int maxNumber)
{
this.biggest = maxNumber;
}
public int getNumber()
{
return number;
}
public int getGuess()
{
return guess;
}
public void setGuess(int guess)
{
this.guess = guess;
}
public int getSmallest()
{
return smallest;
}
public int getBiggest()
{
return biggest;
}
public int getRemainingGuesses()
{
return remainingGuesses;
}
public String check()
{
if (guess
>number)
{
biggest = guess - 1;
}
if (guess<number)
{
smallest = guess + 1;
}
if (guess == number)
{
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));
}
remainingGuesses--;
return null;
}
@PostConstruct
public void reset()
{
this.smallest = 0;
this.guess = 0;
this.remainingGuesses = 10;
this.number = manager.getInstanceByType(Integer.class, new AnnotationLiteral<Random
>(){});
}
}
The numberguess for Tomcat differs in a couple of ways. Firstly, Web Beans should be deployed as a Web Application library in WEB-INF/lib
. For your convenience we provide a single jar suitable for running Web Beans in any servlet container webbeans-servlet.jar
.
当然,你必须也要包含JSF和EL, 以及通用的注释(jsr250-api.jar
),这些都是一个Java EE服务器默认应该包含的。
Secondly, we need to explicitly specify the servlet listener (used to boot Web Beans, and control it's interaction with requests) in web.xml
:
<listener> <listener-class >org.jboss.webbeans.environment.servlet.Listener</listener-class> </listener >
Whilst JSR-299 specifies integration with Java ServerFaces, Web Beans allows you to inject into Wicket components, and also allows you to use a conversation context with Wicket. In this section, we'll walk you through the Wicket version of the numberguess example.
You may want to review the Wicket documentation at http://wicket.apache.org/.
Like the previous example, the Wicket WebBeans examples make use of the webbeans-servlet
module. The use of the Jetty servlet container is common in the Wicket community, and is chosen here as the runtime container in order to facilitate comparison between the standard Wicket examples and these examples, and also to show how the webbeans-servlet integration is not dependent upon Tomcat as the servlet container.
These examples make use of the Eclipse IDE; instructions are also given to deploy the application from the command line.
To generate an Eclipse project from the example:
cd examples/wicket/numberguess mvn -Pjetty eclipse:eclipse
Then, from eclipse, choose File -> Import -> General -> Existing Projects into Workspace, select the root directory of the numberguess example, and click finish. Note that if you do not intend to run the example with jetty from within eclipse, omit the "-Pjetty." This will create a project in your workspace called webbeans-wicket-numberguess
This project follows the wicket-quickstart
approach of creating an instance of Jetty in the Start
class. So running the example is as simple as right-clicking on that Start class in src/test/java
in the Package Explorer and choosing Run as Java Application. You should see console output related to Jetty starting up; then visit able http://localhost:8080
to view the app. To debug choose Debug as Java Application.
This example can also be deployed from the command line in a (similar to the other examples). Assuming you have set up the build.properties
file in the examples
directory to specify the location of JBoss AS or Tomcat, as previously described, you can run ant deploy
from the examples/wicket/numberguess
directory, and access the application at http://localhost:8080/webbeans-numberguess-wicket
.
JSF uses Unified EL expressions to bind view layer components in JSP or Facelet views to beans, Wicket defines it's components in Java. The markup is plain html with a one-to-one mapping between html elements and the view components. All view logic, including binding of components to models and controlling the response of view actions, is handled in Java. The integration of Web Beans with Wicket takes advantage of the same binding annotations used in your business layer to provide injection into your WebPage subclass (or into other custom wicket component subclasses).
The code in the wicket numberguess example is very similar to the JSF-based numberguess example. The business layer is identical!
Differences are:
Each wicket application must have a WebApplication
subclass, In our case, our application class is SampleApplication
:
public class SampleApplication extends WebBeansApplication { @Override public Class getHomePage() { return HomePage.class; } }
This class specifies which page wicket should treat as our home page, in our case, HomePage.class
In HomePage
we see typical wicket code to set up page elements. The bit that is interesting is the injection of the Game
bean:
@Current Game game;
The Game
bean is can then be used, for example, by the code for submitting a guess:
final Component guessButton = new AjaxButton("GuessButton") { protected void onSubmit(AjaxRequestTarget target, Form form) { if (game.check()) {
All injections may be serialized; actual storage of the bean is managed by JSR-299. Note that Wicket components, like the HomePage and it subcomponents, are not JSR-299 beans.
Wicket components allow injection, but they cannot use interceptors, decorators and lifecycle callbacks such as @PostConstruct
or @Initializer
methods.
The example uses AJAX for processing of button events, and dynamically hides buttons that are no longer relevant, for example when the user has won the game.
In order to activate wicket for this webapp, the Wicket filter is added to web.xml, and our application class is specified:
<filter> <filter-name >wicket.numberguess-example</filter-name> <filter-class >org.apache.wicket.protocol.http.WicketFilter</filter-class> <init-param> <param-name >applicationClassName</param-name> <param-value >org.jboss.webbeans.examples.wicket.SampleApplication</param-value> </init-param> </filter> <filter-mapping> <filter-name >wicket.numberguess-example</filter-name> <url-pattern >/*</url-pattern> </filter-mapping> <listener> <listener-class >org.jboss.webbeans.environment.servlet.Listener</listener-class> </listener >
Note that the servlet listener is also added, as in the Tomcat example, in order to boostrap Web Beans when Jetty starts, and to hook Web Beans into the Jetty servlet request and session lifecycles.
This example can be found in the examples/se/numberguess
folder of the Web Beans distribution.
To run this example:
Open a command line/terminal window in the examples/se/numberguess
directory
Ensure that Maven 2 is installed and in your PATH
Ensure that the JAVA_HOME
environment variable is pointing to your JDK installation
execute the following command
mvn -Drun
There is an empty beans.xml
file in the root package (src/main/resources/beans.xml
), which marks this application as a Web Beans application.
The game's main logic is located in Game.java
. Here is the code for that class, highlighting the changes made from the web application version:
@ApplicationScoped
public class Game implements Serializable
{
private int number;
private int guess;
private int smallest;
@MaxNumber
private int maxNumber;
private int biggest;
private int remainingGuesses;
private boolean validNumberRange = true;
@Current Generator rndGenerator;
...
public boolean isValidNumberRange()
{
return validNumberRange;
}
public boolean isGameWon(){
return guess == number;
}
public boolean isGameLost()
{
return guess != number && remainingGuesses <= 0;
}
public boolean check()
{
boolean result = false;if ( checkNewNumberRangeIsValid() )
{
if ( guess
> number )
{
biggest = guess - 1;
}
if ( guess < number )
{
smallest = guess + 1;
}
if ( guess == number )
{
result = true;
}
remainingGuesses--;
}
return result;
}
private boolean checkNewNumberRangeIsValid()
{
return validNumberRange = ( ( guess
>= smallest ) && ( guess <= biggest ) );
}![]()
@PostConstruct
public void reset()
{
this.smallest = 0;
...
this.number = rndGenerator.next();
}
}
![]() | The bean is application scoped instead of session scoped, since an instance of the application represents a single 'session'. |
![]() | The bean is not named, since it doesn't need to be accessed via EL |
![]() | There is no JSF
This allows the Swing UI to query the state of the game, which it does indirectly via a class called |
![]() | Validation of user input is performed during the |
![]() | The |
The MessageGenerator
class depends on the current instance of Game
, and queries its state in order to determine the appropriate messages to provide as the prompt for the user's next guess and the response to the previous guess. The code for MessageGenerator
is as follows:
public class MessageGenerator
{@Current Game game;
public String getChallengeMessage()
{
StringBuilder challengeMsg = new StringBuilder( "I'm thinking of a number between " );
challengeMsg.append( game.getSmallest() );
challengeMsg.append( " and " );
challengeMsg.append( game.getBiggest() );
challengeMsg.append( ". Can you guess what it is?" );
return challengeMsg.toString();
}public String getResultMessage()
{
if ( game.isGameWon() )
{
return "You guess it! The number was " + game.getNumber();
} else if ( game.isGameLost() )
{
return "You are fail! The number was " + game.getNumber();
} else if ( ! game.isValidNumberRange() )
{
return "Invalid number range!";
} else if ( game.getRemainingGuesses() == Game.MAX_NUM_GUESSES )
{
return "What is your first guess?";
} else
{
String direction = null;
if ( game.getGuess() < game.getNumber() )
{
direction = "Higher";
} else
{
direction = "Lower";
}
return direction + "! You have " + game.getRemainingGuesses() + " guesses left.";
}
}
}
![]() | The instance of |
![]() | The |
![]() | And again to determine whether to congratulate, console or encourage the user to continue. |
Finally we come to the NumberGuessFrame
class which provides the Swing front end to our guessing game.
public class NumberGuessFrame extends javax.swing.JFrame
{private @Current Game game;
private @Current MessageGenerator msgGenerator;
public void start( @Observes @Deployed Manager manager )
{
java.awt.EventQueue.invokeLater( new Runnable()
{
public void run()
{
initComponents();
setVisible( true );
}
} );
}private void initComponents() {
buttonPanel = new javax.swing.JPanel();
mainMsgPanel = new javax.swing.JPanel();
mainLabel = new javax.swing.JLabel();
messageLabel = new javax.swing.JLabel();
guessText = new javax.swing.JTextField();
...
mainLabel.setText(msgGenerator.getChallengeMessage());
mainMsgPanel.add(mainLabel);
messageLabel.setText(msgGenerator.getResultMessage());
mainMsgPanel.add(messageLabel);
...
}private void guessButtonActionPerformed( java.awt.event.ActionEvent evt )
{
int guess = Integer.parseInt(guessText.getText());
game.setGuess( guess );
game.check();
refreshUI();
}private void replayBtnActionPerformed( java.awt.event.ActionEvent evt )
{
game.reset();
refreshUI();
}private void refreshUI()
{
mainLabel.setText( msgGenerator.getChallengeMessage() );
messageLabel.setText( msgGenerator.getResultMessage() );
guessText.setText( "" );
guessesLeftBar.setValue( game.getRemainingGuesses() );
guessText.requestFocus();
}
// swing components
private javax.swing.JPanel borderPanel;
...
private javax.swing.JButton replayBtn;
}
![]() | The injected instance of the game (logic and state). |
![]() | The injected message generator for UI messages. |
![]() | This application is started in the usual Web Beans SE way, by observing the |
![]() | This method initialises all of the Swing components. Note the use of the |
![]() |
|
![]() | |
![]() | |
翻译器例子能够将你输入的句子翻译为拉丁文。
翻译器例子是一个EAR应用,包含EJBs和企业Beans。因此,它的结构比猜数字例子复杂。
EJB3.1和Java EE 6允许你在WAR包中打包EJBs, 这将让这个结构更加简单!
首先,让我们看一下EAR聚合器,它位于webbeans-translator-ear
模块下。Maven将为我们自动生成application.xml
和jboss-app.xml
文件:
<plugin>
<groupId
>org.apache.maven.plugins</groupId>
<artifactId
>maven-ear-plugin</artifactId>
<configuration>
<modules>
<webModule>
<groupId
>org.jboss.webbeans.examples.translator</groupId>
<artifactId
>webbeans-translator-war</artifactId>
<contextRoot
>/webbeans-translator</contextRoot>
</webModule>
</modules>
<jboss>
<loader-repository
>webbeans.jboss.org:loader=webbeans-translator</loader-repository>
</jboss>
</configuration>
</plugin
>
我们需要在这里做些事情-首先我们需要设置上下文路径为一个不错的URL(http://localhost:8080/webbeans-translator),我们还需要将JBoss AS的类加载器隔离配置激活。
如果你不使用Maven来生成这些文件,你将需要META-INF/jboss-app.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_5.xsd"
version="5">
<display-name
>webbeans-translator-ear</display-name>
<description
>Ear Example for the reference implementation of JSR 299: Web Beans</description>
<module>
<web>
<web-uri
>webbeans-translator.war</web-uri>
<context-root
>/webbeans-translator</context-root>
</web>
</module>
<module>
<ejb
>webbeans-translator.jar</ejb>
</module>
</application
>
然后,我们看一下WAR包。在猜数字例子中,我们需要faces-config.xml
(配置Facelets)和一个位于WebContent/WEB-INF
下的web.xml
(配置JSF并将Web Beans服务加入Servlet容器中)。
更有意思的是用来翻译文本的facelet。在猜数字应用中我们有一个模板,这个模板套着表单(省略了表单):
<h:form id="NumberGuessMain">
<table>
<tr align="center" style="font-weight: bold" >
<td>
Your text
</td>
<td>
Translation
</td>
</tr>
<tr>
<td>
<h:inputTextarea id="text" value="#{translator.text}" required="true" rows="5" cols="80" />
</td>
<td>
<h:outputText value="#{translator.translatedText}" />
</td>
</tr>
</table>
<div>
<h:commandButton id="button" value="Translate" action="#{translator.translate}"/>
</div>
</h:form
>
用户可以在左手边的文本区输入一些文本,点击翻译按钮查看右边的翻译结果。
最后,我们看一下EJB模块,webbeans-translator-ejb
。在src/main/resources/META-INF
下有两个配置文件,一个是空的web-beans.xml
,用来标识这个档案包包含Web Beans,一个是ejb-jar.xml
。Web Beans为所有的EJB提供注入和初始化服务,使用ejb-jar.xml
文件来配置。你将在使用Web Beans的EJB项目中需要这些配置:
我们将最有意思的部分放在最后,那就是代码!这个例子有两个简单Beans, SentanceParser
和TextTranslator
,还有两个企业Beans,TanslatorControllerBean
和SentenceTranslator
。现在你应该对Web Beans有点熟悉了,我们在这里着重最有意思的部分。
SentanceParser
和TextTranslator
是相互依赖的Beans,TextTranslator
使用构造器初始化:
public class TextTranslator {
private SentenceParser sentenceParser;
private Translator sentenceTranslator;
@Initializer
TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator)
{
this.sentenceParser = sentenceParser;
this.sentenceTranslator = sentenceTranslator;
TextTranslator
是一个无状态Bean(拥有一个本地业务接口),这里是魔术展现的地方-当然,我们不会开发一个完整的翻译器,但我们可以开发一个不错的小玩意!
最后,这里又要一个面向UI的控制器,从用户输入处搜集文本,转发给翻译器。这个控制器是请求范围的,具名的,有状态的会话Bean,它可以将翻译器注入进来。
@Stateful
@RequestScoped
@Named("translator")
public class TranslatorControllerBean implements TranslatorController
{
@Current TextTranslator translator;
这个Bean也拥有页面上所有域的getter和setter方法。
这个Bean是有状态会话Bean,我们需要有一个remove方法:
@Remove
public void remove()
{
}
Web Beans管理器在这个bean销毁的时候调用remove方法;在这个例子中是请求结束的时候。
Web Beans参考实现的例子到此结束。想要获得关于参考实现更多的知识或者帮助,请访问http://www.seamframework.org/WebBeans/Development。
我们在各个方面都需要帮助-bug修复,新特性开发,例子开发和参考指南的翻译等等。