简体   繁体   English

Spring REST应用程序配置和启动

[英]Spring REST application configuration and startup

I have this application that used to work just fine. 我有这个应用程序曾经工作得很好。

I'm trying to run it after a long while and it doesn't behave as expected. 我试图在很长一段时间后运行它并且它没有按预期运行。

Sorry for the not so precise error issue. 很抱歉没有那么精确的错误问题。

It's a Spring REST application which is exposing controllers, and it's NOT a Spring MVC application. 它是一个暴露控制器的Spring REST应用程序,它不是Spring MVC应用程序。

The first thing that puzzles me is that starting it in the debugger will not have it stop at all the breakpoints placed in the methods of the WebConfiguration class: 令我困惑的第一件事是,在调试器中启动它不会停止在WebConfiguration类的方法中放置的所有断点:

package com.nsn.nitro.project.rest.config;

@Configuration
@EnableWebMvc
@EnableSpringDataWebSupport
@ComponentScan(nameGenerator = PackageBeanNameGenerator.class, basePackages = { "com.nsn.nitro.project.rest" })
public class WebConfiguration extends WebMvcConfigurerAdapter {

    private static final int PAGE_DEFAULT_SIZE = 20;

    @Override
    public void addArgumentResolvers(
            List<HandlerMethodArgumentResolver> argumentResolvers) {
        PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver();
        resolver.setFallbackPageable(new PageRequest(0, PAGE_DEFAULT_SIZE));
        resolver.setMaxPageSize(50);
        resolver.setOneIndexedParameters(true);
        resolver.setPageParameterName("page");
        resolver.setSizeParameterName("size");
        argumentResolvers.add(resolver);
        super.addArgumentResolvers(argumentResolvers);
    }

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasenames("classpath:messages/messages",
                "classpath:messages/validation");
        // If true, the key of the message will be displayed if the key is not
        // found, instead of throwing an exception
        messageSource.setUseCodeAsDefaultMessage(true);
        messageSource.setDefaultEncoding("UTF-8");
        // The value 0 means always reload the messages to be developer friendly
        messageSource.setCacheSeconds(0);
        return messageSource;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/*").addResourceLocations("/");
    }

    @Override
    public void configureDefaultServletHandling(
            DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public LocaleResolver localeResolver() {
        return new SmartLocaleResolver();
    }

    @Bean
    public MultipartResolver multipartResolver() {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        multipartResolver.setMaxUploadSize(1024000);
        return multipartResolver;
    }

    // The locale interceptor provides a way to switch the language in any page
    // just by passing the lang=’en’, lang=’fr’, and so on to the url
    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
        localeChangeInterceptor.setParamName("lang");
        return localeChangeInterceptor;
    }

    // Avoid caching issue with AngularJS on IE
    @Bean
    public WebContentInterceptor webContentInterceptor() {
        WebContentInterceptor interceptor = new WebContentInterceptor();
        interceptor.setCacheSeconds(0);
        interceptor.setUseExpiresHeader(true);
        interceptor.setUseCacheControlHeader(true);
        interceptor.setUseCacheControlNoStore(true);
        return interceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeChangeInterceptor());
        registry.addInterceptor(webContentInterceptor());
    }

And the application configuration: 和应用程序配置:

package com.nsn.nitro.project.rest.config;    

@Configuration
@ComponentScan(nameGenerator = PackageBeanNameGenerator.class, basePackages = {
        "com.nsn.nitro.project.data.config",
        "com.nsn.nitro.project.rest.config",
        "com.nsn.nitro.project.rest.service" })
public class ApplicationConfiguration {

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

    public ApplicationConfiguration() {
        logger.debug("===========>> Loading the NITRO application configuration");
    }

}

The debugger does not stop at the breakpoint sitting in the ApplicationConfiguration() constructor either. 调试器不会停留在ApplicationConfiguration()构造函数中的断点处。 And I can't see the logger output in the console log. 我无法在控制台日志中看到记录器输出。

The application seems to start up fine though: 该应用程序似乎启动良好,但:

INFO] <<< tomcat7-maven-plugin:2.2:run (default-cli) < process-classes @ nitro-project-rest <<<
[INFO] 
[INFO] --- tomcat7-maven-plugin:2.2:run (default-cli) @ nitro-project-rest ---
[INFO] Running war on http://localhost:8080/nitro-project-rest
[INFO] Creating Tomcat server configuration at /home/stephane/dev/java/projects/nitro-project-rest/target/tomcat
[INFO] create webapp with contextPath: /nitro-project-rest
Dec 31, 2016 9:41:14 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-bio-8080"]
Dec 31, 2016 9:41:14 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-bio-8443"]
Dec 31, 2016 9:41:16 AM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Tomcat
Dec 31, 2016 9:41:16 AM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.47
Dec 31, 2016 9:41:25 AM org.apache.catalina.core.ApplicationContext log
INFO: 1 Spring WebApplicationInitializers detected on classpath
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/stephane/.m2/repository/org/slf4j/slf4j-log4j12/1.6.4/slf4j-log4j12-1.6.4.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/stephane/.m2/repository/ch/qos/logback/logback-classic/1.1.7/logback-classic-1.1.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
Dec 31, 2016 9:41:26 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
Dec 31, 2016 9:41:26 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8443"]

I start the application with a Maven command: 我用Maven命令启动应用程序:

mvn clean install tomcat7:run

But sending any request, like curl -H "Accept:application/json" --user nsn@nsn.com:******* http://localhost:8080/nitro-project-rest/greeting?message=Steph always gives me the following error: 但发送任何请求,如curl -H "Accept:application/json" --user nsn@nsn.com:******* http://localhost:8080/nitro-project-rest/greeting?message=Steph总是给我以下错误:

SEVERE: Servlet.service() for servlet [default] in context with path [/nitro-project-rest] threw exception
java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener or DispatcherServlet registered?

Here is my Greeting controller: 这是我的问候控制器:

@Controller
@RequestMapping(RESTConstants.SLASH + RESTConstants.GREETING + RESTConstants.SLASH)
public class GreetingController {

    private static final String TEMPLATE = "Hello, %s!";

    @RequestMapping(value = RESTConstants.SLASH + RESTConstants.HELLO, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public HttpEntity<Greeting> hello(@RequestParam(value = "message", required = false, defaultValue = "World") String message, UriComponentsBuilder builder) {
        Greeting greeting = new Greeting(String.format(TEMPLATE, message));
        greeting.add(linkTo(methodOn(GreetingController.class).hello(message, builder)).withSelfRel());
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.setLocation(builder.path(RESTConstants.SLASH + RESTConstants.GREETING + RESTConstants.SLASH + "hello").buildAndExpand().toUri());
        responseHeaders.add("Content-Type", "application/json; charset=utf-8");
        ResponseEntity<Greeting> responseEntity = new ResponseEntity<Greeting>(greeting, responseHeaders, HttpStatus.OK);        
        return responseEntity;
    }

}

I was missing the dispatcher servlet ! 我错过了调度程序servlet!

Now with this file it works much better: 现在使用此文件可以更好地工作:

public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {

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

    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration) {
        registration.setInitParameter("dispatchOptionsRequest", "true");
        registration.setAsyncSupported(true);
        registration.setLoadOnStartup(1);
    }

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

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

    @Override
    protected String[] getServletMappings() {
        // The '/api/*' prefix is to allow a match of an .../api/... request to a controller mapping
        // The '/' is to allow a match of a root request to a static resource
        return new String[] { "/api/*", "/" };
    }

    @Override
    protected String getServletName() {
        return CommonConstants.SERVLET_NAME;
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM