Το autowiring είναι ένα μέσο, όπου επιτρέπουμε στο Spring να ικανοποιήσει αυτόματα τις εξαρτήσεις ενός bean, βρίσκοντας άλλα beans στο application context, τα οποία ταιριάζουν στις ανάγκες του bean. Για να υποδείξουμε στο Spring, ότι πρέπει, να πραγματοποιηθεί autowiring, χρησιμοποιηούμε το annotation @Autowired είτε σε ένα field, είτε σε ένα κατασκευαστή.
Με το annotation @Configuration ορίζουμε, ότι η κλάση μας θα είναι configuration class και ότι θα περιέχει λεπτομέρειες, σχετικά με τα αντικείμενα, τα οποία θα δημιουργηθούν στο Spring application context.
@Configuration
public class AmazonS3Configuration{
}
Το annotation @Bean χρησιμοποείται σε επίπεδο μεθόδου και υποδεικνύει στο Spring, ότι η μέθοδος αυτή θα επιστρέψει ένα αντικείμενο, το οποίο θα πρέπει, να εγγραφεί ως bean στο Spring application Context με το όνομα awsS3AudioBucket.
@Configuration
public class AmazonS3Configuration{
@Bean(name = "awsS3AudioBucket")
public String getAWSS3AudioBucket() {
return awsS3AudioBucket;
}
}
Το annotation @ComponentScan επιτρέπει στο Spring, να αναζητάει annotated components.
Χρησιμοποιούμε το annotation @Component, για να δηλώσουμε ότι η κλάση είναι ένα Spring component. Το annotation σημειώνει την κλάση ως ένα bean, ώστε ο μηχανισμός ανίχνευσης components του Spring, να τα προσθέσει στο application context.
@Component
public class EmailServiceImp implements EmailService{
}
Το annotation είναι μια πιο ειδική περίπτωση του annotation @Component και χρησιμοποείται για κλάσεις, που έχουν πρόσβαση στη βάση δεδομένων.
@Repository
public interface ProductRepository extends JpaRepository{
}
Το annotation είναι μια πιο ειδική περίπτωση του annotation @Component και χρησιμοποείται για κλάσεις, που ανήκουν στο service layer.
@Service("productService")
@Transactional
public class ProductServiceImpl implements ProductService{
}
Το annotation είναι μια πιο ειδική περίπτωση του annotation @Component, σημειώνει την κλάση ως Spring Web MVC Controller και εισάγεται στο Spring IoC Container.
@Controller
public class RoutesController {
}
Το annotation @SpringBootApplication προσθέτει τα annotations @Configuration, @EnableAutoConfiguration και @ComponentScan. χρησιμοποείται στην κύρια κλάση της εφαρμογής και πρέπει, να βρίσκεται στο base package. Για παράδειγμα, αν η κλάση με το annotation τοποθετηθεί στο package springeshop, τότε το spring θα κάνει component scan μόνο στα subpackages, όπως springeshop.configuration και springeshop.model .
@EnableAsync
@SpringBootApplication(scanBasePackages={"springeshop"})
public class SpringEshopApplication {
}
Το annotation @EnableAutoConfiguration τοποθετείται στην κύρια κλάση της εφαρμογής και ενεργοποιεί τον μηχανισμό auto-configuration του Spring. Ο μηχανισμός αυτός προσπαθεί, να ρυθμίσει αυτόματα την εφαρμογή, βασισμένος στα jar dependencies ,που έχουμε προσθέσει στο classpath.
Το annotation αυτό χρησιμοποείται σε επίπεδο κλάσης. Σημειώνει την κλάση ως έναν controller, ο οποίος θα επιστρέφει ένα domain oject αντί για ένα view. Δηλαδή δεν στέλνεται html ως απάντηση, αλλά ένα domain object σε μορφή, την οποία καταλαβαίνει ο καταναλωτής όπως JSON.
@RestController
@RequestMapping("/api")
public class CategoryApiController {
}
Το annotation αυτό χρησιμοποείται σε επίπεδο κλάσης και μεθόδου. Αντιστοιχίζει ένα αίτημα HTTP σε μια συγκεκριμένη μέθοδο, η οποία θα το χειριστεί. Όταν το annotation χρησιμοποείται σε επίπεδο κλάσης, ορίζει το βασικό URL, για το οποίο θα χρησιμοποιηθεί ο controller. Η κάθε μέθοδος θα αντιστοιχίζεται σε διαφορετικό URL. Η παράμετρος method δηλώνει τι τύπου θα είναι το HTTP request, το οποίο θα χειριστεί η μέθοδος. Για παράδειγμα, όταν πραγματοποιηθεί HTTP GET αίτημα στο URL http://localhost:8080/api/deals, θα εκτελεστεί η μέθοδος getDeals().
@RestController
@RequestMapping("/api")
public class DealApiController {
@Autowired
private DealService dealService;
@Autowired
private DealImageService dealImageService;
public static final Logger logger = LoggerFactory.getLogger(DealApiController.class);
@RequestMapping( value = "/deals", method = RequestMethod.GET)
public ResponseEntity<?> getDeals(){
List deals = dealService.findAllDeals();
if(deals.isEmpty()){
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
for(Deal deal : deals){
DealImage dealImage = dealImageService.findByDeal(deal);
deal.setImageUrl(dealImage.getUrl());
}
return new ResponseEntity<List<Deal>>(deals, HttpStatus.OK);
}
}
Το annotation χρησιμοποείται στις παραμέτρους μεθόδου. Χειρίζεται δυναμικές αλλαγές στο URL, όπου ένα κομμάτι του URL λειτουργεί ως παράμετρος. Για παράδειγμα, η παρακάτω μέθοδος getProductByName() θέλουμε, να επιστρέφει το σωστό προιόν, ανάλογα με το όνομα του προιόντος στο url. Όταν ο client θέλει το προιόν με όνομα apivita-shampoo-dry-dandruff-250ml, κάνει ένα HTTP GET request στο url http://localhost:8080/api/products/apivita-shampoo-dry-dandruff-250ml και η παράμετρος name της μεθόδου παίρνει την τιμή "apivita-shampoo-dry-dandruff-250ml".
@RequestMapping( value = "/products/{name}", method = RequestMethod.GET)
public ResponseEntity<?> getProductByName(@PathVariable("name") String name) {
logger.info("Fetching Product with name {}", name);
Product product = productService.findByName(name);
if(product == null){
logger.error("Product with name {} not found.", name);
return new ResponseEntity<>(new ErrorMessage("Product with name {}" + name + " not found"), HttpStatus.NOT_FOUND);
}
ProductImage productImage = productImageService.findByProductId(product.getId());
product.setSmallImageUrl(productImage.getSmallImageurl());
product.setLargeImageUrl(productImage.getLargeImageurl());
product.setVerySmallImageUrl(productImage.getVerySmallImageurl());
int productQuantity = inventoryService.findProductQuantity(product.getId());
product.setQuantity(productQuantity);
return new ResponseEntity<Product>(product, HttpStatus.OK);
}
Το annotation χρησιμοποείται στις παραμέτρους μεθόδου. Αντιστοιχίζει τις παραμέτρους που στέλνει ο client, συνήθως με GET request, με παραμέτρους της μεθόδου , η οποία θα χειριστεί το αίτημα. Όταν o client θέλει τα brands της κατηγορίας shampoos, κάνει ένα GET HTTP request στο URL http://localhost:8080/api/brands?category=shampoos και η παράμετρος category της μεθόδου getCategoryBrands() παίρνει την τιμή "shampoos".
@RequestMapping( value = "/brands", method = RequestMethod.GET)
public ResponseEntity<?> getCategoryBrands(@RequestParam(value ="category", required = false String category) {
Category requestedCategory = categoryService.findByName(getCorrectCategoryName(category));
if(requestedCategory == null){
return new ResponseEntity<>(new ErrorMessage("Category does not exist"), HttpStatus.BAD_REQUEST);
}
List<Brand> brands = productService.findCategoryBrands(requestedCategory.getId());
if(brands.isEmpty()){
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
brands.sort((Brand brand1, Brand brand2) -> brand1.getName().compareTo(brand2.getName()));
return new ResponseEntity<List<Brand>>(brands, HttpStatus.OK);
}
Το annotation χρησιμοποείται στις παραμέτρους μεθόδου. Αντιστοιχίζει την τιμή του HTTP request body με την παράμετρο της μεθόδου, η οποία θα χειριστεί το αίτημα. Όταν o client θέλει να κάνει register, κάνει ένα HTTP POST request στο URL http://localhost:8080/api/register και η παράμετρος user της μεθόδου registerUser() παίρνει την τιμή του request body.
@RequestMapping( value = "/register", method = RequestMethod.POST)
public ResponseEntity<?> registerUser(@Valid @RequestBody User user) {
logger.info("Register user : {}", user);
if(userService.doesUserExist(user)){
return new ResponseEntity<>(new ErrorMessage("A user with username " + user.getUsername() + "already exists"), HttpStatus.CONFLICT);
}
if(userService.doesEmailExist(user)){
return new ResponseEntity<>(new ErrorMessage("Unable to create. A user with email " + user.getEmail() + "already exists"), HttpStatus.CONFLICT);
}
user.setPassword(passwordEncoder.encode(user.getPassword()));
user.setIs_active(true);
if(userService.addUserAndIsSuccess(user)){
Authority authority = new Authority();
authority.setUser(user);
authority.setRole("ROLE_USER");
if(authorityService.saveAuthorityAndIsSuccess(authority)){
return new ResponseEntity<>(user, HttpStatus.CONFLICT);
}
}
return newResponseEntity<>(user, HttpStatus.INTERNAL_SERVER_ERROR);
}
Το annotation χρησιμοποείται στις παραμέτρους μεθόδου. Μπορεί να χρησιμοποιηθεί αντί για το annotation @RequestParam και να πάρουμε το περιεχόμενο μιας φωτογραφίας.
@RequestMapping( value = "/products", method = RequestMethod.POST)
public ResponseEntity<?> createProduct(@Valid @RequestPart(value = "product") Product product,
@RequestPart (value = "smallImage") MultipartFile smallImage, @RequestPart(value = "largeImage") MultipartFile largeImage,
@RequestPart (value = "verySmallImage") MultipartFile verySmallImage) throws InterruptedException, ExecutionException {
Ορίζει ότι η αυτή η κλάση, είναι ένα entity.
@Entity
@Table(name = "brands")
public class Brand {
}
Ορίζει τον πίνακα της βάσης δεδομένων, με τον οποίο θα αντιστοιχίστει το entity.
@Entity
@Table(name = "brands")
public class Brand {
}
Ορίζει την στήλη του πίνακα, με την οποία θα αντιστοιχίστει το πεδίο του entity.
@Column(name = "quantity")
private int quantity;
Ορίζει ότι αυτό το πεδίο δεν θα αποθηκευτεί στον πίνακα της βάσης.
@Transient
private int quantity;
Ορίζει το πρωτεύον κλειδί του πίνακα.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
Ορίζει την στρατηγική παραγωγής τιμών του πρωτεύοντος κλειδιού.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
Ορίζει το συγκεκριμένο πεδίο δεν πρέπει, να είναι null.
@Column(name = "name")
@NotNull(message = "Please provide category name")
private String name;
Xρησιμοποείται, για να δηλώσουμε την πολλαπλότητα της σχέσης των entities.
@ManyToOne (optional = false)
@JoinColumn(name = "category_id")
@NotNull
private Category category;
}
Ορίζει τη στήλη, ως τη join στήλη για τη συσχέτιση των entities.
@ManyToOne (optional = false)
@JoinColumn(name = "category_id")
@NotNull
private Category category;
}
Χρησιμοποείται σε μια κλάση, για να αναπαραστήσει την κατάσταση ενός entity, αλλά δεν θα αποθηκευτεί στη βάση δεδομένων.
@Embeddable
public class OrderProductPrimaryKey implements Serializable {
}
Χρησιμοποείται σε ένα πεδίο, για να δηλώσει ότι είναι σύνθετο πρωτεύον κλειδί και embeddable κλάση.
@EmbeddedId
private OrderProductPrimaryKey id;
}
Χρησιμοποείται σε attributes συσχέτισης @ManyToOne ή @OneToOne, το οποίο παρέχει την αντιστοίχιση για ένα attribute μέσα σε ένα @EmbeddedId πρωτεύον κλειδί.
@OneToOne (fetch = FetchType.LAZY)
@MapsId("orderId")
private Order order;
}
Πραγματοποιεί validation στο μοντέλο, αφού πάρει τιμή.
Το χρησιμοποιούμε, όταν θέλουμε μια μέθοδος να εκτελεστεί σε ξεχωριστό νήμα.
Ενεργοποιεί τη λειτουργία εκτέλεσης ασύγχρονων μεθόδων του Spring.