Я новичок в среде Spring, пробую конфигурацию Spring MVC без xml (без web.xml или mvc-dispatcher-servlet.xml), поскольку это то, что требуется для проекта.
Я получаю следующую ошибку, когда пытаюсь запустить ее (используя Jetty Local, опять же требование проекта)
Ниже приведена моя конфигурация для замены web.xml:
(Также безуспешно пытался расширить AbstractAnnotationConfigDispatcherServletInitializer
)
public class WebConfig implements WebApplicationInitializer {
@Override
public void onStartup( ServletContext servletContext ) throws ServletException {
WebApplicationContext rootContext = getContext(servletContext);
servletContext.addListener(new ContextLoaderListener(rootContext));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("mvc", new DispatcherServlet(rootContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
private AnnotationConfigWebApplicationContext getContext(ServletContext ctx) {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
//Tried various combination of un/commenting following options.
context.register( MvcServletConfig.class );
//context.setConfigLocation("com.xyz.myapp.configuration");
context.setServletContext( ctx );
//context.refresh();
//context.scan( "com.xyz.someapp.*" );
return context;
}
}
Это моя конфигурация MVC/Servlet, заменяющая mvc-dispatcher-servlet.xml:
@EnableWebMvc
@Configuration
@ComponentScan(basePackages = {"com.xyz.myapp"})
public class MvcServletConfig extends WebMvcConfigurerAdapter {
public MvcServletConfig() { super(); }
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("forward:/login.jsp");
}
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setViewClass(JstlView.class);
bean.setPrefix("/WEB-INF/pages/");
bean.setSuffix(".jsp");
return bean;
}
}
Это мой AppConfig:
@Configuration
@ComponentScan(basePackages = {"com.xyz.myapp.*"})
@Import( { HibernateConfig.class } )
public class AppConfig {}
Это мой HibernateConfig, где у меня есть статический метод, который обращается к контексту:
@Configuration
@EnableTransactionManagement
@ComponentScan( {"com.obsm.visensia.configuration"} )
@PropertySources( value ={@PropertySource("classpath:/application.properties")} )
public class HibernateConfig {
@Transactional
public static void InitialiseDummyData()
{
AbstractApplicationContext context = new AnnotationConfigApplicationContext( AppConfig.class);
AccountService accountService = (AccountService) context.getBean("accountService");
if ( accountService != null )
{
Role admin = new AdminRole();
Role serverAdmin = new ServerAdminRole();
Role normal = new NormalRole();
User adminUser = new User();
adminUser.setFirstName( "Kunal" );
adminUser.setLastName( "Patel" );
adminUser.setSex( Sex.Male );
adminUser.setUsername( "kp" );
adminUser.setPassword( "kp" );
adminUser.addRole( admin );
accountService.addUser( adminUser );
User serverAdminUser = new User();
serverAdminUser.setFirstName( "Server" );
serverAdminUser.setLastName( "Admin" );
serverAdminUser.setSex( Sex.Male );
serverAdminUser.setUsername( "serveradmin" );
serverAdminUser.setPassword( "serveradmin" );
serverAdminUser.addRole( serverAdmin );
accountService.addUser( serverAdminUser );
User normalUser = new User();
normalUser.setFirstName( "Normal" );
normalUser.setLastName( "User" );
normalUser.setSex( Sex.Undefined );
normalUser.setUsername( "normal" );
normalUser.setPassword( "normal" );
normalUser.addRole( normal );
accountService.addUser( normalUser );
context.close();
}
}
@Autowired
private Environment environment;
@Bean
public LocalSessionFactoryBean sessionFactory()
{
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource( dataSource() );
sessionFactory.setPackagesToScan( new String[] { "com.obsm.visensia.model" } );
sessionFactory.setHibernateProperties( hibernateProperties() );
return sessionFactory;
}
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName( environment.getRequiredProperty( "jdbc.driverClassName" ) );
dataSource.setUrl( environment.getRequiredProperty( "jdbc.url" ) );
dataSource.setUsername( environment.getRequiredProperty( "jdbc.username" ) );
dataSource.setPassword( environment.getRequiredProperty( "jdbc.password" ) );
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put( "hibernate.dialect", environment.getRequiredProperty( "hibernate.dialect" ) );
properties.put( "hibernate.show_sql", environment.getRequiredProperty( "hibernate.show_sql" ) );
properties.put( "hibernate.hbm2ddl.auto", environment.getRequiredProperty( "hibernate.hbm2ddl.auto" ) );
properties.put( "hibernate.format_sql", environment.getRequiredProperty( "hibernate.format_sql" ) );
return properties;
}
@Bean
@Autowired
public HibernateTransactionManager transactionManager ( SessionFactory sessFact )
{
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory( sessFact );
return transactionManager;
}
}
Мой ЛогинКонтроллер:
@Controller
@RequestMapping("/")
public class LoginController {
@Autowired
private AccountService accountService;
@RequestMapping(method = RequestMethod.GET)
public String login(ModelMap model) {
HibernateConfig.InitialiseDummyData();
model.addAttribute( "user", new User() );
return "login";
}
@RequestMapping(method = RequestMethod.POST)
public String verifyUser(@ModelAttribute("user") User user, Model model)
{
if ( accountService.verifyUser( user.getUsername(), user.getPassword() ) ) {
User usr = accountService.findUserByUsername( user.getUsername() );
model.addAttribute( "message", "Welcome, " + usr.getFirstName() );
return "hello";
}
else
return "login";
}
}
Мой HelloController:
@Controller
@RequestMapping("/")//Doesn't work even if I change it to '/hello'
public class HelloController {
@RequestMapping(method = RequestMethod.GET)
public String printWelcome(ModelMap model) {
model.addAttribute("message", "Hello world!");
return "hello";
}
}
Помогите пожалуйста, я застрял здесь уже 3 дня :'(
ОБНОВЛЕНИЕ
Jetty 9.2.4v20141103, а это трассировка стека:
Jetty 9.2.4v20141103 and following is the stacktrace:
`java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
at org.springframework.util.Assert.notNull(Assert.java:112)
at org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer.<init>(DefaultServletHandlerConfigurer.java:54)
at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.defaultServletHandlerMapping(WebMvcConfigurationSupport.java:416)
at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$b833a897.CGLIB$defaultServletHandlerMapping$30(<generated>)
at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$b833a897$$FastClassBySpringCGLIB$$56ff08f3.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312)
at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$b833a897.defaultServletHandlerMapping(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:590)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1113)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1008)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:505)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:725)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
at com.obsm.visensia.configuration.HibernateConfig.InitialiseDummyData(HibernateConfig.java:32)
at com.obsm.visensia.controller.LoginController.login(LoginController.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:800)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:587)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1125)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1059)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:110)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:497)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:248)
at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:620)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:540)
at java.lang.Thread.run(Thread.java:722)`
Добавлен класс для инициализации моего db сразу после обновления моего контекста, например:
@Component
public class DbInitialiserOnStartUp implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private AccountService accountService;
@Transactional
@Override
public void onApplicationEvent( ContextRefreshedEvent contextRefreshedEvent ) {
if ( accountService != null )
{
//inserts etc...
}
}
}
InitialiseDummyData()
инициализирует некоторые данные для меня в базе данных, поскольку я пытаюсь проверить материал входа в систему, и для этого он обращается кApplicationContext
. Не могли бы вы подсказать, как правильно получить доступ кcontext
, чтобы он не рвало, как сейчас? Спасибо за помощь, очень признателен. :-) 02.05.2015InitialiseDummyData
в компонент Spring, пометьте его, например, как@Component
, и внедрите службу или DAO, необходимые для доступа и хранения/извлечения данных. 03.05.2015ContextRefreshedEvent
. Это правильный способ сделать это? Попробовал то, что вы сказали, используя Bean, но не совсем понял. Однако было бы интересно узнать, как это было бы сделано так, как сказано выше. Я отмечаю ваше обновление как ответ, жаль, что я не могу сделать больше. :-) 05.05.2015