HDIV + Spring 标签库(表单)= 错误,可能的错误?
Posted
技术标签:
【中文标题】HDIV + Spring 标签库(表单)= 错误,可能的错误?【英文标题】:HDIV + Spring tag library (form) = Error, possible bug? 【发布时间】:2015-04-15 10:43:12 【问题描述】:我在使用带有标签 Spring 元素的 HDIV 时遇到了麻烦:“”。
首先,我将解释我的应用程序的架构: 我正在使用 Spring 框架 4.1.6、Spring Security 4.0.0 和 HDIV 2.1.10。
到目前为止,我在开发过程中没有出现错误,但现在我在一个 jsp 文件中找到了一个,当我使用 Spring 的 form 标记时:
<form:form
action="$pageContext.servletContext.contextPath/newUser"
method="POST" class="form-horizontal" commandName="user">
我在第 34 行得到了这个错误:“
当我详细检查来自 HDIV 的代码时:
HdivRequestDataValueProcessor.class
public class HdivRequestDataValueProcessor implements RequestDataValueProcessor
protected LinkUrlProcessor linkUrlProcessor;
protected FormUrlProcessor formUrlProcessor;
if (this.innerRequestDataValueProcessor != null)
String processedAction = this.innerRequestDataValueProcessor.processAction(request, action, method);
if (processedAction != action)
action = processedAction;
String result = this.formUrlProcessor.processUrl(request, action, method);//line 122
return result;
我想知道可能是因为 'form:form' 的结构与 'form' 不同,HDIV 无法找到一些参数,例如 'action'、'method'...但我不确定。
我还附上了我的配置文件以提供更多有用的信息(基于 Java 的配置):
WebApplicationInit.class
import javax.servlet.Filter;
import javax.servlet.ServletContext;
import org.hdiv.filter.ValidatorFilter;
import org.hdiv.listener.InitListener;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebApplicationInit extends
AbstractAnnotationConfigDispatcherServletInitializer
// http://www.robinhowlett.com/blog/2013/02/13/spring-app-migration-from-xml-to-java-based-config/
@Override
protected Class<?>[] getRootConfigClasses()
return new Class[] RootConfig.class, DatabaseConfig.class,
SecurityConfig.class, HdivSecurityConfig.class ;
// , HdivSecurityConfig.class
@Override
protected Class<?>[] getServletConfigClasses()
return new Class[] MvcConfig.class ;
@Override
protected String[] getServletMappings()
return new String[] "/" ;
//web.xml filter
@Override
protected Filter[] getServletFilters()
return new Filter[] new ValidatorFilter();
// web.xml listener
@Override
protected void registerDispatcherServlet(ServletContext servletContext)
super.registerDispatcherServlet(servletContext);
servletContext.addListener(InitListener.class);
HdivSecurityConfig.class
@Configuration
@EnableHdivWebSecurity
public class HdivSecurityConfig extends HdivWebSecurityConfigurerAdapter
@Override
public void addExclusions(ExclusionRegistry registry)
registry.addUrlExclusions("/login").method("GET");
registry.addUrlExclusions("/newUser").method("GET");
registry.addUrlExclusions("/newUser").method("POST");
registry.addUrlExclusions("/about").method("GET");
registry.addUrlExclusions("/resources/.*").method("GET");
registry.addUrlExclusions("/bst-lib/.*").method("GET");
registry.addUrlExclusions("/images/.*").method("GET");
@Override
public void configure(SecurityConfigBuilder builder)
//the session has expired, go to login again
builder.sessionExpired().homePage("/").loginPage("/login");
//Execution strategy
builder.strategy(Strategy.CIPHER);
//error page
builder.errorPage("/error");
SecurityConfig.class
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
private DriverManagerDataSource myWebAppDataSource;
@Autowired
private MyWebAppSimpleAuthenticationProvider myWebAppAuthenticationProvider;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception
auth.authenticationProvider(myWebAppAuthenticationProvider);
@Override
protected void configure(HttpSecurity http) throws Exception
http.authorizeRequests()
.antMatchers("/resources/**", "/bst-lib/**", "/images/**",
"/about", "/newUser").permitAll().anyRequest()
.authenticated().and().formLogin().loginPage("/login")
.permitAll();
SecurityWebApplicationInit.class
public class SecurityWebApplicationInit extends
AbstractSecurityWebApplicationInitializer
提前谢谢你!!
最好的问候,
阿尔伯托
----编辑---
按照给定的示例,现在这是我的代码:
WebApplicationInit.class
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebApplicationInit extends
AbstractAnnotationConfigDispatcherServletInitializer
// http://www.robinhowlett.com/blog/2013/02/13/spring-app-migration-from-xml-to-java-based-config/
@Override
protected Class<?>[] getRootConfigClasses()
return new Class[] RootConfig.class, DatabaseConfig.class,
SecurityConfig.class, HdivSecurityConfig.class ;
@Override
protected Class<?>[] getServletConfigClasses()
return new Class[] MvcConfig.class ;
@Override
protected String[] getServletMappings()
return new String[] "/" ;
@Override
protected String getServletName()
return "myDispatcher";
HDIVSecurityConfig.class
import org.hdiv.config.Strategy;
import org.hdiv.config.annotation.EnableHdivWebSecurity;
import org.hdiv.config.annotation.ExclusionRegistry;
import org.hdiv.config.annotation.RuleRegistry;
import org.hdiv.config.annotation.ValidationConfigurer;
import org.hdiv.config.annotation.builders.SecurityConfigBuilder;
import org.hdiv.config.annotation.configuration.HdivWebSecurityConfigurerAdapter;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableHdivWebSecurity
public class HdivSecurityConfig extends HdivWebSecurityConfigurerAdapter
@Override
public void addExclusions(ExclusionRegistry registry)
registry.addUrlExclusions("/login").method("GET");
registry.addUrlExclusions("/newUser").method("GET");
registry.addUrlExclusions("/newUser").method("POST");
registry.addUrlExclusions("/about").method("GET");
registry.addUrlExclusions("/resources/.*").method("GET");
registry.addUrlExclusions("/bst-lib/.*").method("GET");
registry.addUrlExclusions("/images/.*").method("GET");
registry.addParamExclusions("_csrf");
@Override
public void configure(SecurityConfigBuilder builder)
// the session has expired, go to login again
builder.sessionExpired().homePage("/").loginPage("/login");
// Execution strategy
builder.strategy(Strategy.MEMORY);
builder.maxPagesPerSession(5);
// error page
builder.errorPage("/error");
@Override
public void addRules(RuleRegistry registry)
//registry.addRule("safeText").acceptedPattern("^[a-zA-Z0-9@.\\-_]*$");
@Override
public void configureEditableValidation(
ValidationConfigurer validationConfigurer)
validationConfigurer.addValidation("/.*");
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>myWebApp</display-name>
<listener>
<listener-class>org.hdiv.listener.InitListener</listener-class>
</listener>
<!-- HDIV Validator Filter -->
<filter>
<filter-name>ValidatorFilter</filter-name>
<filter-class>org.hdiv.filter.ValidatorFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ValidatorFilter</filter-name>
<servlet-name>myDispatcher</servlet-name>
</filter-mapping>
<jsp-config>
<taglib>
<taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/tlds/hdiv-c.tld</taglib-location>
</taglib>
</jsp-config>
</web-app>
newUser.jsp
<form:form
action="$pageContext.servletContext.contextPath/newUser"
method="POST" class="form-horizontal" commandName="user">
<div class="form-group">
<label for="inputName"
class="col-sm-offset-2 col-sm-2 control-label">Name:</label>
<div class="col-sm-6">
<form:input class="form-control" id="inputName"
placeholder="Name" path="name" />
</div>
</div>
<div class="form-group">
<label for="inputSurname"
class="col-sm-offset-2 col-sm-2 control-label">Surname:</label>
<div class="col-sm-6">
<form:input class="form-control" id="inputSurname"
placeholder="Surname" path="surname" />
</div>
</div>
<div class="form-group">
<label for="inputOrganisation"
class="col-sm-offset-2 col-sm-2 control-label">Organization:</label>
<div class="col-sm-6">
<form:input class="form-control" id="inputOrganisation"
placeholder="Organization" path="organization" />
</div>
</div>
<div class="form-group">
<label for="inputEmail"
class="col-sm-offset-2 col-sm-2 control-label">Email:</label>
<div class="col-sm-6">
<form:input type="email" class="form-control" id="inputEmail"
placeholder="Email" path="email" />
</div>
</div>
<div class="form-group">
<label for="inputPassword"
class="col-sm-offset-2 col-sm-2 control-label">Password:</label>
<div class="col-sm-6">
<form:password class="form-control" id="inputPassword"
placeholder="Password" path="password" />
</div>
</div>
<div class="form-group">
<label for="inputRPassword"
class="col-sm-offset-2 col-sm-2 control-label">Repeat
Password:</label>
<div class="col-sm-6">
<form:password class="form-control" id="inputRPassword"
placeholder="Repeat Password" path="rPassword" />
</div>
</div>
<div class="col-sm-offset-4 col-sm-8">
<button type="submit" class="btn btn-default login-button">Sing
in</button>
<button type="button" class="btn btn-default login-button"
onclick="clearAll()">Clear All</button>
<button type="button" class="btn btn-default login-button"
onclick="comeBack()">Come Back</button>
</div>
<input type="hidden" name="$_csrf.parameterName"
value="$_csrf.token" />
</form:form>
MvcConfig.class
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.ec.myWebApp" )
public class MvcConfig extends WebMvcConfigurerAdapter
@Autowired
/*
* If I use this commented line, The application fails due to the fact that the bean "hdivEditableValidator" can't be found...If I don't use the tag "Qualifier" it does not fail
*/
// @Qualifier("hdivEditableValidator")
private Validator hdivEditableValidator;
// View Name -> View
@Bean
public InternalResourceViewResolver getViewResolver()
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
// static resources
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
registry.addResourceHandler("/resources/**").addResourceLocations(
"/public-resources/");
registry.addResourceHandler("/bst-lib/**").addResourceLocations(
"/public-resources/lib/bootstrap-3.3.2-dist/");
registry.addResourceHandler("/images/**").addResourceLocations(
"/public-resources/images/");
@Bean
public MultipartResolver multipartResolver()
HdivCommonsMultipartResolver resolver = new HdivCommonsMultipartResolver();
resolver.setMaxUploadSize(100000);
return resolver;
@Override
public Validator getValidator()
return hdivEditableValidator;
我更改了将 HDIV 添加到我的 Web 应用程序的方式,将其添加到 xml 文件中,而不是在使用基于 java 的配置中这样做。另外,我使用示例添加了限定符标记(MvcConfig.class),但是当我使用它时它不起作用......(它找不到bean......)。 null 错误并没有消失...
【问题讨论】:
如果您使用form
而不是form:form
hdiv 没有被使用,因此没有错误。尝试找出导致NullPointerException
的原因,需要的可能是null
。
调试代码的时候发现问题出在下面,在类HdivRequestDataValueProcessor中。 linkUrlProcessor 和 formUrlProcessor 为空
我无法想象空值的原因是什么。这是一个使用 JavaConfig 和 HDIV 2.1.10 的 Spring mvc 应用程序。 github.com/hdiv/hdiv-spring-mvc-showcase/tree/javaconfig也许能帮上忙!
【参考方案1】:
更改此行已解决问题:
@ComponentScan(basePackages = "com.ec.myWebApp" )
在课堂上:MvcConfing,为此:
@ComponentScan(basePackages = "com.ec.myWebApp.controllers",
"com.ec.myWebApp.dao", "com.ec.myWebApp.services" )
我的原始行扫描了 HDIV 配置类两次,第一次是在上下文创建期间,第二次是“@ComponentScan”。这导致了不正确的初始化。因此,config 包被使用了两次,而不是一次。
谢谢。
【讨论】:
以上是关于HDIV + Spring 标签库(表单)= 错误,可能的错误?的主要内容,如果未能解决你的问题,请参考以下文章
@ModelAttribute注解与spring的表单标签库form