【发布时间】:2015-11-26 21:51:14
【问题描述】:
我一直在使用 Spring MVC 4/hibernate 4 和带有 Java 配置的 Web flow 2.4 构建应用程序。我已经使用 JUnits 构建和测试了服务和 daos,但是将 WebFlow 组件添加到应用程序中却一无所获。
我将控制器连同 CoreContextConfiguration 一起移到了核心包中,却一无所获。 LoginController 在 WEB-INF/flows 中有一个对应的 login.jsp 和一个 login-flow.xml 我希望 Spring Webflow 处理控制器,并且可以根据需要显示更多配置代码。我知道我错过了一些东西,可以用新的眼光来看待这个问题。
@EnableWebMvc//added
@Configuration
@Import({
ServiceConfiguration.class,
FlowConfiguration.class,
WebMVCConfiguration.class,
DAOConfiguration.class
})
@ComponentScan("org.tigersndragons.salonbooks.model")
public class CoreContextConfiguration {
INFO: Server startup in 12640 ms
Jun 02, 2014 3:14:43 PM org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping found for HTTP request with URI [/salonbooks/login] in DispatcherServlet with name 'salonbooks'
我在尝试从
访问应用程序时收到上述错误localhost:8080/salonbooks/login
如果我将 LoginController 显式导入到 CoreConfiguration,我会得到
javax.servlet.ServletException: No adapter for handler [org.tigersndragons.salonbooks.core.LoginController@20bd9af4]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler
下面是控制器sn-p
-- 更新为从配置中移除控制器
@Controller
public class LoginController extends AbstractController{
@Autowired
LoginActionFlows loginActionFlows;
@RequestMapping(value="/login", method=RequestMethod.GET)
public String showLogin(Model model){
model.addAttribute("employee", new Employee());
return "login";//new ModelAndView("index","employee", model);
}
@RequestMapping(value="/", method=RequestMethod.GET)
public String index(Model model){
return showLogin( model);//new ModelAndView("index","employee", model);
}
web.xml 看起来像
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>SalonBooks</display-name>
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>org.tigersndragons.salonbooks.core.CoreContextConfiguration</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>salonbooks</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>salonbooks</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
--
流配置
@Configuration
public class FlowConfiguration extends AbstractFlowConfiguration{
@Autowired
WebMVCConfiguration webMVCConfiguration;
@Bean
public FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(flowRegistry())
.build();
}
@Bean
public FlowController flowController (){
FlowController flowController = new FlowController();
flowController.setFlowExecutor(flowExecutor());
flowController.setFlowHandlerAdapter(webMVCConfiguration.flowHandlerAdapter());
return flowController;
}
//updated flowRegistry to specify the specific flow files
@Bean
public FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder(flowBuilderServices())
//.setBasePath("/WEB-INF/flows")
//.addFlowLocationPattern("/**/*-flow.xml")
.addFlowLocation("/WEB-INF/flows/login-flow.xml","login")
.addFlowLocation("/WEB-INF/flows/home/home-flow.xml","home")
.addFlowLocation("/WEB-INF/flows/person/person-flow.xml","person")
.addFlowLocation("/WEB-INF/flows/appointment/appointment-flow.xml","appointment")
.addFlowLocation("/WEB-INF/flows/order/order-flow.xml","order")
.build();
}
@Bean
public FlowBuilderServices flowBuilderServices() {
return getFlowBuilderServicesBuilder()
.setViewFactoryCreator(mvcViewFactoryCreator())
.setValidator(validator())
.setDevelopmentMode(true)
.build();
}
@Bean
public MvcViewFactoryCreator mvcViewFactoryCreator() {
MvcViewFactoryCreator factoryCreator = new MvcViewFactoryCreator();
factoryCreator.setDefaultViewSuffix(".jsp");
factoryCreator.setViewResolvers(Arrays.<ViewResolver>asList(webMVCConfiguration.viewResolver()));
factoryCreator.setUseSpringBeanBinding(true);
return factoryCreator;
}
@Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
WebMVC配置
@Configuration
public class WebMVCConfiguration extends WebMvcConfigurerAdapter {
@Autowired
private FlowConfiguration webFlowConfig;
/* updated this by commenting out
@Bean
public ControllerClassNameHandlerMapping controllerClassNameHandlerMapping(){
ControllerClassNameHandlerMapping mapping = new ControllerClassNameHandlerMapping();
mapping.setPathPrefix("/flows");
return mapping;
}
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/", "classpath:/META-INF/web-resources/");
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// updated this method to do nothing
// registry.addViewController("/");
// registry.addViewController("/login");
// registry.addViewController("/home");
// registry.addViewController("/person");
}
@Bean
public FlowHandlerMapping flowHandlerMapping() {
FlowHandlerMapping handlerMapping = new FlowHandlerMapping();
handlerMapping.setOrder(-1);
handlerMapping.setFlowRegistry(webFlowConfig.flowRegistry());
return handlerMapping;
}
@Bean
public FlowHandlerAdapter flowHandlerAdapter() {
FlowHandlerAdapter handlerAdapter = new FlowHandlerAdapter();
handlerAdapter.setFlowExecutor(webFlowConfig.flowExecutor());
handlerAdapter.setSaveOutputToFlashScopeOnRedirect(true);
return handlerAdapter;
}
@Bean
public SalonFlowHandler SalonFlowHandler() {
return new SalonFlowHandler();
}
/*added urlMappings*/
@Bean
public SimpleUrlHandlerMapping urlMappings(){
SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping();
Properties urlProperties = new Properties();
urlProperties.put("/*", webFlowConfig.flowController());
urlProperties.put("/login", webFlowConfig.flowController());
urlProperties.put("/home", webFlowConfig.flowController());
urlProperties.put("/person", webFlowConfig.flowController());
urlProperties.put("/appointment", webFlowConfig.flowController());
urlProperties.put("/order", webFlowConfig.flowController());
simpleUrlHandlerMapping.setMappings(urlProperties);
simpleUrlHandlerMapping.setAlwaysUseFullPath(true);
return simpleUrlHandlerMapping;
}
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/flows/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<html>
<head>
<meta charset="utf-8">
<title>Welcome to SalonBooks</title>
</head>
<body>
<div>Welcome to SalonBooks!!</div>
<form:form id="login" model="loginActionFlows"
action="${flowExecutionUrl}" >
<input type="hidden" name ="_flowExecutionKey"
value="${flowExecutionKey}" />
User: <br/><form:input type="text" path="username" /><br/>
Passcode: <br/><form:input type="password" path="password"/><br/>
<input name="_eventId_doLogin" type="submit" value="Login"/> |
<input type="button" name="_eventId_cancel" value="Cancel" />
</form:form>
</body>
</html>
login-flow.xml 更新以指定视图和模型
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"
start-state="login">
<var name="loginActionFlows" class="org.tigersndragons.salonbooks.model.flows.LoginActionFlows"/>
<view-state id="login" view="login" model="loginActionFlows">
<transition on="doLogin" to="verifylogin" />
<transition on="cancel" to="done" />
</view-state>
<action-state id="verifylogin">
<evaluate result ="employee" expression="loginActionFlows.checkEmployee(requestParameters.username, requestParameters.password)"/>
<transition to ="home" />
</action-state>
<subflow-state id="home" subflow="home-flow">
<transition to="finish" />
</subflow-state>
<end-state id="finish"/>
</flow>
现在这只是生成 login.jsp 的干式 /text 再现,而不是呈现为 html。所以它似乎开始了流程,但缺少渲染。
【问题讨论】:
-
尝试删除
extends AbstractController -
问题:你是如何在流配置类中指定流处理适配器的?
-
添加了文件夹结构的屏幕截图
-
不,它似乎没有执行 web 流。我有一段时间可以让视图显示并看到它尝试登录,但随后收到 SpelEvaluationExceptions 它不理解或找不到处于操作状态的属性。在 web.xml 中将 servlet-mapping 设置为“/”与“/*”是查看 jsp 和查看原始 jsp 文本之间的区别。
标签: java spring spring-mvc spring-webflow