2014-05-09 120 views
1

我在過去曾與Spring合作過一個大項目,但我從未從頭開始創建Spring MVC Web應用程序。Spring - Thymeleaf - 404錯誤

那麼這就是我現在正在做的實踐,因爲我有一個項目即將到來,將需要它。

我成功地製作了一個簡單的使用.JSP頁面(使用註釋,無XML)的Spring MVC Web應用程序。 我想使用Thymeleaf,並開始了我的轉換過程。

那麼現在我得到一個404錯誤,我的HomeController類甚至沒有被擊中它似乎。

我在控制檯輸出中沒有得到任何錯誤。

我有谷歌搜索,通讀教程和代碼示例。第二雙眼睛會很好。謝謝! :)

注意:從.JSP到Thymeleaf所做的唯一更改是添加了ThymeleafConfig類。我不明白它是如何從工作中走向不工作的。

這裏是我的代碼:

WebInit.java

public class WebInit implements WebApplicationInitializer { 

@Override 
public void onStartup(ServletContext servletContext) 
     throws ServletException { 
    // Creates the root application context 
    AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext(); 
    appContext.register(ServletConfig.class); 
    appContext.setDisplayName("REPLACE ME"); 
    appContext.setConfigLocation("com.demo.config"); 

    // Creates the Spring Container shared by all Servlets and Filters 
    servletContext.addListener(new ContextLoaderListener(appContext)); 

    // Further configures the servlet context 
    ServletRegistration.Dynamic dispatcher = servletContext.addServlet(
      "dispatcher", new DispatcherServlet(appContext)); 
    dispatcher.setLoadOnStartup(1); 
    dispatcher.setAsyncSupported(true); 
    dispatcher.addMapping("/"); 
} 
} 

ServetConfig.java

@Configuration 
@Import(WebConfig.class) 
@ImportResource({ 
    //"classpath:META-INF/spring/persistence-context.xml", 
}) 
public class ServletConfig { 

} 

WebConfig.java

@Configuration 
@ComponentScan("com.illinois.dnr") 
@EnableAspectJAutoProxy 
@EnableWebMvc 
@Import({ThymeleafConfig.class}) 
public class WebConfig extends WebMvcConfigurerAdapter { 
    // Maps resources path to webapp/resources 
    @Override 
    public void addResourceHandlers(ResourceHandlerRegistry registry) { 
     registry.addResourceHandler("/resources/**").addResourceLocations(
       "/resources/"); 
    } 

    // Provides internationalization of messages 
    @Bean 
    public ResourceBundleMessageSource messageSource() { 
     ResourceBundleMessageSource source = new ResourceBundleMessageSource(); 
     source.setBasename("messages"); 
     return source; 
    } 
} 

Thymeleaf.java

@Configuration 
public class ThymeleafConfig { 
    @Bean 
    public ServletContextTemplateResolver templateResolver() { 
     ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(); 
     resolver.setPrefix("/WEB-INF/views/"); 
     resolver.setSuffix(".html"); 
     resolver.setTemplateMode("HTML5"); 
     resolver.setOrder(1); 
     return resolver; 
    } 

    @Bean 
    public SpringTemplateEngine templateEngine() { 
     SpringTemplateEngine engine = new SpringTemplateEngine(); 
     engine.setTemplateResolver(templateResolver()); 
     return engine; 
    } 

    @Bean 
    public ThymeleafViewResolver thymeleafViewResolver() { 
     ThymeleafViewResolver resolver = new ThymeleafViewResolver(); 
     resolver.setTemplateEngine(templateEngine()); 
     return resolver; 
    } 
} 

HomeController.java

@Controller 
public class HomeController { 

    private static final Logger logger = LoggerFactory.getLogger(HomeController.class); 

    /** 
    * Simply selects the home view to render by returning its name. 
    */ 
    @RequestMapping(value = "/dnr", method = RequestMethod.GET) 
    public String home(Locale locale, Model model) { 
     logger.info("Welcome home! The client locale is {}.", locale); 
     Date date = new Date(); 
     DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, 
       DateFormat.LONG, locale); 
     String formattedDate = dateFormat.format(date); 
     model.addAttribute("serverTime", formattedDate); 
     return "home"; 
    } 

    @RequestMapping(value = "/login", method = RequestMethod.GET) 
    public String loginPage(Locale locale, Model model) { 
     logger.info("Login"); 
     return "login"; 
    } 

    @RequestMapping(value = "/home", method = RequestMethod.POST) 
    public String login(@Validated User user, Model model) { 
     model.addAttribute("userName", user.getUserName()); 
     logger.info("User"); 
     return "user"; 
    } 

    @RequestMapping(value = { "/", "/welcome**" }, method = RequestMethod.GET) 
    public ModelAndView welcomePage() { 

     ModelAndView model = new ModelAndView(); 
     model.addObject("title", "Spring Security Hello World"); 
     model.addObject("message", "This is welcome page!"); 
     model.setViewName("hello"); 
     logger.info("Hello"); 
     return model; 
    } 

    @RequestMapping(value = "/admin**", method = RequestMethod.GET) 
    public ModelAndView adminPage() { 

     ModelAndView model = new ModelAndView(); 
     model.addObject("title", "Spring Security Hello World"); 
     model.addObject("message", "This is protected page - Admin Page!"); 
     model.setViewName("admin"); 
     logger.info("admin"); 
     return model; 
    } 

    @RequestMapping(value = "/dba**", method = RequestMethod.GET) 
    public ModelAndView dbaPage() { 

     ModelAndView model = new ModelAndView(); 
     model.addObject("title", "Spring Security Hello World"); 
     model.addObject("message", "This is protected page - Database Page!"); 
     model.setViewName("admin"); 
     logger.info("dba"); 
     return model; 
    } 
} 
+0

使用STS和tomcat7 – MSwezey

+0

有一個堆棧跟蹤可言?另外,你可以在'ThymeleafConfig'方法中放入'System.out.println()來確保它們正在運行。您是否在WEB-INF/views中使用了Thymeleaf模板? – CodeChimp

+0

請記住,你應該去localhost:8080/appName/dnr和頁面是WEB-INF/views/dnr.html –

回答

1

我不知道是否有幫助,但你可以簡化WebInit通過延長AbstractAnnotationConfigDispatcherServletInitializer而不是工具WebApplicationInitializer。否則,Thymeleaf配置對我來說似乎沒問題(假設它叫做)。我給這裏配置工作的骨架,所以你可以嘗試它。

WebApplicationInitializer

public class WebInitializer extends 
    AbstractAnnotationConfigDispatcherServletInitializer { 

    @Override 
    protected Class<?>[] getRootConfigClasses() { 
     return null; 
    } 

    @Override 
    protected Class<?>[] getServletConfigClasses() { 
     return new Class[] { WebConfig.class }; 
    } 

    @Override 
    protected String[] getServletMappings() { 
     return new String[] { "/" }; 
    } 

} 

WebConfig

@Configuration 
@EnableWebMvc 
@ComponentScan("com.kreuzman") 
public class WebConfig { 

    @Bean 
    public ITemplateResolver templateResolver() { 
     TemplateResolver resolver = new ServletContextTemplateResolver(); 
     resolver.setPrefix("/templates/"); 
    resolver.setSuffix(".html"); 
     resolver.setTemplateMode("HTML5"); 
     resolver.setCacheTTLMs(0l); 

     return resolver; 
    } 

    @Bean 
    public SpringTemplateEngine templateEngine() { 
     SpringTemplateEngine engine = new SpringTemplateEngine(); 
     engine.setTemplateResolver(templateResolver()); 

     return engine; 
    } 

    @Bean 
    public ViewResolver thymeleafViewResolver() { 
     ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); 
     viewResolver.setTemplateEngine(templateEngine()); 
     viewResolver.setCharacterEncoding("UTF-8"); 

     return viewResolver; 
    } 

} 
+0

謝謝!希望這可以幫助那些希望純粹基於Annotation的Spring Web App的人。我找到了幾個教程和幫助指南,但他們都有自己的設計風格。我終於找到了一個Spring MVC-Security-WebFlow,Hibernate和Thymeleaf項目的實例。有配置文件設置類似於您的骨架。絕對是這樣做的。更乾淨。謝謝 – MSwezey

1

你想打什麼網頁?該網頁是否存在於/ WEB-INF/views /?

它是一個JSP頁面嗎?您需要排除ThymeleafViewResolver無法解決的所有頁面。我也注意到你沒有將ThymeleafViewResolver設置爲第一個順序。

像這樣

@Bean 
public ThymeleafViewResolver thymeleafViewResolver() 
{ 
    String[] excludedViews = new String[]{ 
     "login", "logout"}; 

    ThymeleafViewResolver resolver = new ThymeleafViewResolver(); 
    resolver.setTemplateEngine(templateEngine()); 
    /* 
    * This is how we get around Thymeleaf view resolvers throwing an error instead of returning 
    * of null and allowing the next view resolver in the {@see 
    * DispatcherServlet#resolveViewName(String, Map<String, Object>, Locale, 
    * HttpServletRequest)} to resolve the view. 
    */ 
    resolver.setExcludedViewNames(excludedViews); 
    resolver.setOrder(1); 
    return resolver; 
} 
+0

我嘗試設置setOrder(1),它沒有工作。我最終刪除了該項目,並從頭開始。這次唯一的區別是我使用了這種依賴關係:javax 6.0 – MSwezey

+0

如果我想同時支持.JSP和.html頁面,你確實幫我排除了.JSP頁面。所以謝謝你 – MSwezey