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;
}
}