繁体   English   中英

如何从 Angular 前端创建 Spring 引导 object?

[英]How do I create a Spring boot object from the Angular front-end?

我正在开发一个电子商务,其后端采用 Spring 引导,前端采用 Angular 材料。 当我在浏览器的支付页面中,在按钮Pay上的点击事件之后,我希望创建一个与发生点击事件的支付相关的订单,但我不知道怎么做这件事。 问题是,当我在点击事件后创建一个Payment类型的 object 时,这个 object (由于PaymentOrder之间的 1:1 关系)需要一个 object 和我在下面的实体中显示的Order类型不知道如何从前端创建它并将其与相关的Payment object 连接起来。

后端

在此处输入图像描述

订单实体:

@Getter
@Setter
@EqualsAndHashCode
@ToString
@Entity

@Table(name = "order", schema = "purchase")
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private int id;

    @Basic
    @CreationTimestamp
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "order_time")
    private Date orderTime;



    @OneToMany(mappedBy = "order", cascade = CascadeType.MERGE)
    private List<ProductInOrder> productsInOrder;


    @ManyToOne
    @JoinColumn(name = "buyer")
    private User buyer;

    @OneToOne(mappedBy= "order")
    private TheReturn theReturn;


    @OneToOne
    @JoinColumn(name = "payment_id")
    @JsonIgnore
    private Payment payment;

    @OneToOne
    @JoinColumn(name = "cart_id")
    private Cart cart;
}

支付实体:

@Getter
@Setter
@EqualsAndHashCode
@ToString
@Entity
@Table(name = "payment", schema = "purchase")
public class Payment {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private int id;

    @Basic
    @Column(name = "owner_name", nullable = true, length = 70)
    private String ownerName;

    @Basic
    @Column(name = "owner_last_name", nullable = true, length = 70)
    private String ownerLastName;

    @Basic
    @Column(name = "card_number", nullable = true, length = 16)
    //il numero di una carta PayPal è di 16 cifre
    private String cardNumber;

    @Basic
    @Temporal(TemporalType.DATE)

    @Column(name = "expiration", nullable = true)
    private Date expiration;

    @Basic
    @Column(name = "cvv", nullable = true, length = 3)
    private String cvv;

    @Basic
    @Column(name = "total", nullable = true)
    private float total;

    @OneToOne(mappedBy = "payment")
    private Order order;

    @OneToOne(mappedBy = "payment")
    private TheReturn theReturn;
}

订单服务:

@Service
public class OrderService {
    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private ProductInOrderRepository productInOrderRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private CartRepository cartRepository;

    @Autowired
    private PaymentRepository paymentRepository;

    @Autowired
    private EntityManager entityManager;



    @Transactional(readOnly = false)
    public Order addOrder(Order order) throws ProductUnavailableException, EmptyOrderException, UserNotFoundException, CartNotFoundException, CartAlreadyExistsException{//

        if(order.getProductsInOrder()==null || order.getProductsInOrder().size()<=0){          
            throw new EmptyOrderException();
        }
        if(!userRepository.existsById(order.getBuyer().getId())){
            throw new UserNotFoundException();
        }

        if(!cartRepository.existsById(order.getCart().getId())){
            throw new CartNotFoundException();
        }

        if(orderRepository.findByCart(order.getCart())!=null){
            throw new CartAlreadyExistsException();
        }
        Order result = orderRepository.save(order);
        for(ProductInOrder p : result.getProductsInOrder()){
            p.setOrder(result);
            ProductInOrder justAdded = productInOrderRepository.save(p);

            entityManager.refresh(justAdded);
            Product product = justAdded.getProduct();
            int newQuantity = product.getQuantity() - p.getQuantity();
            if(newQuantity < 0){
                orderRepository.delete(order);
                p.setOrder(null);
                productInOrderRepository.delete(p);
                throw new ProductUnavailableException(product);
            }
            product.setQuantity(newQuantity);
            entityManager.refresh(p);
        }
        entityManager.refresh(result);
        return result;
    }

订单控制器:

@RestController
@RequestMapping("/orders")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @PostMapping("/createOrder")
    @ResponseStatus(code = HttpStatus.OK)
    public ResponseEntity create(@RequestBody @Valid Order order){//Funziona
    //System.out.println("Ordine in orderController: "+order+"\n");
        try{
            return new ResponseEntity<>(orderService.addOrder(order), HttpStatus.OK);
        }catch (ProductUnavailableException e){
            return new ResponseEntity<>(new ResponseMessage("The quantity of product: "+e.getProduct().getName()+" is unavailable!"), HttpStatus.BAD_REQUEST);
        } catch (EmptyOrderException e) {
            return new ResponseEntity<>(new ResponseMessage("The order has no products."), HttpStatus.BAD_REQUEST);
        } catch (UserNotFoundException e) {
            return new ResponseEntity<>(new ResponseMessage("User not found."), HttpStatus.BAD_REQUEST);
        } catch (CartNotFoundException e) {
            return new ResponseEntity<>(new ResponseMessage("Cart not found."), HttpStatus.BAD_REQUEST);
        } catch (CartAlreadyExistsException e) {
            return new ResponseEntity<>(new ResponseMessage("Cannot associate the same cart cart to more than one order."), HttpStatus.BAD_REQUEST);
        }
    }

支付服务:

@Service
public class PaymentService {

    @Autowired
    private PaymentRepository paymentRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private EntityManager entityManager;

    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public Payment addPayment(Payment p) throws PaymentAlreadyExistsException, IncorrectCardNumberException, IncorrectCvvException{//
        if(paymentRepository.existsByCardNumber(p.getCardNumber())){
            throw new PaymentAlreadyExistsException();
        }
        if(p.getCardNumber().length()!=16){
            throw new IncorrectCardNumberException();
        }
        if(p.getCvv().length()!=3)
        {
            throw new IncorrectCvvException();
        }
        Order newOrder = new Order();
        newOrder.setPayment(p);
        Order justAdded=orderRepository.save(newOrder);
        entityManager.refresh(justAdded);
        p.setOrder(justAdded);
        return paymentRepository.save(p);
    }

支付控制器:

@RestController
@RequestMapping("/payments")
public class PaymentController {
    @Autowired
    private PaymentService paymentService;

    @PostMapping("/createPayment")//funziona
    public ResponseEntity<Payment> create(@RequestBody @Valid Payment payment){
        System.out.print("Sono in paymentController.");
        try {
            Payment added=paymentService.addPayment(payment);
            return new ResponseEntity<>(added, HttpStatus.OK);
        } catch (PaymentAlreadyExistsException e) {
            return new ResponseEntity(new ResponseMessage("Payment already exists!"), HttpStatus.BAD_REQUEST);
        } catch (IncorrectCardNumberException e) {
            return new ResponseEntity(new ResponseMessage("Incorrect card number!"), HttpStatus.BAD_REQUEST);
        } catch (IncorrectCvvException e) {
            return new ResponseEntity(new ResponseMessage("Incorrect CVV"), HttpStatus.BAD_REQUEST);
        }
}

前端

payment.component.html(在这个 html 文件中有我所说的点击事件):

<form #paymentForm="ngForm">


 <div class="form-group">
    <label for="ownerName">OwnerName*</label>
    <input type="text" ngModel name="ownerName" class="form-control" id="ownerName" placeholder="OwnerName" required>
 </div>
  <div class="form-group">
    <label for="ownerLastName">OwnerLastName*</label>
    <input type="text" ngModel name="ownerLastName" class="form-control" id="ownerLastName" placeholder="OwnerLastName" required>
 </div>


  <div class="form-group">
     <label for="cardNumber">CardNumber*</label>
     <input type="text" ngModel name="cardNumber" class="form-control" id="cardNumber" placeholder="CardNumber" required>
  </div>

  <div class="form-group">
     <label for="cvv">Cvv*</label>
     <input type="text" ngModel name="cvv" class="form-control" id="cvv" placeholder="cvv" required>
  </div>


  <div class="form-group">
    <label for="expiration">Expiration*</label>
    <input type="date" ngModel name="expiration" class="form-control" id="expiration" placeholder="expiration" required>
 </div>

 <p>(Tutti i campi contrassegnati con * devono essere riempiti)</p>

  <div class="modal-footer">
     <button [disabled]="paymentForm.invalid" type="submit" class="btn btn-primary" (click)="createPayment('Payment successful!', 'ok', paymentForm)" routerLink="/orders"  routerLinkActive="active">Pay</button>
  </div>
  </form>

payment.component.ts:

export class PaymentComponent implements OnInit {
  public total:number=0;
  public payment!: Payment;
  ownerNameFormControl = new FormControl('', [Validators.required]);
  ownerLastNameFormControl = new FormControl('', [Validators.required]);
  constructor(private _snackBar: MatSnackBar, private paymentService:PaymentService, private shared: SharedService) { }

  ngOnInit(): void {
    this.shared.castTotal.subscribe(total=>this.total=total);
    this.shared.castPayment.subscribe(payment=>this.payment=payment);
  }
  public createPayment(message:string, action:string, createForm:NgForm ) {
    this.paymentService.createPayment(createForm.value).subscribe(
      (response: Payment) => {
        this.payment=response;
        this.shared.setPayment(this.payment);
        console.log(response);
        this._snackBar.open(message, action);
        createForm.reset();

      },
      (error: HttpErrorResponse)=>{
        alert(error.message);
        createForm.reset();
      }
    )
  }
}

付款服务.ts:

@Injectable({
  providedIn: 'root'
})
export class PaymentService {

  constructor(private http: HttpClient) { }

  public createPayment(payment: Payment): Observable<Payment> {
    console.log("Sono in payment service");
    return this.http.post<Payment>('http://localhost:8080/payments/createPayment', payment);
  }

shared.service.ts:

export class SharedService {
  public defaultPayment!: Payment;
  private payment= new BehaviorSubject<Payment>(this.defaultPayment);
  castPayment = this.payment.asObservable();

  constructor() { }

   setPayment(data: Payment){
      this.payment.next(data);   }

order.component.ts:

export class OrderComponent implements OnInit {
  public payment!: Payment;
  public cart!: Cart;
  displayedColumns = ['img', 'name', 'description', 'price', 'quantity'];
  constructor(private shared: SharedService) { }

  ngOnInit(): void {
    this.shared.castPayment.subscribe(payment=>this.payment=payment);
    this.shared.castCart.subscribe(cart=>this.cart=cart);
  }

}

order.service.ts:

export class OrderService {

  constructor(private http: HttpClient) { }

  public createOrder(order: Order): Observable<void> {
    return this.http.post<void>('http://localhost:8080/orders/createOrder', order);
  }

付款.ts:

export interface Payment{
  id: number;
  ownerName: string;
  ownerLastName: string;
  cardNumber: string;
  expiration: Date;
  cvv: string;
  total: number;
  order: Order;
  theReturn: TheReturn;

}

从 FE 向 BE 发送请求基本上有 2 个步骤:

  1. FE 向后端发送请求:

正如您在 Angular 文档中的示例中所见:

/** POST: add a new hero to the database */
addHero(hero: Hero): Observable<Hero> {
  return this.http.post<Hero>(`http://localhost:portNumber/hero`, hero, httpOptions)
    .pipe(
      catchError(this.handleError('addHero', hero))
    );
}

您只需将包含您需要的所有字段的 object 发送到后端。 发送时 - 它以 JSON 发送,这意味着如果 Hero class 具有字段namepower ,它将像这样发送:

{
  "name": "Superman",
  "power": "Can disguise himself by wearing glasses"
}
  1. 在后端使用它:

在 Spring Controller 中,您只需要定义一个 controller 方法,该方法期望具有相同字段的 ZA8CFDE6331BD59EB66AC96F8911。 Spring 具有 Jackson 的依赖关系,它会自动为您反序列化 JSON,所以正如我所说,您只需要创建一个包含所有字段的 DTO。

class HeroDTO {
  private String name; 
  private String power;

  //getters, setters and noArg constructor - important to have for deserialization to work!
}

然后在 controller 方法中:

@PostMapping(value = "/hero", produces = APPLICATION_JSON_VALUE)
public ResponseEntity createHero(@RequestBody HeroDTO heroDTO) {
    //do whatever
}

顺便说一句,您可能会收到 CORS 错误 - 这是正常的,可以通过将@CrossOrigin添加到 Controller 的顶部来禁用 CORS。 更多在这里

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM