This application has no explicit mapping for /error

匿名 (未验证) 提交于 2018-03-17 14:53:49

问题:

I used maven to do the tutorial https://spring.io/guides/gs/uploading-files/
All the codes I used was copied.

The Application can run, but I get the error:

Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. Tue Jun 30 17:24:02 CST 2015 There was an unexpected error (type=Not Found, status=404). No message available

How can I fix it?

回答1:

Make sure that your main class is in a root package above other classes.

When you run a Spring Boot Application, (i.e. a class annotated with @SpringBootApplication), Spring will only scan the classes below your main class package.

com
   +- APP
         +- Application.java  <--- your main class should be here, above your controller classes
         |
         +- model
         |   +- user.java
         +- controller
             +- UserController.java


回答2:

You can solve this by adding an ErrorController in your application. You can have the error controller return a view that you need.

Error Controller in my application looks like below:

import org.springframework.boot.autoconfigure.web.ErrorAttributes;
import org.springframework.boot.autoconfigure.web.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * Basic Controller which is called for unhandled errors
 */
@Controller
public class AppErrorController implements ErrorController{

    /**
     * Error Attributes in the Application
     */
    private ErrorAttributes errorAttributes;

    private final static String ERROR_PATH = "/error";

    /**
     * Controller for the Error Controller
     * @param errorAttributes
     */
    public AppErrorController(ErrorAttributes errorAttributes) {
        this.errorAttributes = errorAttributes;
    }

    /**
     * Supports the HTML Error View
     * @param request
     * @return
     */
    @RequestMapping(value = ERROR_PATH, produces = "text/html")
    public ModelAndView errorHtml(HttpServletRequest request) {
        return new ModelAndView("/errors/error", getErrorAttributes(request, false));
    }

    /**
     * Supports other formats like JSON, XML
     * @param request
     * @return
     */
    @RequestMapping(value = ERROR_PATH)
    @ResponseBody
    public ResponseEntity> error(HttpServletRequest request) {
        Map body = getErrorAttributes(request, getTraceParameter(request));
        HttpStatus status = getStatus(request);
        return new ResponseEntity>(body, status);
    }

    /**
     * Returns the path of the error page.
     *
     * @return the error path
     */
    @Override
    public String getErrorPath() {
        return ERROR_PATH;
    }


    private boolean getTraceParameter(HttpServletRequest request) {
        String parameter = request.getParameter("trace");
        if (parameter == null) {
            return false;
        }
        return !"false".equals(parameter.toLowerCase());
    }

    private Map getErrorAttributes(HttpServletRequest request,
                                                   boolean includeStackTrace) {
        RequestAttributes requestAttributes = new ServletRequestAttributes(request);
        return this.errorAttributes.getErrorAttributes(requestAttributes,
                includeStackTrace);
    }

    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request
                .getAttribute("javax.servlet.error.status_code");
        if (statusCode != null) {
            try {
                return HttpStatus.valueOf(statusCode);
            }
            catch (Exception ex) {
            }
        }
        return HttpStatus.INTERNAL_SERVER_ERROR;
    }
}

The above class is based on Springs BasicErrorController class.

You can instantiate the above ErrorController like this in a @Configuration file:

 @Autowired
 private ErrorAttributes errorAttributes;

 @Bean
 public AppErrorController appErrorController(){return new AppErrorController(errorAttributes);}

You can choose override the default ErrorAttributes by implementing ErrorAttributes. But in most cases the DefaultErrorAttributes should suffice.



回答3:

When we create a Spring boot application we annotate it with @SpringBootApplication annotation. This annotation 'wraps up' many other necessary annotations for the application to work. One such annotation is @ComponentScan annotation. This annotation tells spring to look for Spring components and configure the application to run.

Your application class needs to be top of your package hierarchy, so that Spring can scan sub-packages and find out the other required components.

package com.test.spring.boot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

This works as the controller package is under com.test.spring.boot package

package com.test.spring.boot.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HomeController {

    @RequestMapping("/")
    public String home(){
        return "Hello World!";
    }
}

This does NOT Work as the controller package is NOT under com.test.spring.boot package

package com.test.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HomeController {

     @RequestMapping("/")
     public String home(){
         return "Hello World!";
     }
 }

From Spring Boot documentation:

Many Spring Boot developers always have their main class annotated with @Configuration, @EnableAutoConfiguration and @ComponentScan. Since these annotations are so frequently used together (especially if you follow the best practices above), Spring Boot provides a convenient @SpringBootApplication alternative.

The @SpringBootApplication annotation is equivalent to using @Configuration, @EnableAutoConfiguration and @ComponentScan with their default attributes



回答4:

in my case it because of package position , meaning package of controller must be above main class package

if my main class package is package co.companyname.spring.tutorial; any controller package should package co.companyname.spring.tutorial.WHAT_EVER_HERE;

package co.companyname.spring.tutorial; // package for main class
@SpringBootApplication
public class FirstProjectApplication {

    public static void main(String[] args) {
        SpringApplication.run(FirstProjectApplication.class, args);
    }
}


package co.companyname.spring.tutorial.controllers; // package for controllers 

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController 
public class HelloController { 

@RequestMapping("/hello")  
public String hello() {   
 return "Hello, world"; 
 }}

after finish coding press boot dashboard

enter image description here

one last thing to make sure your controller is mapping or not just console you should see somehting smilliar

Mapped "{[/hello]}" onto public java.lang.String co.companyname.spring.tutorial.controllers.HelloController.hello()

happy coding



回答5:

Try adding the dependency.


    org.springframework.boot
    spring-boot-starter-thymeleaf



回答6:

In my case the controller class was annotated with @Controller. Changing that to @RestController resolved the problem. Basically @RestController is @Controller + @ResponseBody So either use @RestController , or @Controller with @ResponseBody annotation with each method.

Some useful notes here : https://www.genuitec.com/spring-frameworkrestcontroller-vs-controller/



回答7:

The problem is that you are navigating to localhost:8080/ instead of localhost:8080/upload as prescribed in the guide. Spring Boot has a default error page used when you navigate to an undefined route to avoid giving away server specific details (which can be viewed as a security risk).

You're options are to either: visit the right page, add your own landing page, or override the white error page.

To simplify this particular situation, I updated the guide so that it uses / instead of /upload.



回答8:

I added this dependency and it solved my problem.


    org.springframework.boot

    spring-boot-starter-thymeleaf



回答9:

You might be getting the error i.e.

"This application has no explicit mapping for /error, so you are seeing this as a fallback."

This is because it is not scanning your Controller & Service classes which you have to specify in your main() class like this,

package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableAutoConfiguration
**@ComponentScan({"com.example.demo", "controller", "service"})**
public class SpringBootMvcExample1Application {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootMvcExample1Application.class, args);
    }
}

Note: Here, I have specified various classes like demo, controller and service to be scanned then only it will work properly.



回答10:

In the main class, after the configuration "@SpringBootApplication", adding "@ComponentScan" without having any arguments, worked for me !!!

Main Class :

@SpringBootApplication
@ComponentScan
public class CommentStoreApplication {

    public static void main(String[] args) {
        SpringApplication.run(CommentStoreApplication.class, args);

    }
}

RestController Class :

@RestController
public class CommentStoreApp {

    @RequestMapping("/") 
    public String hello() {
        return "Hello World!";
    }
}

P.S: Don't miss to run mvn clean and mvn install commands, before launching the application



回答11:

All I have done to solve this kind of problem is to mention anotation @Configuration in MVCConfig Class.

Like this one :

package com.example;

/**
 * Created by sartika.s.hasibuan on 1/10/2017.
 */
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@EnableAutoConfiguration
@Configuration
@ComponentScan
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/home").setViewName("home");
        registry.addViewController("/").setViewName("home");
        registry.addViewController("/hello").setViewName("hello");
        registry.addViewController("/login").setViewName("login");
    }

}


回答12:

I had a similar mistake, I use the spring boot and velocity, my solution is to check the file application.properties, spring.velocity.toolbox-config-location found that this property is wrong



回答13:

In my case, this problem occurs when running the SpringApplication from within IntelliJ after running it first with maven.

To solve the problem, I run first mvn clean. Then I run SpringApplication from within IntelliJ.



回答14:

Change @Controller to @RestController in your controller class and everything should go smoothly.



回答15:

I too got the same error and was able to resolve the error by adding the below dependency to my pom.xml.


    org.apache.tomcat.embed
    tomcat-embed-jasper
    provided

Reason is we are using JSP as the view. Default embedded servlet container for Spring Boot Starter Web is tomcat. To enable support for JSP’s, we would need to add a dependency on tomcat-embed-jasper.

In my case I was returning a JSP as view from controller. Hope this answer helps someone who are struggling with same issue.



回答16:

I am developing Spring Boot application for a few weeks.. And i was gettig same error like below;

Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. Thu Jan 18 14:12:11 AST 2018 There was an unexpected error (type=Not Found, status=404). No message available

When i get this error massage i realized my controller or rest controller class is note defined in my project. I mean our all controller packages aren't same package with main class which include @SpringBootApplication annotation.. I mean you need to add you controller package's name to @ComponentScan annotation to your main class which is inludes @SpringBootApplication annotation.If you write codes of below your problem will be solving... Most important thing is you have to add your all controller's package to @ComponentScan annotation like i did in the below

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan({ "com.controller.package1, com.controller.package2, com.controller.package3, com.controller.packageN", "controller", "service" } // If our Controller class or Service class is not in the same packages we have //to add packages's name like this...directory(package) with main class
public class MainApp {
    public static void main(String[] args) {
        SpringApplication.run(MainApp.class, args);
    }
}

I hope this codes are going to help someone...

If you find another way to solve this error or you have some suggestions for me, please write to comments... thanks...



回答17:

Make sure your Main.class should be on top of your controllers. In case of the following example:

Main.class containing:

@SpringBootApplication
public class Main {
    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }
}

EmployeeController.class containing:

@RestController
public class EmployeeController {
    @InitBinder
    public void setAllowedFields(WebDataBinder dataBinder) {
        dataBinder.setDisallowedFields("id");
    }

    @RequestMapping(value = "/employee/save", method = RequestMethod.GET)
    public String save(){
        Employee newEmp = new Employee();
        newEmp.setAge(25);
        newEmp.setFirstName("Pikachu");
        newEmp.setId(100);
        return "Name: " + newEmp.getFirstName() + ", Age: " + newEmp.getAge() + ", Id = " + newEmp.getId();
    }
}

If your main class is in the root folder, just like this path: {projectname}/src/main/java/main then make sure your controllers below your Main class. For example {projectname}/src/main/java/main/controllers.



回答18:

The tutorial expects you to have the Thymeleaf template engine in classpath. I ran into the same problem and finally figured this out. I'll reach out to the tutorial author to include that info.

The easiest way if you've followed the tutorial is to add the dependency to your pom.xml in the project root folder. Next time you run your app Spring will detect Thymeleaf and use the uploadform template


  org.springframework.boot
  spring-boot-starter-thymeleaf

For the full example see their Github repository.



回答19:

Do maven clean or clean verify and try to run it.The instances has to be cleaned before deploying the another project. It worked for me. I tried it for 2 days to understand this.



回答20:

I had tried many ways to fix this problem too, was like, I changed dependency spring-boot-starter-web to spring-boot-starter-thymeleaf, or I replaced annotation @RestController to @Controller but It was the same error. Finally I found a solution by adding a single line of annotation @ComponentScan(basePackages = {"hello"}) on the top of Application class and it works perfectly.

@ComponentScan(basePackages = {"hello"})
public class Application {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(App.class, args);
    }
}

I hope it helps you guys too.