Skip to content

7 Spring MVC Implementation

Three important interfaces in hibernate

  • SessionFactory: it is a heavyweight object which usually is created during application start up for connecting to a database and kept for later use. It also services clients to obtain Session instances from this factory.
  • Session: this is the central API class abstracting the notion of a persistence service, the main function of the Session is to offer create, read and delete operations for instances of mapped entity classes.
  • Transaction: allows the application to define units of work. All or nothing.

Sign up

CustomerDao.java

package com.eve.onlineOrder.dao;
// dao 层用于与数据库进行交互,包括增删改查等操作。
// dao 是 data access object 的缩写。
// 例如,CustomerDao 类用于与数据库中的 customer 表进行交互。

import com.eve.onlineOrder.entity.Authorities;
import com.eve.onlineOrder.entity.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository // @Repository 用于标注数据访问组件,即 DAO 组件。
public class CustomerDao {

    @Autowired // @Autowired 用于自动装配,将 CustomerDao 注入到 CustomerService 中。
    private SessionFactory sessionFactory; // SessionFactory 用于创建 Session 对象。
    // SessionFactory 是一个线程安全的对象,一般情况下,一个项目只需要一个 SessionFactory 对象即可。
    // SessionFactory 用于创建 Session 对象,Session 对象用于与数据库进行交互。
    // SessionFactory 通过 Hibernate 的配置文件创建,配置文件中包含数据库的连接信息。
    // 例如,src/main/resources/hibernate.cfg.xml 中包含数据库的连接信息。
    // session 是一个线程不安全的对象,因此,一般情况下,一个线程只创建一个 session 对象。
    // 例如,当用户注册时,需要向数据库中的 customer 表和 authorities 表中插入数据。
    // 因此,需要创建一个 Session 对象,然后通过 Session 对象向数据库中插入数据
    public void signUp(Customer customer){
        Authorities authorities = new Authorities(); // 创建 Authorities 对象。
        // Authorities 对象用于向数据库中的 authorities 表中插入数据。
        authorities.setAuthorities("ROLE_USER");// 设置 authorities 对象的属性。
        authorities.setEmail(customer.getEmail()); // 设置 authorities 对象的属性。

        Session session = null; // 创建 Session 对象。
        try {
            session = sessionFactory.openSession(); // 通过 SessionFactory 创建 Session 对象。
            session.beginTransaction(); // 开启事务。
            session.save(authorities); // 保存 authorities 对象。
            session.save(customer); // 保存 customer 对象。
            session.getTransaction().commit(); // 提交事务。
        } catch (Exception e) { // 捕获异常。
            e.printStackTrace(); // 打印异常信息。
            if (session != null){ // 如果 session 不为空。
                session.getTransaction().rollback(); // 回滚事务。
            }
        } finally { // 最终执行。
            if (session != null) { // 如果 session 不为空。
                session.close(); // 关闭 session。
            }
        }
    }

    public Customer getCustomer(String email){ // 通过用户名获取用户信息。
        Customer customer = null; // 创建 Customer 对象。
        try (Session session = sessionFactory.openSession()) { // 通过 SessionFactory 创建 Session 对象。
            customer = session.get(Customer.class, email); // 通过 Session 对象获取 Customer 对象。
        } catch (Exception e) { // 捕获异常。
            e.printStackTrace(); // 打印异常信息。
        }
        return customer; // 返回 Customer 对象。
    }
}

CustomerService.java:

package com.eve.onlineOrder.service;

import com.eve.onlineOrder.dao.CustomerDao;
import com.eve.onlineOrder.entity.Cart;
import com.eve.onlineOrder.entity.Customer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service // @Service 用于标注业务层组件,即 Service 组件。
// Service 层用于实现业务逻辑,例如,当用户注册时,需要向数据库中的 customer 表和 authorities 表中插入数据。
// 因此,需要在 Service 层中实现向数据库中插入数据的业务逻辑。
public class CustomerService {
    @Autowired // @Autowired 用于自动装配,将 CustomerDao 注入到 CustomerService 中。
    // CustomerDao 用于与数据库进行交互,包括增删改查等操作。
    // CustomerDao 是 data access object 的缩写。
    private CustomerDao customerDao;

    // 例如,当用户注册时,需要向数据库中的 customer 表和 authorities 表中插入数据。
    // 因此,需要在 Service 层中实现向数据库中插入数据的业务逻辑。
    public void signUp(Customer customer){
        Cart cart = new Cart(); // 创建 Cart 对象。
        // Cart 对象用于向数据库中的 cart 表中插入数据。
        customer.setCart(cart); // 设置 cart 对象的属性。

        customer.setEnabled(true); // 设置 customer 对象的属性。

        // 调用 CustomerDao 中的 signUp 方法,将 Customer 对象插入到数据库中。
        // Customer 对象包含了用户注册时填写的信息,例如,用户名、密码、地址等。
        customerDao.signUp(customer);// 调用 CustomerDao 中的 signUp 方法,将 Customer 对象插入到数据库中。
    }

    public Customer getCustomer(String email){ // 通过用户名获取用户信息。
        return customerDao.getCustomer(email);// 调用 CustomerDao 中的 getCustomer 方法,通过用户名获取用户信息。
    }

}

SignUpcontroller.java

package com.eve.onlineOrder.controller;

import com.eve.onlineOrder.entity.Customer;
import com.eve.onlineOrder.service.CustomerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;

@Controller // @Controller 用于标注控制层组件,即 Controller 组件。
public class SignUpController {

    @Autowired // @Autowired 用于自动装配,将 CustomerService 注入到 SignUpController 中。
    private CustomerService customerService;

    @RequestMapping(value = "/signup", method = RequestMethod.POST)
    // @RequestMapping 用于映射请求,即指定请求的 URL。
    // value 属性用于指定请求的 URL。例如,/signup 表示请求的 URL 为 http://localhost:8080/signup。
    // method 属性用于指定请求的方法。例如,RequestMethod.POST 表示请求的方法为 POST。
    @ResponseStatus(value= HttpStatus.CREATED)
    // @ResponseStatus 用于指定响应的状态码。
    // value 属性用于指定响应的状态码。例如,HttpStatus.CREATED 表示响应的状态码为 201。
    // HttpStatus 是一个枚举类,包含了所有的状态码。
    public void signUp(@RequestBody Customer customer){
        // @RequestBody 用于获取请求的内容。
        // 例如,当用户注册时,需要向数据库中的 customer 表和 authorities 表中插入数据。
        // 因此,需要获取请求的内容,即 Customer 对象。
        // Customer 对象包含了用户注册时填写的信息,例如,用户名、密码、地址等。
        customerService.signUp(customer);
        // 调用 CustomerService 中的 signUp 方法,将 Customer 对象插入到数据库中。

    }


}

Postman test

Maven clean -> Maven install, and start tomcat

Using postman

Screenshot 2023-12-13 at 20.51.48

Screenshot 2023-12-13 at 20.52.05

Send the request, the response status should be 201.

Screenshot 2023-12-13 at 20.53.49

Define rest of the project's API

Fetch data from url

  • @RequestParam: use the @RequestParam annotation to bind Servlet request parameters (that is, query parameters) to a method argument in a controller

For example, http://localhost:8080/search?lon=22&lat=37

If we would like to define a REST API via Spring MVC, we could define it as below

@RequestMapping(value="/search", method=RequestMethod.GET)
public String search(@RequestParam("lon") double lon, @RequestParam("lat") double lat){...}
  • PathVarible: can be used to handle template variables in the request URI mapping.

For example: get menu for a specific restaurant

http://localhost:8080/restaurant/1/menu

Create MenuInfoController.java under controller package to load restaurants and corresponding menu information

package com.eve.onlineOrder.controller;


import com.eve.onlineOrder.entity.MenuItem;
import com.eve.onlineOrder.entity.Restaurant;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.List;

// @Controller 用于标注控制层组件,即 Controller 组件。
// Controller 层用于接收请求,调用 Service 层的方法,将数据返回给前端页面。
@Controller
public class MenuInfoController {
    @RequestMapping(value="/restaurant/{restaurantId}/menu", method = RequestMethod.GET)
    // @RequestMapping 用于映射请求,即指定请求的 URL。
    // value 属性用于指定请求的 URL。例如,/restaurant/{restaurantId}/menu
    // 表示请求的 URL 为 http://localhost:8080/restaurant/{restaurantId}/menu。
    // method 属性用于指定请求的方法。例如,RequestMethod.GET 表示请求的方法为 GET。
    // RequestMethod 是一个枚举类,包含了所有的请求方法。
    @ResponseBody
    // @ResponseBody 用于将返回的数据放到响应体中。
    // 例如,当用户访问 http://localhost:8080/restaurant/{restaurantId}/menu 时,需要将菜单信息返回给前端页面。
    // 因此,需要将菜单信息放到响应体中,然后返回给前端页面。
    public List<MenuItem> getMenus(@PathVariable("restaurantId") int restaurantId){
        return new ArrayList<>();
    }

    // @RequestMapping 用于映射请求,即指定请求的 URL。
    // value 属性用于指定请求的 URL。例如,/restaurants
    //  表示请求的 URL 为 http://localhost:8080/restaurants。
    // method 属性用于指定请求的方法。例如,RequestMethod.GET 表示请求的方法为 GET。
    @RequestMapping(value="/restaurants", method = RequestMethod.GET)
    @ResponseBody
    public List<Restaurant> getRestaurants(){
        // getRestaurants 方法用于获取所有的餐馆信息
        return new ArrayList<>(); // 返回一个空的餐馆列表。
    }
}

@ResponseBody

Use the @ResponseBody annotation on a method to indicate that the return value should be written straight to the HTTP response body, and it will be automatically convert to json format

    @RequestMapping(value="/restaurants", method = RequestMethod.GET)
    @ResponseBody
    public List<Restaurant> getRestaurants(){
            ...
    }

Implementation

  1. Create ItemOrderController.java class under controller package to add a item to customer's cart

ItemOrderController.java:

package com.eve.onlineOrder.controller;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;

@Controller // @Controller 用于标注控制层组件,即 Controller 组件。
public class ItemOrderController {
    @RequestMapping(value = "/order/{menuId}", method = RequestMethod.POST)
    // @RequestMapping 用于映射请求,即指定请求的 URL。
    // value 属性用于指定请求的 URL。例如,/order/{menuId}
    // 表示请求的 URL 为 http://localhost:8080/order/{menuId}。
    // method 属性用于指定请求的方法。例如,RequestMethod.POST 表示请求的方法为 POST。
    // RequestMethod 是一个枚举类,包含了所有的请求方法。
    // 例如,当用户点击菜单中的某个菜品时,需要将该菜品添加到购物车中。
    // 因此,需要向数据库中的 cart_item 表中插入数据。
    @ResponseStatus(value = HttpStatus.CREATED)
    // @ResponseStatus 用于指定响应的状态码。
    // value 属性用于指定响应的状态码。例如,HttpStatus.CREATED 表示响应的状态码为 201。
    //  HttpStatus 是一个枚举类,包含了所有的状态码。
    public void addMenuItemToCart() {

    }
}
  1. Create CartController.java class under controller package to get customer's cart

CartController.java

package com.eve.onlineOrder.controller;

import com.eve.onlineOrder.entity.Cart;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller // @Controller 用于标注控制层组件,即 Controller 组件。
// Controller 层用于接收请求,调用 Service 层的方法,将数据返回给前端页面。
// 例如,当用户访问 http://localhost:8080/cart 时,需要将购物车信息返回给前端页面。
//  因此,需要在 Controller 层中实现将购物车信息返回给前端页面的业务逻辑。
public class CartController {
    @RequestMapping(value="/cart", method = RequestMethod.GET)
    // @RequestMapping 用于映射请求,即指定请求的 URL。
    // value 属性用于指定请求的 URL。例如,/cart
    // 表示请求的 URL 为 http://localhost:8080/cart。
    // method 属性用于指定请求的方法。例如,RequestMethod.GET 表示请求的方法为 GET。
    // RequestMethod 是一个枚举类,包含了所有的请求方法。
    @ResponseBody // @ResponseBody 用于将返回的数据放到响应体中。
    // 例如,当用户访问 http://localhost:8080/cart 时,需要将购物车信息返回给前端页面。
    // 因此,需要将购物车信息放到响应体中,然后返回给前端页面。
    public Cart getCart() {
        return new Cart();
    }


}
  1. Create CheckoutController.java class to checkout the current order
package com.eve.onlineOrder.controller;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;

@Controller // @Controller 用于标注控制层组件,即 Controller 组件。
// Controller 层用于接收请求,调用 Service 层的方法,将数据返回给前端页面。
public class CheckoutController {
    // @RequestMapping 用于映射请求,即指定请求的 URL。
    // value 属性用于指定请求的 URL。例如,/checkout
    // 表示请求的 URL 为 http://localhost:8080/checkout。
    @RequestMapping(value = "/checkout", method = RequestMethod.GET)
    // @RequestMapping 用于映射请求,即指定请求的 URL。
    // value 属性用于指定请求的 URL。例如,/checkout
    // 表示请求的 URL 为 http://localhost:8080/checkout。
    @ResponseStatus(value = HttpStatus.OK)
    // @ResponseStatus 用于指定响应的状态码。
    // value 属性用于指定响应的状态码。例如,HttpStatus.OK 表示响应的状态码为 200。
    // HttpStatus 是一个枚举类,包含了所有的状态码
    public void checkout() { // checkout 方法用于实现结账的业务逻辑
    }
}