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
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.
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!
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
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 –
@DanielWoods Wird dein kommendes Buch auf Ratpack irgendwelche Informationen auf haben Wie starte ich Ratpack mit Spring Boot? – geoand
- 1. Spring Boot Actuator ohne Spring Boot
- 2. Spring Security Implementierung vorzugsweise ohne Spring Boot
- 3. Spring-Boot & Spring-Security-Konfiguration
- 4. Spring boot application.version ist null
- 5. Spring Boot MVC: kann JSP nicht finden
- 6. Spring Boot Statische Ressourcen
- 7. Spring Boot MVC: Whitelabel Fehler Seite
- 8. Spring Boot XML-Konfigurationsoption
- 9. Spring Cloud Config-Client ohne Spring Boot
- 10. Spring Boot und FreeMarker
- 11. Spring Boot JSP
- 12. Spring Boot + Spring Daten mit mehreren Mandanten
- 13. Spring Boot + Websocket (SockJS)
- 14. Ist es möglich, Spring Boot Session ohne Redis zu verwenden?
- 15. Sicherheitskonfiguration mit Spring-Boot
- 16. Spring Boot oaut2 Eigenschaften
- 17. Verwenden Sie den Spring Boot Actuator ohne Spring-Boot-Anwendung
- 18. Spring-Batch- oder Spring-Boot-Async-Methodenausführung?
- 19. Unterschied zwischen Spring und Spring Boot
- 20. Spring Boot mit Spring Social Google-Anbieter
- 21. Wo sind Spring-Tutorials ohne Spring-Boot?
- 22. Spring Boot + Spring Security + Hierarchische Rollen
- 23. Was ist die Beziehung zwischen Spring Boot und Spring IO?
- 24. Beschleunigte Spring Boot-Startzeit
- 25. Intellij Spring Boot PropertiesLauncher
- 26. Spring Boot mit Liferay
- 27. Spring Boot Exception Handling
- 28. Spring Boot JSP 404
- 29. Spring Boot-Sicherheitskonsole/Befehlszeilenanwendung
- 30. Vorteil der Spring Boot
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
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. –
@DaveSyer Kannst du mehr Informationen darüber geben, woran Phil gerade arbeitet :)? – geoand