Springboot @RestController 请求不跳转返回字符串?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Springboot @RestController 请求不跳转返回字符串?相关的知识,希望对你有一定的参考价值。

如果改成@Controller是可以,但是我还是想知道用@RestController 该如何跳转页面而不是显示字符串。

不可以,@RestController就是@Controller和@ResponseBody的结合,会直接返回方法中return的内容并转成json发到前台,无法跳转页面。
非要跳转的话也不是不行,你把页面url放到返回的参数里,在前端解析json中的地址,然后在前端跳转就完事了。
参考技术A

前后端分离项目的时候,不是你主动跳转到页面的,因为你后端静态资源里面压根就没有页面

都是以json的形式来返回给前端的异步请求方法中,让前端根据你返回的数据来解析写逻辑

参考技术B 可以,但是这样的话就不要通过视图解析器了,而是通过forward和redirect关键字,进行转发和重定向 参考技术C 其实他们作用是一样的,唯一区别是:controller:是用于注释你的action或者servlet的。service:是用来注释你的service层的实现类。repository:是用来注释你的持久层,也就是dao层的实现类的。

Springboot - DevTools - RestController 在重建项目时并不总是映射

【中文标题】Springboot - DevTools - RestController 在重建项目时并不总是映射【英文标题】:Springboot - DevTools - RestController not always mapped when Rebuild Project 【发布时间】:2016-12-25 11:41:32 【问题描述】:

我正在使用 SpringBoot 1.3.5 和 maven。

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.5.RELEASE</version>
</parent>

还有开发工具

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
</dependency>

我正在使用 Intellij IDEA 2016.2,之前是 2014 年,但遇到了同样的问题。

我正在从 Intellij Idea 运行我的 springboot 应用程序,第一次启动时一切都已加载并正常工作,我可以访问我的静态页面并且我的 2 个 Rest Controller 工作。

2016-08-18 15:27:58.771  INFO 26626 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@469d0c02: startup date [Thu Aug 18 15:27:57 CEST 2016]; root of context hierarchy
2016-08-18 15:27:58.789  INFO 26626 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "[/authentication/introspect],methods=[GET]" onto public com.myapp.models.TokenIntrospection com.myapp.resources.AuthenticationResources.introspectToken(java.lang.String)
2016-08-18 15:27:58.790  INFO 26626 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "[/configuration],methods=[GET]" onto public com.myapp.models.AppConfiguration com.myapp.resources.ConfigurationResources.getConfiguration()
2016-08-18 15:27:58.792  INFO 26626 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "[/error]" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2016-08-18 15:27:58.793  INFO 26626 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "[/error],produces=[text/html]" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)

因为简单的“制作项目”不适用于静态重新加载,所以我使用“重建项目”,有时,当应用程序重新启动时,我没有映射我的控制器,有时缺少一个,有时两个都丢失。

我对此一无所知:(

编辑

@Morfic 解决方案不起作用,所以我使用 Intellij 本地服务器来提供静态内容和 gulp-livereload 而不是 spring-dev-tools。

当我处于开发模式时,我只需要在 JS 中管理 REST 调用,因为 REST 资源位于 localhost:8080 但我的静态资源位于 localhost:63342,并在我的 springboot 中启用 CORS(在属性文件中使用一个标志来启用CORS 与否)。

@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter 

    @Value("$cors.enabled")
    private boolean corsEnabled;

    @Override
    public void addCorsMappings(CorsRegistry registry) 
        super.addCorsMappings(registry);
        if(corsEnabled) 
            registry.addMapping("/**")
                    .allowedOrigins("*")
                    .allowedMethods("GET", "PUT", "POST", "DELETE", "OPTIONS")
                    .allowedHeaders("Origin", "X-Requested-With", "Content-Type", "Accept", "Authorization")
                    .allowCredentials(true)
                    .maxAge(3600L);
        
    

所以问题仍有待解决。

【问题讨论】:

【参考方案1】:

我只是设法通过一个简单的 hello-world 服务并使用 Rebuild project 几次来重现此问题,因为它只会偶尔重现一次。我的预感是,在 IJ 有机会完全清理和重建之前,开发工具发现已经发生了变化。可能一旦资源发布并且在从我看到的输出目录编译类之前,dev-tools 开始重新加载尚不存在的类... p>

根据这个假设,我查看了日志和类时间戳,在开发工具开始重新加载上下文的时间和我的类写入磁盘的时间之间存在大约 1 秒的差距。显然,我的 @PostConstruct 日志都没有出现,并且 spring 的 autoconfig 没有找到我的类...

作为一种解决方法,您可以使用trigger-file。按照链接中的建议将其作为全局配置添加到您的主目录中,或者添加到您的 application.properties 文件中。此外,由于对该文件的任何更改(创建、删除、修改)都会触发重新启动,并且Rebuild project 会清理输出目录,因此您必须定义一个额外的路径来查找该文件。因此,假设我们有一个常规的 IJ spring boot 运行配置,application.properties 中有以下 2 个:

# name of the file to trigger a restart
spring.devtools.restart.trigger-file=restarttrigger

# where else to look for it. Also . evaluates to the app's base dir
spring.devtools.restart.additional-paths=.

...一旦您看到 IJ 完成构建过程,请转到应用程序根目录并添加或删除您的触发器文件,具体取决于它是否已经存在,这应该会导致重新启动。我已经测试了几次,到目前为止没有尝试失败。下面是手动重启过程的简短视频演示:

有几种方法可以自动执行此过程。除了在 IJ 中定义人工制品并使用后处理 ant 任务生成文件之外,您还可以使用 maven(您已经在使用)来生成这样的文件,但缺点是您必须改用 maven compile Rebuild project 的原因是 IJ 在进行重建时不会调用 maven(或者我还没有找到如何做到这一点)。请在下面找到一个简单的配置based on the fact that:

(注意:在 Maven 2.0.5 及更高版本中,绑定到一个阶段的多个目标按照它们在 POM 中声明的顺序执行,但是不支持同一插件的多个实例。相同的多个实例插件在 Maven 2.0.11 及更高版本中分组执行并排序)。

因此,the compiler plugin is by default bound to the compile phase,因此我们添加了一个小任务来使用 application.properties 文件(或其他任何内容)生成 trigger-file

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <!-- first, compile all we need -->
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.3</version>
        </plugin>
        <plugin>
            <!-- then, generate the trigger-file so dev-tools will restart -->
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.8</version>
            <executions>
                <execution>
                    <phase>compile</phase>
                    <configuration>
                        <tasks>
                            <copy file="$project.basedir/src/main/resources/application.properties"
                                  toFile="$project.basedir/restarttrigger" overwrite="true" />
                        </tasks>
                    </configuration>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

进一步更新:

查看FileSystemWatcher.scan() 的来源,有一个do-while 循环可以解释为:虽然自上次检查以来文件系统仍在进行更改,但等待(可配置的)时间并再次验证

private void scan() throws InterruptedException 
    Thread.sleep(this.pollInterval - this.quietPeriod);
    Map<File, FolderSnapshot> previous;
    Map<File, FolderSnapshot> current = this.folders;
    do 
        previous = current;
        current = getCurrentSnapshots();
        Thread.sleep(this.quietPeriod);
    
    while (isDifferent(previous, current));
    if (isDifferent(this.folders, current)) 
        updateSnapshots(current.values());
    

根据documentation,quietPeriod 可以通过spring.devtools.restart.quiet-period 属性进行配置,但根据上述来源,它必须是一个小于pollInterval 的值,可以通过spring.devtools.restart.poll-interval 进行配置。因此,玩弄这些设置,我得到了一个不错的结果:

# Amount of time (in milliseconds) to wait between polling for classpath changes.
spring.devtools.restart.poll-interval=3000

# Amount of quiet time (in milliseconds) required without any classpath changes before a restart is triggered.
spring.devtools.restart.quiet-period=2999

最后,您应该能够将这些值调整为最适合您的值。

尽管如此,如果您正在修改的源是静态资源,例如 FE GUI 页面,并且根据您的要求,也许最好使用从其位置为它们提供服务的工具,例如节点或类似的简单 http 服务器。 ..

【讨论】:

哇侯很好的解释,谢谢。正如您可能猜到的那样,每次我想重新加载我的项目时,我都无法播放文件创建/修改:(而且我没有解释它,但我使用带有 2 个休息控制器的 springboot 并且需要经常为静态文件重建 我试过这个但没有改变问题:***.com/a/36839483/1243048 @Titmael 我的建议是最简单和最安全的,因为在您创建/编辑/删除文件时,所有内容都应该已经编译并可用。不幸的是,从我所看到的情况来看,通过 Mavent 是不可能的,因为 IJ 不会在构建过程中调用它,但是如果您在构建时创建人工制品并使用构建后 Ant 目标复制触发器文件,它可能会有点自动化'有兴趣。 @Titmael 关于轮询间隔,乍一看sources 在检测到文件更改后并没有真正等待,似乎只是在更改检查之间等待多长时间,但我必须仔细看看。有机会进一步调查后,我会回复你... @Titmael 我添加了另一种与链接问题相关的可能方法。如果这也没有用,那么也许您需要寻找更合适的工具来满足您的需求......【参考方案2】:

@Morfic 的这部分回答对我很有帮助:

# Amount of time (in milliseconds) to wait between polling for classpath changes.
spring.devtools.restart.poll-interval=3000

# Amount of quiet time (in milliseconds) required without any classpath changes before a restart is triggered.
spring.devtools.restart.quiet-period=2999

【讨论】:

@Morfic 你做了多少广泛的 RnD 来让它工作?这太棒了,投票和安静时间的技巧开箱即用,感谢节省我们时间的语气。

以上是关于Springboot @RestController 请求不跳转返回字符串?的主要内容,如果未能解决你的问题,请参考以下文章

spring Restcontroller 或 RepositoryRestResource 用啥

spring boot常用注解使用小结

Spring:RestController 和 Controller 的不同异常处理程序

Spring-Boot:同时处理多个请求

协程解析前的响应,kotlin

Junit5测试无法注入依赖但正常运行的应用程序可以注入它