基于javaweb+mysql的ssm+maven仓库管理系统(java+ssm+jsp+mysql+maven)
运行环境
Java≥8、MySQL≥5.7、Tomcat≥8
开发工具
eclipse/idea/myeclipse/sts等均可配置运行
适用
课程设计,大作业,毕业设计,项目练习,学习演示等
功能说明
基于javaweb+mysql的SSM+Maven仓库管理系统(java+ssm+jsp+mysql+maven)
一、项目简述
功能包括: 仓库管理,出入库管理,仓库人员管理,基本信息管理, 供应商信息,系统管理等等。
二、项目运行
环境配置: Jdk1.8 + Tomcat8.5 + mysql + Eclispe (IntelliJ IDEA,Eclispe,MyEclispe,Sts 都支持)
项目技术: JSP +Spring + SpringMVC + MyBatis + html+ css + JavaScript + JQuery + Ajax + layui+ maven等等。
} else {
repositoryID = repositoryIDBelong;
}
}
if (authorizeCheck && argumentCheck) {
if (stockRecordManageService.stockOutOperation(customerID, goodsID, repositoryID, number, personInCharge))
result = Response.RESPONSE_RESULT_SUCCESS;
}
// 设置 Response
responseContent.setResponseResult(result);
return responseContent.generateResponse();
}
/**
* 货物入库操作
*
* @param supplierID 供应商ID
* @param goodsID 货物ID
* @param repositoryIDStr 仓库ID
* @param number 入库数目
* @return 返回一个map,key为result的值表示操作是否成功
*/
@RequestMapping(value = "stockIn", method = RequestMethod.POST)
public
@ResponseBody
Map<String, Object> stockIn(@RequestParam("supplierID") Integer supplierID,
@RequestParam("goodsID") Integer goodsID,
@RequestParam(value = "repositoryID", required = false) String repositoryIDStr,
@RequestParam("number") long number) throws StockRecordManageServiceException {
// 初始化 Response
Response responseContent = ResponseFactory.newInstance();
String result = Response.RESPONSE_RESULT_ERROR;
boolean authorizeCheck = true;
boolean argumentCheck = true;
Integer repositoryID = null;
// 参数检查
if (repositoryIDStr != null && repositoryIDStr.trim().length()>0) {
if (StringUtils.isNumeric(repositoryIDStr)) {
repositoryID = Integer.valueOf(repositoryIDStr);
} else {
argumentCheck = false;
responseContent.setResponseMsg("request argument error");
}
}
if (StringUtils.isBlank(repositoryID) || !StringUtils.isNumeric(repositoryID))
isAvailable = false;
if (StringUtils.isBlank(number) || !StringUtils.isNumeric(number))
isAvailable = false;
if (isAvailable) {
isSuccess = storageManageService.addNewStorage(Integer.valueOf(goodsID), Integer.valueOf(repositoryID),
Integer.valueOf(number)) ? Response.RESPONSE_RESULT_SUCCESS : Response.RESPONSE_RESULT_ERROR;
}
// 设置 Response
responseContent.setResponseResult(isSuccess);
return responseContent.generateResponse();
}
/**
* 更新库存信息
*
* @return 返回一个map,其中:key 为 result表示操作的结果,包括:success 与 error
*/
@RequestMapping(value = "updateStorageRecord", method = RequestMethod.POST)
public
@ResponseBody
Map<String, Object> updateStorageRecord(@RequestBody Map<String, Object> params) throws StorageManageServiceException {
// 初始化 Response
Response responseContent = ResponseFactory.newInstance();
boolean isAvailable = true;
String result = Response.RESPONSE_RESULT_ERROR;
String goodsID = (String) params.get("goodsID");
String repositoryID = (String) params.get("repositoryID");
String number = (String) params.get("number");
if (StringUtils.isBlank(goodsID) || !StringUtils.isNumeric(goodsID))
isAvailable = false;
if (StringUtils.isBlank(repositoryID) || !StringUtils.isNumeric(repositoryID))
isAvailable = false;
if (StringUtils.isBlank(number) || !StringUtils.isNumeric(number))
isAvailable = false;
if (isAvailable) {
result = storageManageService.updateStorage(Integer.valueOf(goodsID), Integer.valueOf(repositoryID),
public
@ResponseBody
Map<String, Object> stockIn(@RequestParam("supplierID") Integer supplierID,
@RequestParam("goodsID") Integer goodsID,
@RequestParam(value = "repositoryID", required = false) String repositoryIDStr,
@RequestParam("number") long number) throws StockRecordManageServiceException {
// 初始化 Response
Response responseContent = ResponseFactory.newInstance();
String result = Response.RESPONSE_RESULT_ERROR;
boolean authorizeCheck = true;
boolean argumentCheck = true;
Integer repositoryID = null;
// 参数检查
if (repositoryIDStr != null && repositoryIDStr.trim().length()>0) {
if (StringUtils.isNumeric(repositoryIDStr)) {
repositoryID = Integer.valueOf(repositoryIDStr);
} else {
argumentCheck = false;
responseContent.setResponseMsg("request argument error");
}
}
// 获取session中的信息
Subject currentUser = SecurityUtils.getSubject();
Session session = currentUser.getSession();
UserInfoDTO userInfo = (UserInfoDTO) session.getAttribute("userInfo");
String personInCharge = userInfo == null ? "none" : userInfo.getUserName();
Integer repositoryIDBelong = userInfo == null ? -1 : userInfo.getRepositoryBelong();
// 设置非管理员请求的仓库ID
if (!currentUser.hasRole("systemAdmin")) {
if (repositoryIDBelong < 0) {
authorizeCheck = false;
responseContent.setResponseMsg("You are not authorized");
} else {
repositoryID = repositoryIDBelong;
}
}
// 执行 Service
// 设置 Response
responseContent.setResponseResult(result);
return responseContent.generateResponse();
}
/**
* 删除指定 ID 的仓库信息
*
* @param repositoryID 仓库ID
* @return 返回一个map,其中:key 为 result 的值为操作的结果,包括:success 与 error;key 为 data
* 的值为仓库信息
*/
@RequestMapping(value = "deleteRepository", method = RequestMethod.GET)
public
@ResponseBody
Map<String, Object> deleteRepository(@RequestParam("repositoryID") Integer repositoryID) throws RepositoryManageServiceException {
// 初始化 Response
Response responseContent = ResponseFactory.newInstance();
// 删除记录
String result = repositoryService.deleteRepository(repositoryID) ? Response.RESPONSE_RESULT_SUCCESS : Response.RESPONSE_RESULT_ERROR;
// 设置 Response
responseContent.setResponseResult(result);
return responseContent.generateResponse();
}
/**
* 从文件中导入仓库信息
*
* @param file 保存有仓库信息的文件
* @return 返回一个map,其中:key 为 result表示操作的结果,包括:success 与
* error;key为total表示导入的总条数;key为available表示有效的条数
*/
@RequestMapping(value = "importRepository", method = RequestMethod.POST)
public
@ResponseBody
Map<String, Object> importRepository(MultipartFile file) throws RepositoryManageServiceException {
// 初始化 Response
Response responseContent = ResponseFactory.newInstance();
String result = Response.RESPONSE_RESULT_ERROR;
// 读取文件
int total = 0;
int available = 0;
if (file != null) {
Map<String, Object> importInfo = repositoryService.importRepository(file);
if (importInfo != null) {
total = (int) importInfo.get("total");
available = (int) importInfo.get("available");
result = Response.RESPONSE_RESULT_SUCCESS;
}
}
* @throws Exception exception
*/
@Override
protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
// 如果用户还没有登陆则继续后续的流程
Subject subject = getSubject(servletRequest, servletResponse);
if (!subject.isAuthenticated() && !subject.isRemembered())
return true;
// 判断当前用户登陆数量是否超出
Session session = subject.getSession();
String userName = (String) subject.getPrincipal();
Serializable sessionId = session.getId();
// 初始化用户的登陆队列,将用户的队列放入到缓存中
Deque<Serializable> deque = cache.get(userName);
if (deque == null) {
deque = new LinkedList<>();
cache.put(userName, deque);
}
// 如果队列中没有此用户的 sessionId 且用户没有被踢出,则放入队列
if (!deque.contains(sessionId) && session.getAttribute("kickOut") == null) {
deque.push(sessionId);
}
// 若队列中的 sessionId 是否超出最大会话数目, 则踢出用户
while (deque.size() > maxSessionNum) {
Serializable kickOutSessionId;
if (kickOutAfter) {
kickOutSessionId = deque.removeFirst();
} else {
kickOutSessionId = deque.removeLast();
}
// 设置 sessionId 对应的 session 中的字段,表示该用户已经被踢出
try {
Session kickOutSession = sessionManager.getSession(new DefaultSessionKey(kickOutSessionId));
if (kickOutSession != null) {
kickOutSession.setAttribute("kickOut", true);
}
} catch (Exception e) {
// do logging
e.printStackTrace();
}
}
// 如果当前登陆用户被踢出,则退出并跳转
if (session.getAttribute("kickOut") != null && Boolean.TRUE.equals(session.getAttribute("kickOut"))) {
try {
// 登出
subject.logout();
@RequestParam("offset") int offset,
@RequestParam("limit") int limit) throws SystemLogServiceException {
// 创建 Response
Response response = ResponseFactory.newInstance();
List<UserOperationRecordDTO> rows = null;
long total = 0;
// 检查参数
String regex = "([0-9]{4})-([0-9]{2})-([0-9]{2})";
boolean startDateFormatCheck = (StringUtils.isEmpty(startDateStr) || startDateStr.matches(regex));
boolean endDateFormatCheck = (StringUtils.isEmpty(endDateStr) || endDateStr.matches(regex));
boolean userIDCheck = (StringUtils.isEmpty(userIDStr) || StringUtils.isNumeric(userIDStr));
if (startDateFormatCheck && endDateFormatCheck && userIDCheck) {
// 转到 Service 进行查询
Integer userID = -1;
if (StringUtils.isNumeric(userIDStr))
userID = Integer.valueOf(userIDStr);
Map<String, Object> queryResult = systemLogService.selectUserOperationRecord(userID, startDateStr, endDateStr, offset, limit);
if (queryResult != null) {
rows = (List<UserOperationRecordDTO>) queryResult.get("data");
total = (long) queryResult.get("total");
}
} else
response.setResponseMsg("Request argument error");
if (rows == null)
rows = new ArrayList<>(0);
response.setCustomerInfo("rows", rows);
response.setResponseTotal(total);
return response.generateResponse();
}
}
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
if (!"XMLHttpRequest".equalsIgnoreCase(httpServletRequest.getHeader("X-Requested-with"))) {
// 普通请求
WebUtils.issueRedirect(httpServletRequest, httpServletResponse, kickOutUrl);
} else {
// ajax 请求
httpServletResponse.setStatus(430);
}
} catch (Exception e) {
// do nothing
}
return false;
}
return true;
}
}
/**
* 扩展 FormAuthenticationFilter ,对部分方法重写,使其支持 Ajax 请求
*
*/
public class ExtendFormAuthenticationFilter extends FormAuthenticationFilter {
private static final Logger log = LoggerFactory.getLogger(FormAuthenticationFilter.class);
* 删除一条库存信息
*
* @param goodsID 货物ID
* @param repositoryID 仓库ID
* @return 返回一个map,其中:key 为 result表示操作的结果,包括:success 与 error
*/
@RequestMapping(value = "deleteStorageRecord", method = RequestMethod.GET)
public
@ResponseBody
Map<String, Object> deleteStorageRecord(@RequestParam("goodsID") String goodsID,
@RequestParam("repositoryID") String repositoryID) throws StorageManageServiceException {
// 初始化 Response
Response responseContent = ResponseFactory.newInstance();
String result = Response.RESPONSE_RESULT_ERROR;
boolean isAvailable = true;
if (StringUtils.isBlank(goodsID) || !StringUtils.isNumeric(goodsID))
isAvailable = false;
if (StringUtils.isBlank(repositoryID) || !StringUtils.isNumeric(repositoryID))
isAvailable = false;
if (isAvailable) {
result = storageManageService.deleteStorage(Integer.valueOf(goodsID), Integer.valueOf(repositoryID))
? Response.RESPONSE_RESULT_SUCCESS : Response.RESPONSE_RESULT_ERROR;
}
// 设置 Response
responseContent.setResponseResult(result);
return responseContent.generateResponse();
}
/**
* 导入库存信息
*
* @param file 保存有库存信息的文件
* @return 返回一个map,其中:key 为 result表示操作的结果,包括:success 与
* error;key为total表示导入的总条数;key为available表示有效的条数
*/
@RequestMapping(value = "importStorageRecord", method = RequestMethod.POST)
public
@ResponseBody
Map<String, Object> importStorageRecord(@RequestParam("file") MultipartFile file) throws StorageManageServiceException {
// 初始化 Response
Response responseContent = ResponseFactory.newInstance();
String result = Response.RESPONSE_RESULT_ERROR;
int total = 0;
int available = 0;
return responseContent.generateResponse();
}
/**
* 导出仓库信息到文件中
*
* @param searchType 查询类型
* @param keyWord 查询关键字
* @param response HttpServletResponse
*/
@SuppressWarnings("unchecked")
@RequestMapping(value = "exportRepository", method = RequestMethod.GET)
public void exportRepository(@RequestParam("searchType") String searchType, @RequestParam("keyWord") String keyWord,
HttpServletResponse response) throws RepositoryManageServiceException, IOException {
// 导出文件名
String fileName = "repositoryInfo.xlsx";
// 查询
List<Repository> repositories;
Map<String, Object> queryResult = query(searchType, keyWord, -1, -1);
if (queryResult != null)
repositories = (List<Repository>) queryResult.get("data");
else
repositories = new ArrayList<>();
// 生成文件
File file = repositoryService.exportRepository(repositories);
// 输出文件
if (file != null) {
// 设置响应头
response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
FileInputStream inputStream = new FileInputStream(file);
OutputStream outputStream = response.getOutputStream();
byte[] buffer = new byte[8192];
int len;
while ((len = inputStream.read(buffer, 0, buffer.length)) > 0) {
outputStream.write(buffer, 0, len);
outputStream.flush();
}
inputStream.close();
outputStream.close();
}
}
}
/**
* 扩展 FormAuthenticationFilter ,对部分方法重写,使其支持 Ajax 请求
*
*/
public class ExtendFormAuthenticationFilter extends FormAuthenticationFilter {
private static final Logger log = LoggerFactory.getLogger(FormAuthenticationFilter.class);
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception{
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
if (!"XMLHttpRequest".equalsIgnoreCase(httpServletRequest.getHeader("X-Requested-with"))){
// 请求为普通请求
if(this.isLoginRequest(request, response)) {
if(this.isLoginSubmission(request, response)) {
if(log.isTraceEnabled()) {
log.trace("Login submission detected. Attempting to execute login.");
}
return this.executeLogin(request, response);
} else {
if(log.isTraceEnabled()) {
log.trace("Login page view.");
}
return true;
}
} else {
if(log.isTraceEnabled()) {
log.trace("Attempting to access a path which requires authentication. Forwarding to the Authentication url [" + this.getLoginUrl() + "]");
}
this.saveRequestAndRedirectToLogin(request, response);
return false;
}
}else{
default:
// do other thing
break;
}
return queryResult;
}
/**
* 可指定仓库对库存信息查询
*
* @param keyword 查询关键字
* @param searchType 查询类型
* @param repositoryBelong 查询所属的仓库
* @param offset 分页偏移值
* @param limit 分页大小
* @return 结果的一个Map,其中: key为 rows 的代表记录数据;key 为 total 代表结果记录的数量
*/
@SuppressWarnings("unchecked")
@RequestMapping(value = "getStorageListWithRepository", method = RequestMethod.GET)
public
@ResponseBody
Map<String, Object> getStorageListWithRepoID(@RequestParam("keyword") String keyword,
@RequestParam("searchType") String searchType, @RequestParam("repositoryBelong") String repositoryBelong,
@RequestParam("offset") int offset, @RequestParam("limit") int limit) throws StorageManageServiceException {
// 初始化 Response
Response responseContent = ResponseFactory.newInstance();
List<Storage> rows;
long total = 0;
// query
Map<String, Object> queryResult = query(searchType, keyword, repositoryBelong, offset, limit);
if (queryResult != null) {
rows = (List<Storage>) queryResult.get("data");
total = (long) queryResult.get("total");
} else
rows = new ArrayList<>();
// 设置 Response
responseContent.setCustomerInfo("rows", rows);
responseContent.setResponseTotal(total);
return responseContent.generateResponse();
}
/**
* 查询库存信息,查询所属的仓库为session保存的信息
*
* @param keyword 查询关键字
* @param searchType 查询类型
* @param offset 分页偏移值
* @param limit 分页大小
* @param request 请求
}
}
}
/**
* 用户账户请求 Handler
*
* @since 017/2/26.
*/
HttpServletRequest request, HttpServletResponse response) throws StorageManageServiceException, IOException {
String fileName = "storageRecord.xlsx";
HttpSession session = request.getSession();
UserInfoDTO userInfo = (UserInfoDTO) session.getAttribute("userInfo");
Integer sessionRepositoryBelong = userInfo.getRepositoryBelong();
if (sessionRepositoryBelong > 0)
repositoryBelong = sessionRepositoryBelong.toString();
List<Storage> storageList = null;
Map<String, Object> queryResult = query(searchType, keyword, repositoryBelong, -1, -1);
if (queryResult != null)
storageList = (List<Storage>) queryResult.get("data");
File file = storageManageService.exportStorage(storageList);
if (file != null) {
// 设置响应头
response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
FileInputStream inputStream = new FileInputStream(file);
OutputStream outputStream = response.getOutputStream();
byte[] buffer = new byte[8192];
int len;
while ((len = inputStream.read(buffer, 0, buffer.length)) > 0) {
outputStream.write(buffer, 0, len);
outputStream.flush();
}
inputStream.close();
outputStream.close();
}
}
}
}
/**
* 处理文件下载请求
*
*/
@Controller
@RequestMapping("/commons/fileSource")
public class FileSourceHandler {
@RequestMapping(value = "download/{fileName:.+}", method = RequestMethod.GET)
public void fileDownload(@PathVariable("fileName") String fileName, HttpServletRequest request,
HttpServletResponse response) throws IOException {
if (fileName == null)
return;
// 获取文件
ServletContext context = request.getServletContext();
String directory = context.getRealPath("/WEB-INF/download");
Path file = Paths.get(directory, fileName);
if (Files.exists(file)) {
// 设置响应头
response.addHeader("Content-Disposition", "attachment;filename=" + file.getFileName());
Files.copy(file, response.getOutputStream());
response.getOutputStream().flush();
}
}
}
/**
* 全局异常处理器
}
/**
* 导出客户信息
*
* @param searchType 查找类型
* @param keyWord 查找关键字
* @param response HttpServletResponse
*/
@SuppressWarnings("unchecked")
@RequestMapping(value = "exportCustomer", method = RequestMethod.GET)
public void exportCustomer(@RequestParam("searchType") String searchType, @RequestParam("keyWord") String keyWord,
HttpServletResponse response) throws CustomerManageServiceException, IOException {
String fileName = "customerInfo.xlsx";
List<Customer> customers = null;
Map<String, Object> queryResult = query(searchType, keyWord, -1, -1);
if (queryResult != null) {
customers = (List<Customer>) queryResult.get("data");
}
// 获取生成的文件
File file = customerManageService.exportCustomer(customers);
// 写出文件
if (file != null) {
// 设置响应头
response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
FileInputStream inputStream = new FileInputStream(file);
OutputStream outputStream = response.getOutputStream();
byte[] buffer = new byte[8192];
int len;
while ((len = inputStream.read(buffer, 0, buffer.length)) > 0) {
outputStream.write(buffer, 0, len);
outputStream.flush();
}
inputStream.close();
outputStream.close();
}
}
}
}
}
} else {
errorMsg = "already login";
}
// 设置 Response
response.setResponseResult(result);
response.setResponseMsg(errorMsg);
return response.generateResponse();
}
/**
* 注销账户
*
* @return 返回一个 Map 对象,键值为 result 的内容代表注销操作的结果,值为 success 或 error
*/
@RequestMapping(value = "logout", method = RequestMethod.GET)
public
@ResponseBody
Map<String, Object> logout() {
// 初始化 Response
Response response = ResponseFactory.newInstance();
Subject currentSubject = SecurityUtils.getSubject();
if (currentSubject != null && currentSubject.isAuthenticated()) {
// 执行账户注销操作
currentSubject.logout();
response.setResponseResult(Response.RESPONSE_RESULT_SUCCESS);
} else {
response.setResponseResult(Response.RESPONSE_RESULT_ERROR);
response.setResponseMsg("did not login");
}
return response.generateResponse();
}
/**
* 修改账户密码
*
* @param passwordInfo 密码信息
* @param request 请求
* @return 返回一个 Map 对象,其中键值为 result 代表修改密码操作的结果,
* 值为 success 或 error;键值为 msg 代表需要返回给用户的信息
*/
@RequestMapping(value = "passwordModify", method = RequestMethod.POST)
public
@ResponseBody
Map<String, Object> passwordModify(@RequestBody Map<String, Object> passwordInfo,
/**
* 用户账户请求 Handler
*
* @since 017/2/26.
*/
@Controller
@RequestMapping("/account")
public class AccountHandler {
private static Logger log = Logger.getLogger("application");
@Autowired
private AccountService accountService;
@Autowired
private SystemLogService systemLogService;
@Autowired
private RepositoryAdminManageService repositoryAdminManageService;
private static final String USER_ID = "id";
private static final String USER_NAME = "userName";
private static final String USER_PASSWORD = "password";
/**
* 登陆账户
*
* @param user 账户信息
* @return 返回一个 Map 对象,其中包含登陆操作的结果
*/
@RequestMapping(value = "login", method = RequestMethod.POST)
@ResponseBody
public Map<String, Object> login(@RequestBody Map<String, Object> user) {
// 初始化 Response
Response response = ResponseFactory.newInstance();
String result = Response.RESPONSE_RESULT_ERROR;
String errorMsg = "";
// 获取当前的用户的 Subject
Subject currentUser = SecurityUtils.getSubject();