简体   繁体   English

为什么我不应该将JSF SessionScoped bean用于逻辑?

[英]Why shouldn't I use a JSF SessionScoped bean for logic?

I'm developing a java EE web app using JSF with a shopping cart style process, so I want to collect user input over a number of pages and then do something with it. 我正在使用带有购物车样式流程的JSF开发一个java EE Web应用程序,所以我想在多个页面上收集用户输入,然后用它做一些事情。

I was thinking to use an EJB 3 stateful session bean for this, but my research leads me to believe that a SFSB is not tied to a client's http session, so I would have to manually keep track of it via an httpSession, some side questions here . 我正在考虑使用EJB 3有状态会话bean,但是我的研究让我相信SFSB并不依赖于客户端的http会话,因此我必须通过httpSession手动跟踪它,一些方面的问题这里 。 . .

1) Why is it called a session bean, as far as I can see it has nothing to do with a session, I could achieve the same by storing a pojo in a session. 1)为什么它被称为会话bean,据我所知它与会话无关,我可以通过在会话中存储pojo来实现同样的目的。

2) What's the point of being able to inject it, if all I'm gonna be injecting' is a new instance of this SFSB then I might as well use a pojo? 2)能够注射它的重点是什么,如果所有我要注射'是这个SFSB的新实例那么我不妨使用pojo?

So back to the main issue I see written all over that JSF is a presentation technology, so it should not be used for logic, but it seems the perfect option for collecting user input. 回到我看到的主要问题,JSF是一种演示技术,所以它不应该用于逻辑,但它似乎是收集用户输入的完美选择。

I can set a JSF session scoped bean as a managed property of all of my request beans which means it's injected into them, but unlike a SFSB the JSF managed session scoped bean is tied to the http session and so the same instance is always injected as long as the http session hasn't been invalidated. 我可以将JSF会话作用域bean设置为我所有请求bean的托管属性,这意味着它被注入到它们中,但与SFSB不同,JSF托管会话作用域bean与http会话绑定,因此相同的实例始终被注入只要http会话没有失效。

So I have multiple tiers 所以我有多层

1st tier) JSF managed request scoped beans that deal with presentation, 1 per page. 第1层)JSF托管请求范围的bean处理演示文稿,每页1个。
2nd tier) A JSF managed session scoped bean that has values set in it by the request beans. 第二层)一个JSF托管会话范围的bean,它由请求bean设置了值。
3rd tier) A stateless session EJB who executes logic on the data in the JSF session scoped bean. 第3层)无状态会话EJB,它对JSF会话范围bean中的数据执行逻辑。

Why is this so bad? 为什么这么糟糕?

Alternative option is to use a SFSB but then I have to inject it in my initial request bean and then store it in the http session and grab it back in each subsequent request bean - just seems messy. 另一种选择是使用SFSB但是我必须将它注入我的初始请求bean中,然后将其存储在http会话中并在每个后续请求bean中将其抓回 - 只是看起来很乱。

Or I could just store everything in the session but this isn't ideal since it involves the use of literal keys and casting . 或者我可以将所有内容存储在会话中,但这并不理想,因为它涉及使用文字键和强制转换。 etc .. etc which is error prone. 等等。这容易出错。 . . and messy! 凌乱!

Any thoughts appreciated I feel like I'm fighting this technology rather than working with it. 任何想法都赞赏我觉得我正在与这项技术作斗争,而不是与之合作。

Thanks 谢谢

Why is it called a session bean, as far as I can see it has nothing to do with a session, I could achieve the same by storing a pojo in a session. 为什么它被称为会话bean,据我所知,它与会话无关,我可以通过在会话中存储pojo来实现同样的目的。

From the old J2EE 1.3 tutorial : 从旧的J2EE 1.3教程

What Is a Session Bean? 什么是会话Bean?

A session bean represents a single client inside the J2EE server. 会话bean表示J2EE服务器内的单个客户端。 To access an application that is deployed on the server, the client invokes the session bean's methods. 要访问部署在服务器上的应用程序,客户端将调用会话Bean的方法。 The session bean performs work for its client, shielding the client from complexity by executing business tasks inside the server. 会话bean为其客户端执行工作,通过在服务器内执行业务任务来保护客户端免受复杂性的影响。

As its name suggests, a session bean is similar to an interactive session. 顾名思义,会话bean类似于交互式会话。 A session bean is not shared--it may have just one client, in the same way that an interactive session may have just one user. 会话bean不是共享的 - 它可能只有一个客户端,就像交互式会话可能只有一个用户一样。 Like an interactive session, a session bean is not persistent. 像交互式会话一样,会话bean不是持久的。 (That is, its data is not saved to a database.) When the client terminates, its session bean appears to terminate and is no longer associated with the client. (也就是说,它的数据不会保存到数据库中。)当客户端终止时,其会话bean似乎终止并且不再与客户端关联。

So it has to do with a "session". 所以它与“会话”有关。 But session not necessarily means "HTTP session" 但会话不一定意味着“HTTP会话”

What's the point of being able to inject it, if all I'm gonna be injecting' is a new instance of this SFSB then I might as well use a pojo? 能够注射它的重点是什么,如果我要注射的是'这个SFSB的新实例那么我不妨使用pojo?

Well, first of all, you don't inject a SFSB in stateless component (injection in another SFSB would be ok), you have to do a lookup. 好吧,首先,你没有在无状态组件中注入SFSB(在另一个SFSB注入就可以了),你必须进行查找。 Secondly, choosing between HTTP session and SFSB really depends on your application and your needs. 其次,在HTTP会话和SFSB之间进行选择实际上取决于您的应用程序和您的需求。 From a pure theoretical point of view, the HTTP session should be used for presentation logic state (eg where you are in your multi page form) while the SFSB should be used for business logic state. 从纯粹的理论角度来看,HTTP会话应该用于表示逻辑状态(例如,您处于多页表单中),而SFSB应该用于业务逻辑状态。 This is nicely explained in the "old" HttpSession vs Stateful session beans thread on TSS which also has a nice example where SFSB would make sense: 在TSS上的“旧” HttpSession vs Stateful会话bean线程中很好地解释了这一点,它也有一个很好的例子,其中SFSB是有意义的:

You may want to use a stateful session bean to track the state of a particular transaction. 您可能希望使用有状态会话bean来跟踪特定事务的状态。 ie some one buying a railway ticket. 即某人购买铁路车票。

The web Session tracks the state of where the user is in the html page flow. Web会话跟踪用户在html页面流中的位置。 However, if the user then gained access to the system through a different channel eg a wap phone, or through a call centre you would still want to know the state of the ticket buying transaction. 但是,如果用户随后通过不同的频道(例如,wap电话)或通过呼叫中心获得了对系统的访问权限,您仍然希望知道购票交易的状态。

But SFSB are not simple and if you don't have needs justifying their use, my practical advice would be to stick with the HTTP session (especially if all this is new to you). 但是SFSB并不简单,如果你没有合理使用它们的需求,我的实际建议就是坚持使用HTTP会话(特别是如果这对你来说都是新的)。 Just in case, see: 以防万一,请参阅:

So back to the main issue I see written all over that JSF is a presentation technology, so it should not be used for logic, but it seems the perfect option for collecting user input. 回到我看到的主要问题,JSF是一种演示技术,所以它不应该用于逻辑,但它似乎是收集用户输入的完美选择。

That's not business logic, that's presentation logic. 这不是业务逻辑,而是表示逻辑。

So I have multiple tiers (...) 所以我有多层(...)

No. You have probably a client tier, a presentation tier, a business tier, a data tier. 不。您可能拥有客户端层,表示层,业务层和数据层。 What you're describing looks more like layers (not even sure). 你所描述的内容看起来更像是层(甚至不确定)。 See: 看到:

Why is this so bad? 为什么这么糟糕?

I don't know, I don't know what you're talking about :) But you should probably just gather the multi page form information into a SessionScoped bean and call a Stateless Session Bean (SLSB) at the end of the process. 我不知道,我不知道你在说什么:)但你应该只是将多页表单信息收集到SessionScoped bean中并在进程结束时调用无状态会话Bean(SLSB)。

1) Why is it called a session bean, as far as I can see it has nothing to do with a session, I could achieve the same by storing a pojo in a session. 1)为什么它被称为会话bean,据我所知它与会话无关,我可以通过在会话中存储pojo来实现同样的目的。

Correction: an EJB session has nothing to do with a HTTP session. 更正:EJB会话与HTTP会话无关。 In EJB, roughly said, the client is the servlet container and the server is the EJB container (both running in a web/application server). 粗略地说,在EJB中,客户端是servlet容器,服务器是EJB容器(都在Web /应用程序服务器中运行)。 In HTTP, the client is the webbrowser and the server is the web/application server. 在HTTP中,客户端是webbrowser,服务器是Web /应用程序服务器。

Does it make more sense now? 现在更有意义吗?

2) What's the point of being able to inject it, if all I'm gonna be injecting' is a new instance of this SFSB then I might as well use a pojo? 2)能够注射它的重点是什么,如果所有我要注射'是这个SFSB的新实例那么我不妨使用pojo?

Use EJB for transactional business tasks. 将EJB用于事务性业务任务。 Use a session scoped managed bean to store HTTP session specific data. 使用会话范围的托管bean来存储特定于HTTP会话的数据。 Neither of both are POJO's by the way. 顺便说一下,两者都不是POJO。 Just Javabeans. 只是Javabeans。

Why shouldn't I use a JSF SessionScoped bean for logic? 为什么我不应该将JSF SessionScoped bean用于逻辑?

If you aren't taking benefit of transactional business tasks and the abstraction EJB provides around it, then just doing it in a simple JSF managed bean is indeed not a bad alternative. 如果您没有利用事务性业务任务和EJB提供的抽象,那么只需在一个简单的JSF托管bean中执行它确实不是一个糟糕的选择。 That's also the normal approach in basic JSF applications. 这也是基本JSF应用程序中的常规方法。 The actions are however usually to be taken place in a request scoped managed bean wherein the session scoped one is been injected as a @ManagedProperty . 但是,这些操作通常发生在请求范围的托管bean中,其中会话范围的一个被注入为@ManagedProperty

But since you're already using EJB, I'd question if there wasn't a specific reason for using EJB. 但是既然你已经在使用EJB,我就会质疑是否没有使用EJB的具体原因。 If that's the business requirement from upper hand, then I'd just stick to it. 如果这是业务需求的优势,那么我就会坚持下去。 At least, your session-confusion should now be cleared up. 至少,现在应该清除你的会话混淆。

Just in case you're not aware of this, and as a small contribution to the answers you have, you could indeed anotate a SFSB with @SessionScoped, and CDI will handle the life cycle of the EJB... This would tie an EJB to the Http Session that CDI manages. 如果您不了解这一点,并且作为对您所拥有的答案的一个小贡献,您确实可以使用@SessionScoped来平衡SFSB,并且CDI将处理EJB的生命周期...这将绑定EJB到CDI管理的Http Session。 Just letting you know, because in your question you say: 只是让你知道,因为在你的问题中你说:

but my research leads me to believe that a SFSB is not tied to a client's http session, so I would have to manually keep track of it via an httpSession, some side questions here . . .

Also, you could do what you suggest, but it depends on your requirements, until CDI beans get declarative transaction support or extended persistence contexts etc, you'll find yourself writing a lot of boilerplate code that would make your bean less clean. 此外,你可以做你的建议,但这取决于你的要求,直到CDI bean获得声明式事务支持或扩展持久性上下文等,你会发现自己编写了很多样板代码,这会使你的bean不那么干净。 Of course you can also use frameworks like Seam (now moving to DeltaSpike ) to enhance certain capabilities of your beans through their extensions. 当然,您也可以使用Seam之类的框架(现在转移到DeltaSpike )来通过扩展来增强bean的某些功能。

So I'd say yes, at first glance you may feel it's not necessary to use a stateful EJB, but certain use cases may be better solve through them. 所以我会说是的,乍一看你可能觉得没有必要使用有状态EJB,但某些用例可能更好地解决它们。 If a user adds a product to his cart, and another user adds this same product later, but there is only one unit in stock, who gets it? 如果用户将产品添加到他的购物车中,而另一个用户稍后添加了相同的产品,但是只有一个库存单位,谁可以获得它? the one who does the checkout faster? 谁更快结账? or the one who added it first? 还是先添加它的人? What if you want to access your entity manager to persist a kart in case the user decides to randomly close his browser or what if you have transactions that spawn multiple pages and you want every step to be synchronized to the db? 如果您想要访问您的实体管理器以保留卡丁车,以防用户决定随机关闭其浏览器,或者如果您有生成多个页面的事务并且您希望每个步骤都与数据库同步,该怎么办? (To keep a transaction open for so long is not advisable but maybe there could be a scenario where this is needed?) You could use SLSB but sometimes it's better and cleaner to use a SFSB.. (为了保持交易开放这么长时间是不可取的,但也许可能存在需要这样做的情况?)你可以使用SLSB,但有时使用SFSB会更好更清洁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM