package org.springside.core.commons; import org.apache.commons.lang.StringUtils; import org.springframework.validation.BindingResult; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.servlet.ModelAndView; import org.springside.core.Constants; import org.springside.core.commons.support.IUser; import org.springside.core.commons.support.audit.AuditableEntity; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * SpringSide 基于命名规则的CRUD Controller基类. * 结合了Multi-Action 与 Form Controller的优点, * 本类演示的仅仅是封装的一种可能性,大家可以根据自己的项目自由扩展或重定义. * 如果不需要这么紧密的封装,可用{@link BaseController} * * @author calvin * @see BaseController * @see org.springside.bookstore.admin.web.BookManageController */ abstract public class BaseManageController extends BaseController { /** * 以下的View变量即可以在配置文件中定义,也可以在子类静态初始化 *
     * {
     * listView = "/admin/listBook.jsp";
     * editView = "/admin/editBook.jsp";
     * successView = "redirect:/admin/book.do";
     * }
     * 
*/ protected String listView = null; protected String editView = null; protected String showView = null; protected String successView = null; public void setListView(String listView) { this.listView = listView; } public void setEditView(String editView) { this.editView = editView; } public void setSuccessView(String successView) { this.successView = successView; } public void setShowView(String showView) { this.showView = showView; } /** * 设置默认函数为list() */ public ModelAndView index(HttpServletRequest request, HttpServletResponse response) throws Exception { return list(request, response); } /** * 显示对象列表页面的模板方法. * 调用子类的 {@link #onList(HttpServletRequest,HttpServletResponse,ModelAndView)} */ public ModelAndView list(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mav = new ModelAndView(listView); mav.addAllObjects(referenceData(request)); onList(request, response, mav); return mav; } /** * 显示创建新对象的输入页面的模板方法. * 调用子类的 {@link #onCreate(HttpServletRequest,HttpServletResponse,ModelAndView)} */ public ModelAndView create(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mav = new ModelAndView(editView); mav.addAllObjects(referenceData(request)); onCreate(request, response, mav); return mav; } /** * 保存新增对象的模板方法. * 调用子类的 {@link #onSave(HttpServletRequest,HttpServletResponse,ModelAndView,boolean)} */ public ModelAndView save(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mav = new ModelAndView(successView); onSave(request, response, mav, true); return mav; } /** * 显示对象修改时的输入页面的模板方法. * 调用子类的 {@link #onEdit(HttpServletRequest,HttpServletResponse,ModelAndView)} */ public ModelAndView edit(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mav = new ModelAndView(editView); mav.addAllObjects(referenceData(request)); onEdit(request, response, mav); return mav; } /** * 显示对象详情页面的模板方法。该页面中的对象属性不能修改 * 调用子类的 {@link #onShow(HttpServletRequest,HttpServletResponse,ModelAndView)} */ public ModelAndView show(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mav = new ModelAndView(showView); mav.addAllObjects(referenceData(request)); onShow(request, response, mav); return mav; } /** * 保存对象更新的模板方法 * 调用子类的 {@link #onSave(HttpServletRequest,HttpServletResponse,ModelAndView,boolean)} */ public ModelAndView update(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mav = new ModelAndView(successView); onSave(request, response, mav, false); return mav; } /** * 查询对象的模板方法 * 调用子类的 {@link #onQuery(HttpServletRequest,HttpServletResponse,ModelAndView)} */ public ModelAndView query(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mav = new ModelAndView(listView); mav.addAllObjects(referenceData(request)); onQuery(request, response, mav); return mav; } /** * 删除选择的对象的模板方法 * 调用子类的 {@link #onRemoveSelected(HttpServletRequest,HttpServletResponse,ModelAndView)} */ public ModelAndView removeSelected(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mav = new ModelAndView(successView); mav.addAllObjects(referenceData(request)); onRemoveSelected(request, response, mav); return mav; } /*以下为回调函数列表,意义见前,在各子类中实现*/ protected void onList(HttpServletRequest request, HttpServletResponse response, ModelAndView mav) throws Exception { } protected void onCreate(HttpServletRequest request, HttpServletResponse response, ModelAndView mav) throws Exception { } protected void onEdit(HttpServletRequest request, HttpServletResponse response, ModelAndView mav) throws Exception { } protected void onShow(HttpServletRequest request, HttpServletResponse response, ModelAndView mav) throws Exception { } protected void onQuery(HttpServletRequest request, HttpServletResponse response, ModelAndView mav) throws Exception { } protected void onSave(HttpServletRequest request, HttpServletResponse response, ModelAndView mav, boolean isNew) throws Exception { } protected void onRemoveSelected(HttpServletRequest request, HttpServletResponse response, ModelAndView mav) throws Exception { } /** * 将辅助显示的对象,如类别列表,状态列表 放入request的Attribute中. * 实际调用{@link #referenceData(HttpServletRequest, Map)}, * 多此一层封装仅仅为了初始化module. */ protected Map referenceData(HttpServletRequest request) { Map model = new HashMap(); referenceData(request, model); return model; } /** * 将辅助显示的对象,如类别列表,状态列表 放入request的Attribute中. * 在各子类实现. */ protected void referenceData(HttpServletRequest request, Map model) { } /** * 回调函数.校验出错时,将出错的对象及出错信息放回model. * 在{@link #onSave(HttpServletRequest,HttpServletResponse,ModelAndView,boolean)}中调用. */ protected ModelAndView onBindError(HttpServletRequest request, BindingResult result, ModelAndView mav, String viewName) { mav.setViewName(viewName); mav.addAllObjects(result.getModel()); mav.addAllObjects(referenceData(request)); return mav; } /** * 为AuditableEntity接口重载了{@link BaseController#bindObject(javax.servlet.http.HttpServletRequest, Object)}的bindObject函数. * 如果对象实现了该接口: * 自动对createUser/modifyUser取session中的"user"属性. * 自动对createTime/modifyTime取当前时间. */ protected BindingResult bindObject(HttpServletRequest request, Object command) throws Exception { BindingResult result = super.bindObject(request, command); if (command instanceof AuditableEntity) { AuditableEntity ve = (AuditableEntity) command; IUser user = (IUser) request.getSession().getAttribute(Constants.USER_IN_SESSION); if (ve.getCreateUser() == null) ve.setCreateUser(user); else ve.setModifyUser(user); if (ve.getCreateTime() == null) ve.setCreateTime(new Date()); else ve.setModifyTime(new Date()); } return result; } /** * 将上传文件写到服务器硬盘. * 一些不支持BLOB类型的数据库,必须把上传的文件写到硬盘. * 本函数写得并不严谨,如文件同名判断,加入时间戳作为文件名一部分等未做,just for demo * * @return 文件的相对路径 */ protected String uploadImageToFile(HttpServletRequest request, String uploadDir, String parameterName) throws IOException { String fileRelativePath = null; MultipartHttpServletRequest multipartRequest = null; try { multipartRequest = (MultipartHttpServletRequest) request; } catch (ClassCastException e) { return null; //only for testcast 中,mockservlet不能转为MultipartRequest } MultipartFile multipartFile = multipartRequest.getFile(parameterName); if (StringUtils.isNotEmpty(multipartFile.getOriginalFilename())) { String fileName = multipartFile.getOriginalFilename(); String fileRealPath = getServletContext().getRealPath(uploadDir) + File.separator + fileName; File file = new File(fileRealPath); multipartFile.transferTo(file); fileRelativePath = uploadDir + "/" + fileName; } return fileRelativePath; } }