我正在使用 Spring MVC 和 Groovy 将已经存在的 Java Web 应用程序转换为 RESTful Web 应用程序。我想要实现的主要功能之一是热部署。我选择 groovy 是因为我不想更改已经实现的业务逻辑(处理程序),而且如果我必须在部署后更改 groovy 代码,我可以轻松地做到这一点而无需重新启动服务器(即在运行时)。可以这样做是因为 Spring 支持 groovy 脚本(bean)的动态重新加载。如果它们被更改,它会重新加载动态语言类。
我正在使用 Spring 注释将请求 URL 映射到控制器方法,并且应用程序部署在 tomcat 6.0.35 中。
这是 web.xml 文件
//web.xml
<?xml version = "1.0" encoding = "UTF-8"?>
<web-app 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" version="2.5">
<!-- Spring Dispatcher -->
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
<!-- Loads application context files in addition to ${contextConfigLocation} -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Set session timeout to 30 minutes -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
这个 groovy 文件是 DispatcherServlet 将请求映射到的控制器。
// UserController.groovy
@Controller
class UserController
{
// This is the method to which the HTTP request is submitted to based on the mapping of the
// action field of the form ie. /service/user/login/auth.json
@RequestMapping(value="/user/login/auth.{extension:[a-zA-Z]+}", method=RequestMethod.POST)
@ResponseBody
public String authenticate(
@PathVariable String extension,
@RequestParam(value="username", required=true) String username,
@RequestParam(value="password", required=true) String password)
{
// UserResource makes the backend calls, authenticates a user and returns the result.
def user = new UserResource()
def result = user.login(name:username, userPassword:password)
// Output the result of the query. Method makeView makes a JSON response of the result
// and sends to the client(browser)
def builder = makeView(extension)
{
it.login(action:result.action, message:result.message)
}
}
}
Spring 配置文件如下,我使用了支持动态语言的“lang:groovy”标签。我还提到刷新时间为 5 秒,因此在运行时对这些 groovy 文件所做的任何更改都可以每 1 秒看到一次,并且类会重新加载。
//applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.1.xsd
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang-3.1.xsd">
<context:annotation-config/>
<context:component-scan base-package="app.controller,app.resource" />
<lang:groovy id="user" script-source="classpath:controller/UserController.groovy" refresh-check-delay="1000"></lang:groovy>
<!-- To enable @RequestMapping process on type level and method level -->
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<!-- Resolves view names to template resources within the directory -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".html"/>
</bean>
</beans>
我已经相应地配置了我的 Buildpath 和 groovy 编译器,以便所有 groovy 脚本都直接复制到目标文件夹,而不是编译为类文件。
主要问题
当我在 tomcat 服务器中部署这个项目时,它会加载所有需要的 Spring bean,包括 ScriptProcessor。现在,当我打开浏览器,加载表单并尝试提交身份验证表单时,我在 Tomcat 日志中收到以下错误:
15:20:09 WARN - No mapping found for HTTP request with URI [/service/user/login/auth.json] in DispatcherServlet with name 'rest'
我还在 $TOMCAT_DIR/conf/context.xml 中对防锁资源和 JARS 进行了更改
<Context antiResourceLocking="true" antiJARLocking="true" reloadable="true" privileged="true">
.
.
.</Context>
但是,如果我将我的项目配置为将这些 groovy 脚本编译为字节码类,注释掉 applicationContext.xml 中的“lang:groovy”标签,然后重新启动服务器,那么 groovy 脚本将被编译为类文件,并且完美地处理了请求. 进行身份验证。
此外,如果我使用以下两行而不是标记在 applicationContet.xml 中配置动态 bean,我的 bean 确实会在运行时动态创建,并且由于注释,URL 会映射到相应的控制器方法。
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor" />
<bean id ="User" class="org.springframework.scripting.groovy.GroovyScriptFactory">
<constructor-arg value="classpath:controller/UserController.groovy" />
</bean>
但我不知道如何用这种风格创建 bean 刷新功能。所以我猜标签处理 groovy 脚本的方式存在问题。
我真的很感激这方面的一些帮助。我在整个互联网上搜索并阅读了无数的教程,并按照那里提到的确切程序进行操作。但我不知道出了什么问题。
请帮我解决这个问题。
谢谢你。