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
Send the request, the response status should be 201.
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
- 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() {
}
}
- 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();
}
}
- 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 方法用于实现结账的业务逻辑
}
}