這篇文章轉載自:我的簡書
初始Spring MVC
前幾天開始了我的spring學習之旅,由於之前使用過MVC模式來做項目,所以我先下手的是 Spring MVC,做個練手項目,非常簡單
項目介紹:
用戶輸入信息 → 后台處理 → 輸出信息
開始
- 創建Spring MVC 項目(創建時下載所需文件)
2.創建完的項目目錄是這樣的
3. 配置Web項目結構
參考另一篇文章IDEA如何創建及配置Web項目(多圖)
有變化的是: 不需要自己創建 lib 文件夾,在創建項目時已經建立,另外在 WEB-INF 建立 jsp 用於存放 .jsp 文件,其他的都沒什么區別
配置完的樣子(文件夾旁有箭頭是因為我在做完項目才截圖,具體的類以及其他文件都已在內):
- 配置Spring MVC的核心 —— dispatcher-servlet.xml
Spring MVC provides an annotation-based programming model where @Controller and @RestController components use annotations to express request mappings, request input, exception handling, and more. Annotated controllers have flexible method signatures and do not have to extend base classes nor implement specific interfaces.
如官方文檔所說,我也使用了注解來定義控制器(Controller)和服務(Service).
首先需要添加的是
<context:component-scan base-package="controller"/>
<context:component-scan base-package="service"/>
這樣我們就能通過注解來定義Controller以及Service.
然后,我們需要配置視圖解析器,在具體操作時只要寫出視圖的名稱(xxx),就可以采用URL拼接的方式,達到這種效果:/WEB-INF/jsp/xxx.jsp
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
- 開始進行具體的操作
首先是基本數據類:
public class Product {
private long id;
private String name;
private String price;
private String inventory;
public void setId(long id) {
this.id = id;
}
public long getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() { return name; }
public void setPrice(String price) {
this.price = price;
}
public String getPrice() { return price; }
public void setInventory(String inventory) {
this.inventory = inventory;
}
public String getInventory() { return inventory; }
}
接下來是收集用戶輸入所需要的表單類:
public class ProductForm {
private String name;
private String price;
private String inventory;
public void setName(String name) {
this.name = name;
}
public void setPrice(String price) {
this.price = price;
}
public void setInventory(String inventory) {
this.inventory = inventory;
}
public String getName() {
return name;
}
public String getPrice() {
return price;
}
public String getInventory() {
return inventory;
}
}
然后編寫服務接口,以及它的實現類
import domain.Product;
public interface ProductService {
Product add(Product product);
Product get(long id);
}
ProductServiceImpl就是剛才配置的服務(Service)
import domain.Product;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
@Service
public class ProductServiceImpl implements ProductService{
private Map<Long, Product> productMap = new HashMap<>();
private AtomicLong atomicLong = new AtomicLong();
@Override
public Product add(Product product){
long id = atomicLong.incrementAndGet();
product.setId(id);
productMap.put(id, product);
return product;
}
@Override
public Product get(long id){
return productMap.get(id);
}
}
最重要的是控制器:
采用**@Autowired注解的方式自動裝配Service, 使用@RequestMapping**注解的方式,將注解中的路徑映射到控制器:
import domain.Product;
import form.ProductForm;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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.servlet.mvc.support.RedirectAttributes;
import service.ProductService;
@Controller
public class ProductController {
//日志記錄具體操作
private static final Log logger = LogFactory.getLog(ProductController.class);
@Autowired
private ProductService productService;
//method = RequestMethod.POST表示只接受POST形式的請求
@RequestMapping(value = "/product_save", method = RequestMethod.POST)
//采用POST的方式發送請求
public String saveProduct(ProductForm productForm, RedirectAttributes redirectAttributes){
logger.info("saveProduct called");
//獲得用戶輸入
Product product = new Product();
product.setName(productForm.getName());
product.setPrice(productForm.getPrice());
product.setInventory(productForm.getInventory());
//添加有記錄的產品,並且根據ID進行重定向
Product savedProduct = productService.add(product);
redirectAttributes.addFlashAttribute("message", "Add product Successfully");
return "redirect:/product_view/" + savedProduct.getId();
}
//根據ID,將用戶輸入展示在ProductView中
@RequestMapping(value = "product_view/{id}")
public String viewProduct(@PathVariable Long id, Model model){
//根據ID得到信息
Product product = productService.get(id);
model.addAttribute("product", product);
//ProductView.jsp
return "ProductView";
}
}
需要注意的是,在現在的Spring版本中,如果直接對Service進行注解,將會有產生警告: 
按住Alt + Enter 修正錯誤,會看見提示:
官方推薦使用構造器注入
到此為止,后台工作就結束了
- 頁面
接下來是JSP的編寫:
首先是用戶輸入的頁面 (ProductForm.jsp)
<body>
<div>
<form action="product_save" method="post">
<fieldset>
<legend>Add a product</legend>
<p>
<label for="name">Product Name: </label>
<input type="text" id="name" name="name">
</p>
<p>
<label for="price">Price: </label>
<input type="text" id="price" name="price">
</p>
<p>
<label for="inventory">Inventory: </label>
<input type="text" id="inventory" name="inventory">
</p>
<p>
<input id="reset" type="reset" tabindex="4">
<input id="submit" type="submit" tabindex="5" value="Add Product">
</p>
</fieldset>
</form>
</div>
</body>
比較表單中的**