2015-02-18 14 views
7

Wir sind ein Spring Boot-Shop und verlassen uns bei unseren REST-Endpunkten stark auf Spring MVC. Wir verwenden Boot und eingebetteten Tomcat, um ein Self-Hosting-JAR zu erstellen. Ist es möglich, Tomcat durch Ratback zu ersetzen und gleichzeitig meinen gesamten Spring MVC-Code beizubehalten? Ich habe Angst, dass Spring MVC irgendwie in die Servlet-Spezifikation eingebunden ist und nicht ohne einen Servlet-Container laufen wird. Ich bin mir bewusst, dsyer/spring-boot-ratpack Arbeit, aber nach dem Skimming der Code konnte nicht entscheiden, ob Spring MVC gut mit der Brücke spielen würde. Kennt jemand eine Arbeit, die es uns ermöglicht, unsere Investition in Spring MVC zu behalten und Spring Boot mit Ratpack zu verwenden, um den HTTP-Verkehr zu verwalten?Ist Spring Boot + Spring MVC + Ratpack möglich?

Antwort

2

Das Spring MVC-Programmiermodell ist nicht sehr stark von Servlet-APIs abhängig, wird jedoch in keinen anderen Containern unterstützt (d. H. Nicht in Ratpack). Es gibt jetzt etwas Async-Zeug und Servlet 3.1 erweitert es noch etwas, also wenn das der Teil von Ratpack ist, der Sie anzieht, wäre vielleicht nur das Verwenden ein besserer Ansatz. Sie werden jedoch nicht den ganzen Weg zu reaktiven und nicht blockierenden E/A bekommen.

+0

Dave, interessante Idee. Ich bin auf jeden Fall an den reaktiven Dingen interessiert, die Ratpack bietet, aber ich bin auch an der Startzeit und der wahrgenommenen Schlankheit im Vergleich zu Tomcat interessiert. Viele Funktionen, die Tomcat uns bietet, bleiben ungenutzt. Während wir den Microservices-Pfad entlang gehen, finde ich, dass wir Anwendungen starten und stoppen, insbesondere im Kontext von CI. Mit kleineren, schnelleren Startanwendungen können wir unsere Zykluszeiten verkürzen. Es würde auch nicht schaden, wenn wir mit weniger Ressourcen skalieren könnten. – user1836542

+0

Ein guter Punkt, vielleicht, aber ich bin nicht wirklich überzeugt von der Startzeit Argument, bis Sie die gleiche App auf beiden Plattformen mit gleichwertigen Funktionen und Sicherheit schreiben (die meisten der Start-up-Zeit mit Tomcat besteht aus Anwendungscode Initialisierungssitzungsentropie). BTW, haltet euch später in diesem Jahr für einige superschnelle Neustarts auf der Plattform eurer Wahl (inklusive Tomcat) auf dem Laufenden - Phil Webb arbeitet an etwas. –

+0

@DaveSyer Kannst du mehr Informationen darüber geben, woran Phil gerade arbeitet :)? – geoand

11

Ich vermute, dass der Kern Ihrer Frage destilliert werden kann: "Können wir unsere Spring Controller auf die nicht blockierende HTTP-Schicht von Ratpack setzen?" und die einfachste Antwort auf diese Frage ist nein, weil das MVC-Programmiermodell nicht sehr gut in das reaktive/NIO-Modell passt.

Wenn Ihre Anwendung jedoch einigen gängigen Model-View-Controller- (und Service-) Mustern gefolgt ist, sollten Ihre Controller wirklich nur die Datenbindung durchführen und analysieren und an eine Service-Schicht delegieren. Wenn das der Fall ist, ist der Code in Ihrem Controller wahrscheinlich nicht blockierend und Sie könnten ihn einfach in den Ratpack-Code übersetzen.

Als Beispiel betrachten wir die folgende @RestController in einer Frühlings-Boot-App:

@RestController 
@RequestMapping("/user") 
class UserController { 

    @Autowired 
    UserService userService 

    @RequestMapping(method = RequestMethod.POST) 
    Long create(@RequestBody @Valid User user) { 
    User savedUser = userService.save(user) 
    return savedUser.id 
    } 
} 

Spring Datenbindung Aspekt ein Berechnungsprozess (dh nicht-I/O-bound), so können wir dies leicht übersetzen in einen Ratpack Handler:

import app.SpringConfig 
import app.User 
import app.UserService 
import org.springframework.boot.SpringApplication 
import org.springframework.context.ApplicationContext 
import ratpack.jackson.JacksonModule 

import static ratpack.groovy.Groovy.ratpack 
import static ratpack.jackson.Jackson.fromJson 
import static ratpack.jackson.Jackson.json 
import static ratpack.spring.Spring.spring 

ratpack { 
    bindings { 
    add(new JacksonModule()) 
    bindInstance(ApplicationContext, SpringApplication.run(SpringConfig)) 
    } 
    handlers { ApplicationContext ctx -> 
    register(spring(ctx)) 

    prefix("user") { 
     handler { UserService userService -> 
     byMethod { 
      post { 
      def user = parse(fromJson(User)) 
      blocking { 
       userService.save(user) 
      } then { User savedUser -> 
       render(json(savedUser)) 
      } 
      } 
     } 
     } 
    } 
    } 
} 

Wo SpringConfig wie folgt aussieht:

package app 

import org.springframework.context.annotation.Bean 
import org.springframework.context.annotation.Configuration 

@Configuration 
class SpringConfig { 
    @Bean 
    UserService userService() { 
    new UserService() 
    } 
} 

Und hier ist ein Funktionstest zu beweisen es:

package app 

import com.fasterxml.jackson.databind.ObjectMapper 
import ratpack.groovy.test.GroovyRatpackMainApplicationUnderTest 
import ratpack.test.ApplicationUnderTest 
import ratpack.test.http.TestHttpClient 
import spock.lang.Shared 
import spock.lang.Specification 

import static groovy.json.JsonOutput.toJson 

class FuncSpec extends Specification { 
    @Shared ApplicationUnderTest aut = new GroovyRatpackMainApplicationUnderTest() 
    @Shared ObjectMapper mapper = new ObjectMapper() 
    @Delegate TestHttpClient client = aut.httpClient 
    def "should parse and save user"() { 
    given: 
    def user = new User(username: "dan", email: "[email protected]") 

    when: 
    requestSpec { spec -> 
     spec.body { b -> 
     b.type("application/json") 
     b.text(toJson(user)) 
     } 
    } 
    post('user') 

    then: 
    def savedUser = mapper.readValue(response.body.text, User) 

    and: 
    savedUser.id 
    } 
} 

hoffe, das hilft!

+0

Große Antwort. Ich glaube, dass unser Layering Sound dort ist, wo die Controller hauptsächlich für die HTTP-Anpassung zuständig sind, bevor sie an Service-Beans übergeben werden, die das Heavy-Lifting durchführen. Ich glaube, Ihr vorgeschlagenes Modell wird für uns funktionieren. Daniel, müssten unsere annotierungsbasierten Ausnahme-Handler auf die Ratpack-API portiert werden oder würden sie magisch so arbeiten wie sie sind? – user1836542

+0

Da sie auf der Controller/Webmvc-Ebene eine Schnittstelle haben, müssten sie portiert werden, aber das ist ein ziemlich nahtloser Prozess in Ratpack. Die einzige Voraussetzung ist, dass ein 'ErrorHandler' in der Registry verfügbar ist. https://github.com/ratpack/ratpack/blob/master/ratpack-core/src/main/java/ratpack/error/internal/ErrorHandler.java#L22 –

+0

@DanielWoods Wird dein kommendes Buch auf Ratpack irgendwelche Informationen auf haben Wie starte ich Ratpack mit Spring Boot? – geoand