Controller for Managing Receiving Addresses
package com.example.web.controller;
import com.example.core.entity.DeliveryAddress;
import com.example.core.service.DeliveryAddressService;
import com.example.core.util.ServiceResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.time.LocalDateTime;
@Controller
@RequestMapping("/deliveryAddress")
public class DeliveryAddressController {
@Autowired
private DeliveryAddressService addressService;
@GetMapping("/{id}")
public ModelAndView findAddressById(@PathVariable("id") Integer id) {
ServiceResponse response = addressService.findAddressById(id);
ModelAndView mv = new ModelAndView();
mv.addObject("response", response);
mv.setViewName("deliveryAddress/detail");
return mv;
}
@GetMapping
public ModelAndView findAllForCustomer() {
Integer customerId = 1;
ServiceResponse response = addressService.findAllByCustomerId(customerId);
ModelAndView mv = new ModelAndView();
mv.addObject("response", response);
mv.setViewName("deliveryAddress/list");
return mv;
}
@PostMapping
public ModelAndView createAddress(DeliveryAddress address) {
address.setCustomerId(1);
ServiceResponse response = addressService.createAddress(address);
ModelAndView mv = new ModelAndView();
if (response.getStatusCode() == 200) {
mv.setViewName("redirect:/deliveryAddress");
} else {
mv.addObject("response", response);
mv.setViewName("/deliveryAddress/create");
}
return mv;
}
@DeleteMapping("/{id}")
public ModelAndView deactivateAddress(@PathVariable("id") Integer addressId) {
ServiceResponse response = addressService.deactivateAddress(addressId);
ModelAndView mv = new ModelAndView();
if (response.getStatusCode() == 200) {
mv.setViewName("redirect:/deliveryAddress");
} else {
mv.setViewName("deliveryAddress/list");
mv.addObject("deactivationError", "Deletion failed");
}
return mv;
}
@GetMapping("/edit/{id}")
public ModelAndView getForEdit(@PathVariable("id") Integer id) {
ServiceResponse response = addressService.findAddressById(id);
ModelAndView mv = new ModelAndView();
mv.addObject("response", response);
mv.setViewName("deliveryAddress/edit");
return mv;
}
@PutMapping
public ModelAndView modifyAddress(DeliveryAddress address) {
address.setModificationTime(LocalDateTime.now());
ServiceResponse response = addressService.modifyAddress(address);
ModelAndView mv = new ModelAndView();
if (response.getStatusCode() == 200) {
mv.setViewName("redirect:/deliveryAddress/" + address.getId());
} else {
mv.addObject("modificationError", "Update failed");
mv.setViewName("edit");
}
return mv;
}
}
Entity Class
package com.example.core.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
@TableName("delivery_address")
public class DeliveryAddress implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "address_id", type = IdType.AUTO)
private Integer id;
private Long recipientPhone;
private String recipientName;
private Integer customerId;
private String province;
private String city;
private String district;
private String street;
private String detail;
private Integer status;
private Integer version;
private LocalDateTime creationTime;
private LocalDateTime modificationTime;
// Getters and Setters omitted for brevity
}
Mapper Interface
package com.example.core.repository;
import com.example.core.entity.DeliveryAddress;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface DeliveryAddressMapper extends BaseMapper<DeliveryAddress> {
}
Service Implementation
package com.example.core.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.core.entity.DeliveryAddress;
import com.example.core.repository.DeliveryAddressMapper;
import com.example.core.service.DeliveryAddressService;
import com.example.core.util.ServiceResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
@Service
public class DeliveryAddressServiceImpl implements DeliveryAddressService {
@Autowired
private DeliveryAddressMapper addressRepository;
@Override
public ServiceResponse findAddressById(Integer id) {
DeliveryAddress address = addressRepository.selectById(id);
return address != null ? ServiceResponse.success(address) : ServiceResponse.failure("Address not found");
}
@Override
public ServiceResponse findAllByCustomerId(Integer customerId) {
LambdaQueryWrapper<DeliveryAddress> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(DeliveryAddress::getCustomerId, customerId)
.eq(DeliveryAddress::getStatus, 1);
List<DeliveryAddress> addresses = addressRepository.selectList(wrapper);
if (addresses == null || addresses.isEmpty()) {
return ServiceResponse.failure("No delivery addresses found");
}
return ServiceResponse.success(addresses);
}
@Override
public ServiceResponse createAddress(DeliveryAddress address) {
address.setStatus(1);
address.setVersion(1);
address.setCreationTime(LocalDateTime.now());
int affectedRows = addressRepository.insert(address);
return affectedRows > 0 ? ServiceResponse.success(address) : ServiceResponse.failure("Creation failed");
}
@Override
public ServiceResponse deactivateAddress(Integer id) {
DeliveryAddress address = addressRepository.selectById(id);
address.setStatus(0);
address.setVersion(address.getVersion() + 1);
int affectedRows = addressRepository.updateById(address);
return affectedRows > 0 ? ServiceResponse.success(address) : ServiceResponse.failure("Deactivation failed");
}
@Override
public ServiceResponse modifyAddress(DeliveryAddress address) {
int currentVersion = addressRepository.selectById(address.getId()).getVersion();
address.setVersion(currentVersion + 1);
int affectedRows = addressRepository.updateById(address);
return affectedRows > 0 ? ServiceResponse.success(address) : ServiceResponse.failure("Modification failed");
}
}
Service Interface
package com.example.core.service;
import com.example.core.entity.DeliveryAddress;
import com.example.core.util.ServiceResponse;
public interface DeliveryAddressService {
ServiceResponse findAddressById(Integer id);
ServiceResponse findAllByCustomerId(Integer customerId);
ServiceResponse createAddress(DeliveryAddress address);
ServiceResponse deactivateAddress(Integer id);
ServiceResponse modifyAddress(DeliveryAddress address);
}
Response Utility Class
package com.example.core.util;
public class ServiceResponse {
private int statusCode;
private String message;
private Object payload;
public static ServiceResponse success(Object payload) {
return new ServiceResponse(200, "Operation succeeded", payload);
}
public static ServiceResponse failure(Object payload) {
return new ServiceResponse(400, "Operation failed", payload);
}
public static ServiceResponse successWithMessage(String message, Object payload) {
return new ServiceResponse(200, message, payload);
}
// Constructor and Getters/Setters omitted for brevity
}
Database Schema
CREATE TABLE `delivery_address` (
`address_id` int NOT NULL AUTO_INCREMENT,
`recipient_phone` bigint DEFAULT NULL,
`recipient_name` varchar(255) DEFAULT NULL,
`customer_id` int DEFAULT NULL,
`province` varchar(255) NOT NULL,
`city` varchar(255) NOT NULL,
`district` varchar(255) NOT NULL,
`street` varchar(255) NOT NULL,
`detail` varchar(255) NOT NULL,
`status` int DEFAULT NULL,
`version` int DEFAULT NULL,
`creation_time` datetime DEFAULT NULL,
`modification_time` datetime DEFAULT NULL,
PRIMARY KEY (`address_id`),
KEY `fk_address_customer` (`customer_id`),
CONSTRAINT `fk_address_customer` FOREIGN KEY (`customer_id`) REFERENCES `customer` (`customer_id`)
);
Application Configuration
server:
servlet:
context-path: /api
port: 8080
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/app_db?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: db_user
password: db_password
mvc:
view:
prefix: /
suffix: .jsp
hiddenmethod:
filter:
enabled: true
JSP View Examples
Detail Page (detail.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Address Details</title>
</head>
<body>
Recipient: ${response.payload.recipientName} <br>
Phone: ${response.payload.recipientPhone}<br>
Address: ${response.payload.province} ${response.payload.city} ${response.payload.district} ${response.payload.street} ${response.payload.detail}
</body>
</html>
List Page (list.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Address List</title>
<script src="${pageContext.request.contextPath}/js/jquery-3.7.0.min.js"></script>
<style>
/* CSS styles for address list */
</style>
</head>
<body>
${deactivationError}
<c:choose>
<c:when test="${response.statusCode != 200}">
No data available
</c:when>
<c:otherwise>
<div class="container">
<h2>My Delivery Addresses</h2>
<ul class="addressList" id="addressList">
<c:forEach var="addr" items="${response.payload}">
<li>
<div class="btn-container">
<a href="${pageContext.request.contextPath}/deliveryAddress/edit/${addr.id}">Edit</a>
<form method="post" action="${pageContext.request.contextPath}/deliveryAddress/${addr.id}">
<input type="hidden" name="_method" value="DELETE">
<input type="button" value="Remove" class="removeBtn">
</form>
</div>
<h3>${addr.recipientName}</h3>
<p>Phone: ${addr.recipientPhone}</p>
<p>Address: ${addr.province} ${addr.city} ${addr.district} ${addr.street} ${addr.detail}</p>
</li>
</c:forEach>
</ul>
</div>
</c:otherwise>
</c:choose>
<script>
document.querySelector(".addressList").onclick = function(event) {
var targetElement = event.target;
if (targetElement.nodeName === 'INPUT' && targetElement.className === 'removeBtn') {
if (confirm("Confirm removal of this address?")) {
targetElement.parentElement.submit();
}
}
};
</script>
</body>
</html>
Create Form (create.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Add Delivery Address</title>
<style>
/* Form styling */
</style>
</head>
<body>
<div class="container">
<h2>Add New Address</h2>
<form id="addressForm" method="post" action="${pageContext.request.contextPath}/deliveryAddress">
<label for="recipient">Recipient Name:</label>
<input type="text" id="recipient" name="recipientName" required>
<label for="phone">Phone Number:</label>
<input type="tel" id="phone" name="recipientPhone" required>
<label for="provinceSelect">Province:</label>
<select id="provinceSelect" name="province" required>
<option value="">Select Province</option>
<option value="Jiangsu">Jiangsu</option>
<option value="Zhejiang">Zhejiang</option>
<option value="Guangdong">Guangdong</option>
</select>
<label for="citySelect">City:</label>
<select id="citySelect" name="city" required>
<option value="">Select City</option>
</select>
<label for="districtInput">District:</label>
<input type="text" id="districtInput" name="district" required>
<label for="streetInput">Street:</label>
<input type="text" id="streetInput" name="street" required>
<label for="detailInput">Detail:</label>
<input type="text" id="detailInput" name="detail" required>
<input type="submit" value="Submit">
</form>
</div>
<script>
const cityMapping = {
"Jiangsu": ["Suzhou", "Nanjing", "Wuxi"],
"Zhejiang": ["Hangzhou", "Ningbo", "Wenzhou"],
"Guangdong": ["Guangzhou", "Shenzhen", "Dongguan"]
};
document.getElementById("provinceSelect").addEventListener("change", function() {
const citySelect = document.getElementById("citySelect");
citySelect.innerHTML = '<option value="">Select City</option>';
const selectedCities = cityMapping[this.value];
if (selectedCities) {
selectedCities.forEach(city => {
const option = document.createElement("option");
option.value = city;
option.textContent = city;
citySelect.appendChild(option);
});
}
});
</script>
</body>
</html>
Edit Form (edit.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Edit Address</title>
<style>
/* Form styling */
</style>
</head>
<body>
<div class="container">
<h2>Edit Address</h2>
<form action="${pageContext.request.contextPath}/deliveryAddress" method="post">
<input type="hidden" name="_method" value="PUT"/>
<input type="hidden" name="id" value="${response.payload.id}">
<label for="recipientEdit">Recipient Name:</label>
<input type="text" id="recipientEdit" name="recipientName" value="${response.payload.recipientName}" required>
<label for="phoneEdit">Phone:</label>
<input type="tel" id="phoneEdit" name="recipientPhone" value="${response.payload.recipientPhone}" required>
<label for="provinceEdit">Province:</label>
<select id="provinceEdit" name="province" required>
<option value="${response.payload.province}">${response.payload.province}</option>
<option value="Jiangsu">Jiangsu</option>
<option value="Zhejiang">Zhejiang</option>
<option value="Guangdong">Guangdong</option>
</select>
<label for="cityEdit">City:</label>
<select id="cityEdit" name="city" required>
<option value="${response.payload.city}">${response.payload.city}</option>
</select>
<label for="districtEdit">District:</label>
<input type="text" id="districtEdit" name="district" value="${response.payload.district}" required>
<label for="streetEdit">Street:</label>
<input type="text" id="streetEdit" name="street" value="${response.payload.street}" required>
<label for="detailEdit">Detail:</label>
<input type="text" id="detailEdit" name="detail" value="${response.payload.detail}" required>
<input type="submit" value="Update">
</form>
</div>
<script>
// Same city mapping and population logic as create.jsp
</script>
</body>
</html>