Tavaszi Boot Tutorial - Bootstrap egy egyszerű alkalmazás
1. Áttekintés
A Spring Boot egy véleményes, a konvenciókon túlkonfigurációra összpontosító kiegészítő a Spring platformhoz - nagyon hasznos a minimális erőfeszítéssel történő induláshoz, és önálló, gyártási szintű alkalmazások létrehozásához.
Ez az oktatóanyag a Boot kiindulópontja - az első lépések egyszerű módon, egy alapvető webalkalmazással.
Áttekintünk néhány alapvető konfigurációt, egy kezelőfelületet, gyors adatkezelést és kivételkezelést.
2. Beállítás
Először is használjuk a Spring Initializr programot a projektünk alapjának létrehozásához.
A létrehozott projekt a Boot szülőre támaszkodik:
org.springframework.boot spring-boot-starter-parent 2.2.2.KÖZLEMÉNY
A kezdeti függőségek meglehetősen egyszerűek lesznek:
org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-jpa com.h2database h2
3. Az alkalmazás konfigurálása
Ezután konfigurálunk egy egyszerűt fő- osztály az alkalmazásunkhoz:
@SpringBootApplication public class Application {public static void main (String [] args) {SpringApplication.run (Application.class, args); }}
Figyelje meg, hogyan használjuk @SpringBootApplication mint elsődleges alkalmazáskonfigurációs osztályunk; a kulisszák mögött ez egyenértékű @ Konfiguráció, @EnableAutoConfiguration, és @ComponentScan együtt.
Végül meghatározunk egy egyszerűt alkalmazás.tulajdonságok fájl - amelynek egyelőre csak egy tulajdonsága van:
szerver.port = 8081
szerver port a kiszolgáló portját az alapértelmezett 8080-ról 8081-re változtatja; természetesen sokkal több Spring Boot tulajdonság érhető el.
4. Egyszerű MVC nézet
Adjunk hozzá egy egyszerű kezelőfelületet a Thymeleaf segítségével.
Először hozzá kell adnunk a tavaszi-bakancs-indító-timeleaf függőség a mi pom.xml:
org.springframework.boot spring-boot-starter-thymeleaf
Ez alapértelmezés szerint engedélyezi a Thymeleaf alkalmazást - nincs szükség további konfigurálásra.
Mostantól konfigurálhatjuk alkalmazás.tulajdonságok:
spring.thymeleaf.cache = false spring.thymeleaf.enabled = true spring.thymeleaf.prefix = classpath: / templates / spring.thymeleaf.suffix = .html spring.application.name = Bootstrap Spring Boot
Ezután meghatározunk egy egyszerű vezérlőt és egy alapvető kezdőlapot - üdvözlő üzenettel:
@Controller public class SimpleController {@Value ("$ {spring.application.name}") String appName; @GetMapping ("/") public String homePage (Model model) {model.addAttribute ("appName", appName); hazatérni"; }}
Végül itt van a miénk home.html:
Kezdőlap Üdvözöljük a mi App
Vegye figyelembe, hogyan használtunk egy tulajdonságot, amelyet a tulajdonságunkban definiáltunk, majd beadtuk, hogy megmutathassuk a kezdőlapunkon.
5. Biztonság
Ezután adjunk hozzá biztonságot alkalmazásunkhoz - először a biztonsági indítót is belefoglalva:
org.springframework.boot spring-boot-starter-security
Mostanra remélhetőleg észrevesz egy mintát - a legtöbb tavaszi könyvtár egyszerűen importálható projektünkbe az egyszerű Boot starterek használatával.
Egyszer a spring-boot-starter-security az alkalmazás osztályútvonalától való függőség - alapértelmezés szerint az összes végpontot bármelyik használatával biztonságban tartják httpBasic vagy formLogin a Spring Security tartalmi-tárgyalási stratégiája alapján.
Éppen ezért, ha az osztályúton van az indító, akkor általában meg kell határoznunk saját egyéni biztonsági konfigurációnkat a WebSecurityConfigurerAdapter osztály:
@Configuration @EnableWebSecurity nyilvános osztály A SecurityConfig kiterjeszti a WebSecurityConfigurerAdapter {@Orride védett void konfigurációját (HttpSecurity http) a {http.authorizeRequests () .anyRequest () .permitAll () .and. }}
Példánkban korlátlan hozzáférést engedélyezünk az összes végponthoz.
Természetesen a Spring Security egy átfogó téma, amelyet nem könnyű lefedni a konfigurációs pár sorban - ezért mindenképpen arra biztatom, hogy mélyebben foglalkozzon a témával.
6. Egyszerű kitartás
Kezdjük azzal, hogy meghatározzuk az adatmodellünket - egy egyszerű Könyv entitás:
@Entity public class Book {@Id @GeneratedValue (strategy = GenerationType.AUTO) private long id; @Column (nullable = false, egyedi = true) private String title; @Column (nullable = false) private String szerző; }
És a tárháza, a Spring Data ideális kihasználásával:
a nyilvános felület BookRepository kiterjeszti a CrudRepository {List findByTitle (String title); }
Végül természetesen konfigurálnunk kell az új perzisztencia rétegünket:
@EnableJpaRepositories ("com.baeldung.persistence.repo") @EntityScan ("com.baeldung.persistence.model") @SpringBootApplication public class Application {...}
Vegye figyelembe, hogy a következőket használjuk:
- @EnableJpaRepositories hogy a megadott csomagot tárolja-e tárolók számára
- @EntityScan hogy felvegyük JPA-entitásainkat
A dolgok egyszerűségének megőrzése érdekében itt H2 memóriában lévő adatbázist használunk - hogy ne legyenek külső függőségeink a projekt futtatásakor.
Miután belefoglaltuk a H2-függőséget, A Spring Boot automatikusan felismeri és beállítja kitartásunkat az adatforrás tulajdonságain kívül további konfigurációra nincs szükség:
spring.datasource.driver-class-name = org.h2.Driver spring.datasource.url = jdbc: h2: mem: bootapp; DB_CLOSE_DELAY = -1 spring.datasource.username = sa spring.datasource.password =
Természetesen, a biztonsághoz hasonlóan, a kitartás is tágabb téma, mint ez az alapkészlet itt, és amelyet mindenképpen tovább kell vizsgálnia.
7. Web és a vezérlő
Ezután vessünk egy pillantást egy webszintre - és ezt egy egyszerű vezérlő - a BookController.
Megvalósítjuk az alapvető CRUD műveleteket Könyv erőforrások egyszerű ellenőrzéssel:
@RestController @RequestMapping ("/ api / books") public class BookController {@Autowired private BookRepository bookRepository; @GetMapping public Iterable findAll () {return bookRepository.findAll (); } @GetMapping ("/ title / {bookTitle}") public list findByTitle (@PathVariable String bookTitle) {return bookRepository.findByTitle (bookTitle); } @GetMapping ("/ {id}") public Book findOne (@PathVariable Long id) {return bookRepository.findById (id) .orElseThrow (BookNotFoundException :: new); } @PostMapping @ResponseStatus (HttpStatus.CREATED) public Book create (@RequestBody Book book) {return bookRepository.save (book); } @DeleteMapping ("/ {id}") public void delete (@PathVariable Long id) {bookRepository.findById (id) .orElseThrow (BookNotFoundException :: new); bookRepository.deleteById (id); } @PutMapping ("/ {id}") nyilvános könyvfrissítési könyv (@RequestBody Book book, @PathVariable Long id) {if (book.getId ()! = Id) {dobjon új BookIdMismatchException (); } bookRepository.findById (id) .orElseThrow (BookNotFoundException :: new); return bookRepository.save (könyv); }}
Mivel az alkalmazás ezen aspektusa egy API, a @RestController annotáció itt - amely megfelel a @Vezérlő együtt @ResponseBody - úgy, hogy minden módszer a visszaküldött erőforrást a HTTP-válaszhoz rendeli.
Csak egy megjegyzésre érdemes felhívni a figyelmet - kitesszük a sajátunkat Könyv entitás mint külső erőforrásunk itt. Ez az itteni egyszerű alkalmazásunknak megfelel, de egy valós alkalmazásban valószínűleg el kívánja különíteni ezt a két fogalmat.
8. Hibakezelés
Most, hogy az alapalkalmazás készen áll, összpontosítsunk egyszerű központosított hibakezelő mechanizmus felhasználásával @ControllerAdvice:
A @ControllerAdvice nyilvános osztály RestExceptionHandler kiterjeszti a ResponseEntityExceptionHandler {@ExceptionHandler ({BookNotFoundException.class}) védett ResponseEntity handleNotFound (Exception ex, WebRequest kérés) {return handExceptionInternal (ex, "Book request" ; } @ExceptionHandler ({BookIdMismatchException.class, ConstraintViolationException.class, DataIntegrityViolationException.class}) public ResponseEntity handleBadRequest (Exception ex, WebRequest request) {return handExceptionInternal (ex, ex.get (ex, ex.get) ); }}
Az itt kezelt szokásos kivételeken túl egyedi kivételt is használunk:
BookNotFoundException:
public class BookNotFoundException kiterjeszti a RuntimeException {public BookNotFoundException (karakterlánc üzenet, dobható ok) {super (üzenet, ok); } // ...}
Ennek képet kell adnia arról, hogy mi lehetséges ezzel a globális kivételkezelő mechanizmussal. Ha teljes megvalósítást szeretne, tekintse meg a részletes oktatóanyagot.
Ne feledje, hogy a Spring Boot egy /hiba alapértelmezés szerint leképezés. Személyre szabhatjuk nézetét egy egyszerű létrehozásával error.html:
Hiba történt [állapot] hiba üzenet
A Boot legtöbb más aspektusához hasonlóan ezt is egyszerű tulajdonsággal tudjuk ellenőrizni:
server.error.path = / hiba2
9. Tesztelés
Végül teszteljük az új Books API-t.
Használhatjuk @SpringBootTest az alkalmazáskörnyezet betöltéséhez és annak ellenőrzéséhez, hogy nincsenek-e hibák az alkalmazás futtatásakor:
@RunWith (SpringRunner.class) @SpringBootTest nyilvános osztály SpringContextTest {@Test public void contextLoads () {}}
Ezután adjunk hozzá egy JUnit tesztet, amely a RestAssured használatával ellenőrzi a hívásokat az általunk írt API-ra:
public class SpringBootBootstrapLiveTest {private static final String API_ROOT = "// localhost: 8081 / api / books"; privát Könyv createRandomBook () {Könyvkönyv = új Könyv (); book.setTitle (randomAlfabetikus (10)); book.setAuthor (randomAlphabetic (15)); visszatérő könyv; } privát karakterlánc createBookAsUri (könyv) {Response response = RestAssured.given () .contentType (MediaType.APPLICATION_JSON_VALUE) .body (book) .post (API_ROOT); return API_ROOT + "/" + response.jsonPath (). get ("id"); }}
Először megpróbálhatunk könyveket találni variáns módszerekkel:
@Test public void whenGetAllBooks_thenOK () {Response response = RestAssured.get (API_ROOT); assertEquals (HttpStatus.OK.value (), response.getStatusCode ()); } @Test public void whenGetBooksByTitle_thenOK () {Book book = createRandomBook (); createBookAsUri (könyv); Válaszválasz = RestAssured.get (API_ROOT + "/ title /" + book.getTitle ()); assertEquals (HttpStatus.OK.value (), response.getStatusCode ()); assertTrue (response.as (List.class) .size ()> 0); } @Test public void whenGetCreatedBookById_thenOK () {Book book = createRandomBook (); Karakterlánc helye = createBookAsUri (könyv); Válasz válasz = RestAssured.get (hely); assertEquals (HttpStatus.OK.value (), response.getStatusCode ()); assertEquals (könyv.getTitle (), válasz.jsonPath () .get ("cím")); } @Test public void whenGetNotExistBookById_thenNotFound () {Response response = RestAssured.get (API_ROOT + "/" + randomNumeric (4)); assertEquals (HttpStatus.NOT_FOUND.value (), response.getStatusCode ()); }
Ezután teszteljük egy új könyv létrehozását:
@Test public void whenCreateNewBook_thenCreated () {Book book = createRandomBook (); Válaszválasz = RestAssured.given () .contentType (MediaType.APPLICATION_JSON_VALUE) .body (book) .post (API_ROOT); assertEquals (HttpStatus.CREATED.value (), response.getStatusCode ()); } @Test public void whenInvalidBook_thenError () {Book book = createRandomBook (); book.setAuthor (null); Válaszválasz = RestAssured.given () .contentType (MediaType.APPLICATION_JSON_VALUE) .body (book) .post (API_ROOT); assertEquals (HttpStatus.BAD_REQUEST.value (), response.getStatusCode ()); }
Meglévő könyv frissítése:
@Test public void whenUpdateCreatedBook_thenUpdated () {Book book = createRandomBook (); Karakterlánc helye = createBookAsUri (könyv); book.setId (Long.parseLong (hely.split ("api / könyvek /") [1])); book.setAuthor ("newAuthor"); Válasz válasz = RestAssured.given () .contentType (MediaType.APPLICATION_JSON_VALUE) .body (könyv) .put (hely); assertEquals (HttpStatus.OK.value (), response.getStatusCode ()); válasz = RestAssured.get (hely); assertEquals (HttpStatus.OK.value (), response.getStatusCode ()); assertEquals ("newAuthor", response.jsonPath () .get ("szerző")); }
És törölj egy könyvet:
@Test public void whenDeleteCreatedBook_thenOk () {Book book = createRandomBook (); Karakterlánc helye = createBookAsUri (könyv); Válasz válasz = RestAssured.delete (hely); assertEquals (HttpStatus.OK.value (), response.getStatusCode ()); válasz = RestAssured.get (hely); assertEquals (HttpStatus.NOT_FOUND.value (), response.getStatusCode ()); }
10. Következtetés
Ez a Spring Boot gyors, de átfogó bevezetője volt.
Természetesen alig karcoltuk meg itt a felszínt - ennél a keretrendszernél sokkal többről van szó, amelyeket egyetlen bevezető cikkben áttekinthetünk.
Pontosan ezért nem csak egyetlen cikkünk van a Bootról az oldalon.
Példáink teljes forráskódja itt is, mint mindig, a GitHubon van.