SSM = Spring (業務對象管理) + Spring MVC (請求分發與視圖) + MyBatis (持久層)。優點:輕量、自由度高、Spring 生態契合度佳。本文通過商品管理系統 (CRUD、分頁、校驗、文件上傳、FreeMarker/JSP 雙視圖) 完整演示整合過程。
SqlSessionFactoryBean + MapperScannerConfigurer (掃描 com.zhangguo.ssmall.mapper)DataSourceTransactionManager + <tx:annotation-driven/> 註解事務<context:component-scan> + <aop:aspectj-autoproxy><mvc:annotation-driven>, <mvc:default-servlet-handler> 靜態資源StandardServletMultipartResolver (Servlet 3.0 原生上傳)ContextLoaderListener 載入 applicationContext.xmlDispatcherServlet 載入 springmvc-servlet.xml, load-on-startup=1, <multipart-config> 上傳限制CharacterEncodingFilter UTF-8 強制編碼public class Goods implements Serializable {
private int id;
@NotNull @Pattern(regexp="^[^><&#]{1,50}$") private String name;
@Min(1) private double price;
private String picture;
// getter/setter/toString
}
public interface GoodsDAO {
List<Goods> getGoodsPager(@Param("skip")int skip, @Param("size")int size);
Goods getGoodsById(int id);
int getGoodsCount();
int insert(Goods entity);
int delete(int id);
int update(Goods entity);
}
<mapper namespace="com.zhangguo.ssmall.mapper.GoodsDAO">
<select id="getGoodsPager" resultType="Goods">select * from goods limit #{skip},#{size}</select>
<select id="getGoodsById" resultType="Goods">select * from goods where id=#{id}</select>
<select id="getGoodsCount" resultType="int">select count(*) from goods</select>
<insert id="insert">insert into goods(name,price,picture) values(#{name},#{price},#{picture})</insert>
<delete id="delete">delete from goods where id=#{id}</delete>
<update id="update">update goods set name=#{name},price=#{price},picture=#{picture} where id=#{id}</update>
</mapper>
@Service
public class GoodsServiceImpl implements GoodsService {
@Resource GoodsDAO goodsdao;
// 分頁、CRUD 直接委託 DAO
public List<Goods> getGoodsPager(int pageNO, int size) {
return goodsdao.getGoodsPager((pageNO-1)*size, size);
}
// ... 其他方法
}
@Controller @RequestMapping("/goods")
public class GoodsController {
@Resource GoodsService goodsService;
@GetMapping("/list")
public String list(Model model, @RequestParam(defaultValue="1") int pageNO) {
int size = 5;
model.addAttribute("goods", goodsService.getGoodsPager(pageNO, size));
model.addAttribute("count", goodsService.getGoodsCount());
model.addAttribute("pageNO", pageNO);
model.addAttribute("size", size);
return "goods/list"; // JSP 視圖
}
@GetMapping("/add") public String add(Model m) { m.addAttribute("entity", new Goods()); return "goods/add"; }
@PostMapping("/addSave") public String addSave(@Valid @ModelAttribute("entity") Goods e, BindingResult br) {
if (!br.hasErrors() && goodsService.insert(e) > 0) return "redirect:/goods/list";
return "goods/add";
}
// edit, delete, deletes, upPicture (文件上傳) 同理...
}
<form:errors>)MultipartFile + UUID 重命名 + transferTo()default.jpgredirect:/goods/list,表單提交用 <c:url> 或 <base>。@ModelAttribute 才能觸發 BindingResult 綁定錯誤。order 與 suffix。DispatcherServlet 配置 <multipart-config>。這個 Demo 涵蓋了 SSM 開發 90% 的常見場景,適合作為專案骨架快速啟動新業務。