在 JSP 中自动装配 Spring Beans 最简洁的方法是什么?

发布于 2024-08-19 08:49:48 字数 439 浏览 11 评论 0原文

我们目前正在向旧的 Web 应用程序添加一些新功能,该应用程序仅使用 JSP,没有任何前端框架。我们最近添加了 Spring,并且希望在修改后的 JSP 中自动装配 Bean,同时不重写所有内容以使用 SpringMVC、Struts2 或 Tapestry5。

我们使用按类型自动装配,因此它会导致在 JSP 中获取类似这样的代码,同时之前获取 Web 应用程序上下文(如“wap”):

MyDao myDao = (MyDao) wap.getBeansOfType(MyDao.class).values().toArray()[0];

我们不想使用这样的代码,而是自动注入我们的 bean直接在我们的 JSP 中,就像我们在业务 bean 中使用 @Autowired 注释一样。

事实上,我们正在寻找在 JSP 中注入 Bean 的最简洁方法。你用什么?

We're currently adding some new features to an old webapp which was using only JSP without any framework for the front. We have added Spring recently, and we would like to autowire our beans in our modified JSP, while not rewriting everything to use SpringMVC, Struts2 or Tapestry5.

We're using autowiring by type, so it leads to get some code like this in the JSP, while previously getting the web application context ( as "wap") :

MyDao myDao = (MyDao) wap.getBeansOfType(MyDao.class).values().toArray()[0];

We would like not to use such a code but rather automagically inject our beans directly in our JSPs as we would in a business bean using @Autowired annotation.

In fact we're looking to the cleanest ways to inject our beans in our JSPs. What do you use ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

傲世九天 2024-08-26 08:49:48

您可以使用Spring的 ContextExusingHttpServletRequest

HttpServletRequest 装饰器
使所有 Spring beans 处于给定状态
WebApplicationContext 可访问为
请求属性,通过lazy
一旦属性获取就检查
已访问。

这需要您的控制器代码将原始 HttpServletRequest 包装在 ContextExusingHttpServletRequest 中,然后将其转发到 JSP。它可以公开特定的命名 bean,也可以公开上下文中的每个 bean。

当然,这只是将问题从 JSP 转移到控制器代码,但这可能是一个更易于管理的问题。

You can use Spring's ContextExposingHttpServletRequest:

HttpServletRequest decorator that
makes all Spring beans in a given
WebApplicationContext accessible as
request attributes, through lazy
checking once an attribute gets
accessed.

This would require your controller code to wrap the original HttpServletRequest in a ContextExposingHttpServletRequest, and then forward that to the JSP. It can either expose specific named beans, or every bean in the context.

Of course, this just shifts the problem from your JSPs to your controller code, but that's perhaps a more manageable problem.

﹂绝世的画 2024-08-26 08:49:48

您不能直接使用@Autowired,因为您的jsps 和servlet 都是由servlet 容器实例化的。因此它们不是 spring 上下文的一部分,因此不会注入它们的依赖项。

您可以:

  1. 将所有代码移至纯 servlet,而不是放在 jsps 中 - 仅在 jsps 中保留演示。
  2. 使用 @Configurable您的 servlet(并添加 javaagent,如链接文档中所述)

另一种方法是手动使 servlet 成为当前上下文的一部分。这在 jsps 和 servlet 中都是可能的:

public void init() {
    WebApplicationContext ctx = WebApplicationContextUtils
         .getRequiredWebApplicationContext(getServletContext());

    AutowireCapableBeanFactory bf = ctx.getAutowireCapableBeanFactory();

    bf.autowireBean(this);
}

这将解决 @Autowired 带注释的依赖项。

现在,我不确定 servlet 容器是否需要仅使用 servlet 类的一个实例。如果没有,您最好将上述代码放在依赖项的 getter 方法中 (getDao()),并且 @Autowired 属性为 null< /code>(即容器使用 servlet 类的另一个实例)- 执行上述操作。


总而言之,确实考虑使用 Web 框架(您列出的任何框架)。在jsps中拥有逻辑是完全错误的,难以支持,难以阅读等等。

You can't use @Autowired directly because both your jsps and servlets are instantiated by the servlet conainer. So they are not part of the spring context and hence their dependencies aren't injected.

You can:

  1. move all code that to pure servlets, rather than in jsps - leave only presentation in the jsps.
  2. use @Configurable on your servlets (and add a javaagent, as described in the linked docs)

Another way, is to make the servlet part of the current context manually. This is possible in both jsps and servlets:

public void init() {
    WebApplicationContext ctx = WebApplicationContextUtils
         .getRequiredWebApplicationContext(getServletContext());

    AutowireCapableBeanFactory bf = ctx.getAutowireCapableBeanFactory();

    bf.autowireBean(this);
}

This will resolve the @Autowired annotated dependencies.

Now, I'm not sure whether servlet containers are required to use only one instance of a servlet class. If not, you'd better place the above code in a getter-method for the dependency (getDao()) and if the @Autowired property is null (i.e. another instance of the servlet-class is used by the container) - perform the above operation.


That all said, really consider using a web framework (any of the ones you listed). Having logic in jsps is completely wrong, hard to support, hard to read, etc.

感情旳空白 2024-08-26 08:49:48

重写 jspInit() 方法并添加自动装配支持怎么样:

<%@ page import="com.example.ExampleService"%>
<%@ page import="org.springframework.beans.factory.annotation.Value"%>
<%@ page import="org.springframework.beans.factory.annotation.Autowired"%>
<%@ page import="org.springframework.web.context.support.SpringBeanAutowiringSupport"%>
<%!
    public void jspInit() 
    {
        SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,
        getServletContext());
    }

    @Value("${example.property}")
    private String someField;

    @Autowired
    private ExampleService exampleService;
%>

<% final Object data = exampleService.getSomething(someField); %>

What about overriding jspInit() method and adding Autowiring support:

<%@ page import="com.example.ExampleService"%>
<%@ page import="org.springframework.beans.factory.annotation.Value"%>
<%@ page import="org.springframework.beans.factory.annotation.Autowired"%>
<%@ page import="org.springframework.web.context.support.SpringBeanAutowiringSupport"%>
<%!
    public void jspInit() 
    {
        SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,
        getServletContext());
    }

    @Value("${example.property}")
    private String someField;

    @Autowired
    private ExampleService exampleService;
%>

<% final Object data = exampleService.getSomething(someField); %>
一枫情书 2024-08-26 08:49:48

我怀疑是否有一种干净的方法可以将依赖项注入到 JSP 中。

我认为干净的解决方案是开始重构代码,使用 SpringMVC 或您引用的替代方案之一从 JSP 中获取业务逻辑。

从一个或多个极简控制器开始,这些控制器只需将请求传递给 JSP,并将注入的 Bean 作为属性; @skaffman的答案给出了一种方法来做到这一点,或者你可以更有选择地做到这一点。然后逐步将代码从 JSP 迁移到控制器中。

I doubt that there is a clean way to inject dependencies into a JSP.

I think that the clean solution would be to start refactoring your code to get the business logic out of the JSPs, using either SpringMVC or one of the alternatives you cited.

Start with one or more minimalist controllers that simply pass the request to the JSPs with the injected beans as attributes; @skaffman's answer gives one way to do that, or you could do it more selectively. Then progressively migrate code out of the JSPs and into the controllers.

笑梦风尘 2024-08-26 08:49:48

这不是自动装配的,但 Spring 可以将您的 bean 名称公开到请求上下文中,您只需在 viewResolver 中配置它即可。

来自: https://raibledesigns.com/rd/entry/spring_mvc_jstlview_and_exposecontextbeansasattributes

<bean id="viewResolver" 
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="exposeContextBeansAsAttributes" value="true"/>
    <property name="prefix" value="/"/>
    <property name="suffix" value=".jsp"/>
</bean>

This isn't autowired, but Spring can expose your bean names into the request context, you just need to configure it in the viewResolver.

From: https://raibledesigns.com/rd/entry/spring_mvc_jstlview_and_exposecontextbeansasattributes

<bean id="viewResolver" 
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="exposeContextBeansAsAttributes" value="true"/>
    <property name="prefix" value="/"/>
    <property name="suffix" value=".jsp"/>
</bean>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文