diff --git a/pom.xml b/pom.xml index 3d4b569..0c5eae2 100644 --- a/pom.xml +++ b/pom.xml @@ -21,6 +21,7 @@ 1.2.3 1.1.2 1.3.2 + 2.4 3.4 1.10 2.4 @@ -162,6 +163,13 @@ ${shiro.version} + + + joda-time + joda-time + ${joda-time.version} + + org.apache.commons diff --git a/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/controller/AdminController.java b/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/controller/AdminController.java index 73b2e83..03328bf 100644 --- a/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/controller/AdminController.java +++ b/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/controller/AdminController.java @@ -1,5 +1,6 @@ package com.certusnet.xproject.admin.web.controller; +import static com.certusnet.xproject.common.consts.ContentType.APPLICATION_JSON; import static org.springframework.web.bind.annotation.RequestMethod.GET; import static org.springframework.web.bind.annotation.RequestMethod.POST; @@ -41,6 +42,7 @@ import com.certusnet.xproject.admin.web.shiro.realm.AdminUserRealm; import com.certusnet.xproject.common.consts.GlobalConstants; import com.certusnet.xproject.common.support.AbstractXTreeBuilder; +import com.certusnet.xproject.common.support.HttpAccessLogging; import com.certusnet.xproject.common.support.Result; import com.certusnet.xproject.common.support.TreeNodeConverter; import com.certusnet.xproject.common.util.DateTimeUtils; @@ -79,8 +81,16 @@ public String login(HttpServletRequest request, HttpServletResponse response) { return "login.html"; } + /** + * 用户登录 + * @param request + * @param response + * @param loginUser + * @return + */ @ResponseBody - @RequestMapping(value="/login/submit", method=POST) + @RequestMapping(value="/login/submit", method=POST, consumes=APPLICATION_JSON, produces=APPLICATION_JSON) + @HttpAccessLogging(title="用户登录", isLogin=true, excludeParamNames={"password"}) public Object submitLogin(HttpServletRequest request, HttpServletResponse response, @RequestBody AdminUser loginUser) { logger.info(">>> 执行用户登录, loginUser = " + loginUser.getUserName()); Result result = new Result(); @@ -171,7 +181,7 @@ public String index(HttpServletRequest request, HttpServletResponse response) { * @return */ @ResponseBody - @RequestMapping(value="/login/user/current") + @RequestMapping(value="/login/user/current", method=GET, produces=APPLICATION_JSON) public Object getLoginUserInfo(HttpServletRequest request, HttpServletResponse response) { LoginToken loginToken = (LoginToken) ShiroUtils.getSessionAttribute(LoginToken.LOGIN_TOKEN_SESSION_KEY); Map user = new HashMap(); @@ -192,7 +202,7 @@ public Object getLoginUserInfo(HttpServletRequest request, HttpServletResponse r * @return */ @ResponseBody - @RequestMapping(value="/login/user/menus") + @RequestMapping(value="/login/user/menus", method=GET, produces=APPLICATION_JSON) public Object getLoginUserMenuList(HttpServletRequest request, HttpServletResponse response) { List> dataList = new ArrayList>(); try { @@ -223,7 +233,7 @@ public Object getLoginUserMenuList(HttpServletRequest request, HttpServletRespon * @param response * @return */ - @RequestMapping(value="/logout") + @RequestMapping(value="/logout", method=GET) public String logout(HttpServletRequest request, HttpServletResponse response) { logger.info(">>> 用户退出系统"); if (SecurityUtils.getSubject().getSession() != null) { diff --git a/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/controller/AdminResourceMgtController.java b/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/controller/AdminResourceMgtController.java index 789efb2..d978f66 100644 --- a/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/controller/AdminResourceMgtController.java +++ b/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/controller/AdminResourceMgtController.java @@ -1,5 +1,7 @@ package com.certusnet.xproject.admin.web.controller; +import static com.certusnet.xproject.common.consts.ContentType.APPLICATION_JSON; +import static org.springframework.web.bind.annotation.RequestMethod.GET; import static org.springframework.web.bind.annotation.RequestMethod.POST; import java.util.List; @@ -50,7 +52,7 @@ public class AdminResourceMgtController extends BaseController { * @param response * @return */ - @RequestMapping(value="/admin/resource/available") + @RequestMapping(value="/admin/resource/available", method=GET, produces=APPLICATION_JSON) public Object getAvailableResources(HttpServletRequest request, HttpServletResponse response) { List allResourceList = adminResourceService.getAllResourceList(null); List> dataList = resourceTreeBuilder.buildObjectTree(GlobalConstants.DEFAULT_ADMIN_ROOT_RESOURCE_ID, allResourceList, resourceTreeNodeConverter); @@ -64,7 +66,7 @@ public Object getAvailableResources(HttpServletRequest request, HttpServletRespo * @param resourceAddForm * @return */ - @RequestMapping(value="/admin/resource/add/submit", method=POST) + @RequestMapping(value="/admin/resource/add/submit", method=POST, consumes=APPLICATION_JSON, produces=APPLICATION_JSON) public Object addResource(HttpServletRequest request, HttpServletResponse response, @RequestBody AdminResource resourceAddForm) { LoginToken loginToken = ShiroUtils.getSessionAttribute(LoginToken.LOGIN_TOKEN_SESSION_KEY); resourceAddForm.setCreateTime(DateTimeUtils.formatNow()); @@ -81,7 +83,7 @@ public Object addResource(HttpServletRequest request, HttpServletResponse respon * @param resourceEditForm * @return */ - @RequestMapping(value="/admin/resource/edit/submit", method=POST) + @RequestMapping(value="/admin/resource/edit/submit", method=POST, consumes=APPLICATION_JSON, produces=APPLICATION_JSON) public Object editResource(HttpServletRequest request, HttpServletResponse response, @RequestBody AdminResource resourceEditForm) { LoginToken loginToken = ShiroUtils.getSessionAttribute(LoginToken.LOGIN_TOKEN_SESSION_KEY); resourceEditForm.setUpdateTime(DateTimeUtils.formatNow()); @@ -97,7 +99,7 @@ public Object editResource(HttpServletRequest request, HttpServletResponse respo * @param id * @return */ - @RequestMapping(value="/admin/resource/del") + @RequestMapping(value="/admin/resource/del", method=GET, produces=APPLICATION_JSON) public Object delResource(HttpServletRequest request, HttpServletResponse response, Long id) { adminResourceService.deleteResourceById(id, true); return genSuccessResult("删除成功!", null); diff --git a/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/controller/AdminRoleMgtController.java b/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/controller/AdminRoleMgtController.java index 13ff46e..2504f7d 100644 --- a/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/controller/AdminRoleMgtController.java +++ b/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/controller/AdminRoleMgtController.java @@ -1,5 +1,7 @@ package com.certusnet.xproject.admin.web.controller; +import static com.certusnet.xproject.common.consts.ContentType.APPLICATION_JSON; +import static org.springframework.web.bind.annotation.RequestMethod.GET; import static org.springframework.web.bind.annotation.RequestMethod.POST; import java.util.ArrayList; @@ -66,7 +68,7 @@ public class AdminRoleMgtController extends BaseController { * @param pager * @return */ - @RequestMapping(value="/admin/role/list") + @RequestMapping(value="/admin/role/list", method=GET, produces=APPLICATION_JSON) public Object listRole(HttpServletRequest request, HttpServletResponse response, AdminRole roleQueryForm, OrderBy orderBy, Pager pager) { PagingList roleList = adminRoleService.getRoleList(roleQueryForm, pager, orderBy); return genSuccessPagingResult(roleList); @@ -79,7 +81,7 @@ public Object listRole(HttpServletRequest request, HttpServletResponse response, * @param roleAddForm * @return */ - @RequestMapping(value="/admin/role/add/submit", method=POST) + @RequestMapping(value="/admin/role/add/submit", method=POST, consumes=APPLICATION_JSON, produces=APPLICATION_JSON) public Object addRole(HttpServletRequest request, HttpServletResponse response, @RequestBody AdminRole roleAddForm) { LoginToken loginToken = ShiroUtils.getSessionAttribute(LoginToken.LOGIN_TOKEN_SESSION_KEY); roleAddForm.setCreateTime(DateTimeUtils.formatNow()); @@ -96,7 +98,7 @@ public Object addRole(HttpServletRequest request, HttpServletResponse response, * @param roleEditForm * @return */ - @RequestMapping(value="/admin/role/edit/submit", method=POST) + @RequestMapping(value="/admin/role/edit/submit", method=POST, consumes=APPLICATION_JSON, produces=APPLICATION_JSON) public Object editRole(HttpServletRequest request, HttpServletResponse response, @RequestBody AdminRole roleEditForm) { LoginToken loginToken = ShiroUtils.getSessionAttribute(LoginToken.LOGIN_TOKEN_SESSION_KEY); roleEditForm.setUpdateTime(DateTimeUtils.formatNow()); @@ -112,7 +114,7 @@ public Object editRole(HttpServletRequest request, HttpServletResponse response, * @param id * @return */ - @RequestMapping(value="/admin/role/del") + @RequestMapping(value="/admin/role/del", method=GET, produces=APPLICATION_JSON) public Object delRole(HttpServletRequest request, HttpServletResponse response, Long id) { adminRoleService.deleteRoleById(id); return genSuccessResult("删除成功!", null); @@ -126,7 +128,7 @@ public Object delRole(HttpServletRequest request, HttpServletResponse response, * @return * @throws Exception */ - @RequestMapping(value="/admin/role/resources") + @RequestMapping(value="/admin/role/resources", method=GET, produces=APPLICATION_JSON) public Object loadRoleResources(HttpServletRequest request, HttpServletResponse response, Long roleId) throws Exception { List allResourceList = adminResourceService.getAllResourceList(null); List roleResourceList = adminRoleService.getResourceListByRoleId(roleId); @@ -150,7 +152,7 @@ public Object loadRoleResources(HttpServletRequest request, HttpServletResponse * @param parameter * @return */ - @RequestMapping(value="/admin/role/config/submit", method=POST) + @RequestMapping(value="/admin/role/config/submit", method=POST, consumes=APPLICATION_JSON, produces=APPLICATION_JSON) public Object configRoleResources(HttpServletRequest request, HttpServletResponse response, @RequestBody Map parameter) { List resourceIdList = new ArrayList(); String resourceIds = MapUtils.getString(parameter, "resourceIds"); diff --git a/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/controller/AdminUserMgtController.java b/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/controller/AdminUserMgtController.java index af7deef..72e5dfa 100644 --- a/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/controller/AdminUserMgtController.java +++ b/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/controller/AdminUserMgtController.java @@ -1,5 +1,7 @@ package com.certusnet.xproject.admin.web.controller; +import static com.certusnet.xproject.common.consts.ContentType.APPLICATION_JSON; +import static org.springframework.web.bind.annotation.RequestMethod.GET; import static org.springframework.web.bind.annotation.RequestMethod.POST; import java.util.ArrayList; @@ -63,7 +65,7 @@ public class AdminUserMgtController extends BaseController { * @param pager * @return */ - @RequestMapping(value="/admin/user/list") + @RequestMapping(value="/admin/user/list", method=GET, produces=APPLICATION_JSON) public Object listRole(HttpServletRequest request, HttpServletResponse response, AdminUser userQueryForm, OrderBy orderBy, Pager pager) { PagingList dataList = adminUserService.getUserList(userQueryForm, pager, orderBy); return genSuccessPagingResult(dataList); @@ -76,7 +78,7 @@ public Object listRole(HttpServletRequest request, HttpServletResponse response, * @param userAddForm * @return */ - @RequestMapping(value="/admin/user/add/submit", method=POST) + @RequestMapping(value="/admin/user/add/submit", method=POST, consumes=APPLICATION_JSON, produces=APPLICATION_JSON) public Object addUser(HttpServletRequest request, HttpServletResponse response, @RequestBody AdminUser userAddForm) throws Exception { LoginToken loginToken = ShiroUtils.getSessionAttribute(LoginToken.LOGIN_TOKEN_SESSION_KEY); userAddForm.setCreateTime(DateTimeUtils.formatNow()); @@ -108,7 +110,7 @@ public Object addUser(HttpServletRequest request, HttpServletResponse response, * @param modelMap * @return */ - @RequestMapping(value="/admin/user/edit/submit", method=POST) + @RequestMapping(value="/admin/user/edit/submit", method=POST, consumes=APPLICATION_JSON, produces=APPLICATION_JSON) public Object editUser(HttpServletRequest request, HttpServletResponse response, @RequestBody AdminUser userEditForm) throws Exception { LoginToken loginToken = ShiroUtils.getSessionAttribute(LoginToken.LOGIN_TOKEN_SESSION_KEY); userEditForm.setUpdateBy(loginToken.getLoginId()); @@ -137,7 +139,7 @@ public Object editUser(HttpServletRequest request, HttpServletResponse response, * @param id * @return */ - @RequestMapping(value="/admin/user/del") + @RequestMapping(value="/admin/user/del", method=GET, produces=APPLICATION_JSON) public Object delUser(HttpServletRequest request, HttpServletResponse response, Long id) { AdminUser user = new AdminUser(); user.setUserId(id); @@ -152,7 +154,7 @@ public Object delUser(HttpServletRequest request, HttpServletResponse response, * @param passwdEditForm * @return */ - @RequestMapping(value="/admin/user/changepwd/submit", method=POST) + @RequestMapping(value="/admin/user/changepwd/submit", method=POST, consumes=APPLICATION_JSON, produces=APPLICATION_JSON) public Object changeUserPasswd(HttpServletRequest request, HttpServletResponse response, @RequestBody AdminUser passwdEditForm, Boolean forceUpdate) { if(forceUpdate == null){ forceUpdate = false; @@ -168,7 +170,7 @@ public Object changeUserPasswd(HttpServletRequest request, HttpServletResponse r * @param userId * @return */ - @RequestMapping(value="/admin/user/enable") + @RequestMapping(value="/admin/user/enable", method=GET, produces=APPLICATION_JSON) public Object enableUser(HttpServletRequest request, HttpServletResponse response, Long userId) { return updateUserStatus(request, response, userId, AdminUserStatusEnum.ADMIN_USER_STATUS_ENABLED); } @@ -180,7 +182,7 @@ public Object enableUser(HttpServletRequest request, HttpServletResponse respons * @param userId * @return */ - @RequestMapping(value="/admin/user/disable") + @RequestMapping(value="/admin/user/disable", method=GET, produces=APPLICATION_JSON) public Object disableUser(HttpServletRequest request, HttpServletResponse response, Long userId) { return updateUserStatus(request, response, userId, AdminUserStatusEnum.ADMIN_USER_STATUS_DISABLED); } @@ -200,7 +202,7 @@ protected Result updateUserStatus(HttpServletRequest request, HttpServle * @param userId * @return */ - @RequestMapping(value="/admin/user/roles") + @RequestMapping(value="/admin/user/roles", method=GET, produces=APPLICATION_JSON) public Object loadUserRoles(HttpServletRequest request, HttpServletResponse response, Long userId, AdminRole filterParam) { List roleList = adminUserService.getUserRoleList(userId, filterParam); return genSuccessResult(roleList); @@ -214,7 +216,7 @@ public Object loadUserRoles(HttpServletRequest request, HttpServletResponse resp * @param roleIds * @return */ - @RequestMapping(value="/admin/user/config/add", method=POST) + @RequestMapping(value="/admin/user/config/add", method=POST, consumes=APPLICATION_JSON, produces=APPLICATION_JSON) public Object addUserRoles(HttpServletRequest request, HttpServletResponse response, @RequestBody Map parameter) { Long userId = MapUtils.getLong(parameter, "userId"); String roleIds = MapUtils.getString(parameter, "roleIds"); @@ -243,7 +245,7 @@ public Object addUserRoles(HttpServletRequest request, HttpServletResponse respo * @param roleIds * @return */ - @RequestMapping(value="/admin/user/config/del", method=POST) + @RequestMapping(value="/admin/user/config/del", method=POST, consumes=APPLICATION_JSON, produces=APPLICATION_JSON) public Object delUserRoles(HttpServletRequest request, HttpServletResponse response, @RequestBody Map parameter) { Long userId = MapUtils.getLong(parameter, "userId"); String roleIds = MapUtils.getString(parameter, "roleIds"); @@ -271,7 +273,7 @@ public Object delUserRoles(HttpServletRequest request, HttpServletResponse respo * @param orderBy * @return */ - @RequestMapping("/admin/user/search") + @RequestMapping(value="/admin/user/search", method=GET, produces=APPLICATION_JSON) public Object searchUsers(HttpServletRequest request, HttpServletResponse response, AdminUser userSearchForm, Pager pager, OrderBy orderBy) { userSearchForm.setStatus(AdminUserStatusEnum.ADMIN_USER_STATUS_ENABLED.getStatusCode()); PagingList dataList = adminUserService.getUserList(userSearchForm, pager, orderBy); diff --git a/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/interceptor/DbStoreHttpAccessLogHandler.java b/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/interceptor/DbStoreHttpAccessLogHandler.java new file mode 100644 index 0000000..f32832c --- /dev/null +++ b/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/interceptor/DbStoreHttpAccessLogHandler.java @@ -0,0 +1,57 @@ +package com.certusnet.xproject.admin.web.interceptor; + +import org.springframework.http.MediaType; + +import com.certusnet.xproject.admin.model.AdminUser; +import com.certusnet.xproject.admin.model.AdminUserAccessLog; +import com.certusnet.xproject.admin.service.AdminUserAccessLogService; +import com.certusnet.xproject.common.support.HttpAccessLogging.LoggingType; +import com.certusnet.xproject.common.util.CollectionUtils; +import com.certusnet.xproject.common.util.DateTimeUtils; +import com.certusnet.xproject.common.util.JsonUtils; +import com.certusnet.xproject.common.util.SpringUtils; +import com.certusnet.xproject.common.web.springmvc.interceptor.AbstractHttpAccessLogHandler; +import com.certusnet.xproject.common.web.springmvc.interceptor.HttpAccessLog; + +public class DbStoreHttpAccessLogHandler extends AbstractHttpAccessLogHandler { + + private final AdminUserAccessLogService adminUserAccessLogService; + + public DbStoreHttpAccessLogHandler(HttpAccessLog httpAccessLog) { + super(httpAccessLog); + this.adminUserAccessLogService = SpringUtils.getBean(AdminUserAccessLogService.class); + } + + public LoggingType getLoggingType() { + return LoggingType.DB; + } + + public void handleLogger(HttpAccessLog httpAccessLog) throws Exception { + AdminUserAccessLog accessLog = new AdminUserAccessLog(); + accessLog.setTitle(httpAccessLog.getTitle()); + accessLog.setUri(httpAccessLog.getUri()); + accessLog.setMethod(httpAccessLog.getMethod()); + accessLog.setRequestHeader(CollectionUtils.isEmpty(httpAccessLog.getRequestHeader()) ? null : JsonUtils.object2Json(httpAccessLog.getRequestHeader())); + accessLog.setRequestContentType(httpAccessLog.getRequestContentType() == null ? null : httpAccessLog.getRequestContentType().toString()); + accessLog.setRequestParameter(JsonUtils.object2Json(httpAccessLog.getRequestParameter())); + accessLog.setAccessUserId(httpAccessLog.getAccessUser().getUserId()); + accessLog.setAccessTime(httpAccessLog.getAccessTime()); + accessLog.setClientIpAddr(httpAccessLog.getClientIpAddr()); + accessLog.setServerIpAddr(httpAccessLog.getServerIpAddr()); + accessLog.setProcessTime1(httpAccessLog.getProcessTime1()); + accessLog.setProcessTime2(httpAccessLog.getProcessTime2()); + accessLog.setLoggingCompleted(httpAccessLog.isLoggingCompleted()); + accessLog.setAsynRequest(httpAccessLog.isAsynRequest()); + accessLog.setResponseContentType(httpAccessLog.getResponseContentType() == null ? null : httpAccessLog.getResponseContentType().toString()); + if(httpAccessLog.getResponseResult() != null){ + if(httpAccessLog.getResponseResult() instanceof String){ + accessLog.setResponseResult(httpAccessLog.getResponseResult().toString()); + }else if(httpAccessLog.getResponseContentType() != null && MediaType.APPLICATION_JSON_UTF8.getType().equals(httpAccessLog.getResponseContentType().getType())){ + accessLog.setResponseResult(JsonUtils.object2Json(httpAccessLog.getResponseResult())); + } + } + accessLog.setCreateTime(DateTimeUtils.formatNow()); + adminUserAccessLogService.recordUserAccessLog(accessLog); + } + +} diff --git a/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/interceptor/DefaultHttpAccessLoggingInterceptor.java b/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/interceptor/DefaultHttpAccessLoggingInterceptor.java new file mode 100644 index 0000000..ca77bb0 --- /dev/null +++ b/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/interceptor/DefaultHttpAccessLoggingInterceptor.java @@ -0,0 +1,64 @@ +package com.certusnet.xproject.admin.web.interceptor; + +import java.util.Map; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.collections.MapUtils; +import org.springframework.core.MethodParameter; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.method.HandlerMethod; + +import com.certusnet.xproject.admin.model.AdminUser; +import com.certusnet.xproject.admin.service.AdminUserService; +import com.certusnet.xproject.admin.web.LoginToken; +import com.certusnet.xproject.common.support.HttpAccessLogging.LoggingType; +import com.certusnet.xproject.common.web.shiro.ShiroUtils; +import com.certusnet.xproject.common.web.springmvc.interceptor.AbstractHttpAccessLogHandler; +import com.certusnet.xproject.common.web.springmvc.interceptor.AbstractHttpAccessLoggingInterceptor; +import com.certusnet.xproject.common.web.springmvc.interceptor.HttpAccessLog; +import com.certusnet.xproject.common.web.springmvc.interceptor.HttpAccessLog.HttpRequestParameter; + +@SuppressWarnings("unchecked") +public class DefaultHttpAccessLoggingInterceptor extends AbstractHttpAccessLoggingInterceptor { + + @Resource(name="adminUserService") + private AdminUserService adminUserService; + + protected AdminUser getAccessUser(HttpServletRequest request, LoggingContext loggingContext) { + if(loggingContext.getHttpAccessLogging().isLogin()){ //用户正在登录 + HandlerMethod handlerMethod = loggingContext.getHandlerMethod(); + MethodParameter[] methodParameters = handlerMethod.getMethodParameters(); + if(methodParameters != null){ + for(MethodParameter methodParameter : methodParameters){ + if(methodParameter.hasParameterAnnotation(RequestBody.class) && AdminUser.class.equals(methodParameter.getParameterType())){ + HttpRequestParameter requestParameter = loggingContext.getHttpAccessLog().getRequestParameter(); + Object requestBody = requestParameter.getBody(); + MediaType contentType = loggingContext.getHttpAccessLog().getRequestContentType(); + if (contentType != null && requestBody != null && requestBody instanceof Map && MediaType.APPLICATION_JSON.getType().equals(contentType.getType())) { + Map requestBodyMap = (Map) requestBody; + return adminUserService.getUserByUserName(MapUtils.getString(requestBodyMap, "userName"), false); + } + } + } + } + return null; + }else{ //用户已登录 + LoginToken loginToken = (LoginToken) ShiroUtils.getSessionAttribute(LoginToken.LOGIN_TOKEN_SESSION_KEY); + return loginToken == null ? null : loginToken.getLoginUser(); + } + } + + protected AbstractHttpAccessLogHandler createHttpAccessLoggerHandler(LoggingContext loggingContext) { + LoggingType loggingType = loggingContext.getHttpAccessLogging().loggingType(); + if(LoggingType.DB.equals(loggingType)){ + return new DbStoreHttpAccessLogHandler((HttpAccessLog) loggingContext.getHttpAccessLog()); + }else if(LoggingType.FILE.equals(loggingType)){ + return new FileStoreHttpAccessLogHandler((HttpAccessLog) loggingContext.getHttpAccessLog()); + } + return null; + } + +} diff --git a/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/interceptor/FileStoreHttpAccessLogHandler.java b/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/interceptor/FileStoreHttpAccessLogHandler.java new file mode 100644 index 0000000..1fdd7a7 --- /dev/null +++ b/xproject-admin/src/main/java/com/certusnet/xproject/admin/web/interceptor/FileStoreHttpAccessLogHandler.java @@ -0,0 +1,46 @@ +package com.certusnet.xproject.admin.web.interceptor; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.certusnet.xproject.admin.model.AdminUser; +import com.certusnet.xproject.admin.model.AdminUserAccessLog; +import com.certusnet.xproject.common.support.HttpAccessLogging.LoggingType; +import com.certusnet.xproject.common.util.CollectionUtils; +import com.certusnet.xproject.common.util.DateTimeUtils; +import com.certusnet.xproject.common.util.JsonUtils; +import com.certusnet.xproject.common.web.springmvc.interceptor.AbstractHttpAccessLogHandler; +import com.certusnet.xproject.common.web.springmvc.interceptor.HttpAccessLog; + +public class FileStoreHttpAccessLogHandler extends AbstractHttpAccessLogHandler { + + private static final Logger logger = LoggerFactory.getLogger(FileStoreHttpAccessLogHandler.class); + + public FileStoreHttpAccessLogHandler(HttpAccessLog httpAccessLog) { + super(httpAccessLog); + } + + public LoggingType getLoggingType() { + return LoggingType.DB; + } + + public void handleLogger(HttpAccessLog httpAccessLog) throws Exception { + AdminUserAccessLog accessLog = new AdminUserAccessLog(); + accessLog.setTitle(httpAccessLog.getTitle()); + accessLog.setUri(httpAccessLog.getUri()); + accessLog.setMethod(httpAccessLog.getMethod()); + accessLog.setRequestHeader(CollectionUtils.isEmpty(httpAccessLog.getRequestHeader()) ? null : JsonUtils.object2Json(httpAccessLog.getRequestHeader())); + accessLog.setRequestParameter(JsonUtils.object2Json(httpAccessLog.getRequestParameter())); + accessLog.setAccessUserId(httpAccessLog.getAccessUser().getUserId()); + accessLog.setAccessTime(httpAccessLog.getAccessTime()); + accessLog.setClientIpAddr(httpAccessLog.getClientIpAddr()); + accessLog.setServerIpAddr(httpAccessLog.getServerIpAddr()); + accessLog.setProcessTime1(httpAccessLog.getProcessTime1()); + accessLog.setProcessTime2(httpAccessLog.getProcessTime2()); + accessLog.setLoggingCompleted(httpAccessLog.isLoggingCompleted()); + accessLog.setAsynRequest(httpAccessLog.isAsynRequest()); + accessLog.setCreateTime(DateTimeUtils.formatNow()); + logger.info("【用户操作日志】>>> " + accessLog); + } + +} diff --git a/xproject-admin/src/main/resources/spring/spring-mvc.xml b/xproject-admin/src/main/resources/spring/spring-mvc.xml index 1c6fb46..b482e35 100644 --- a/xproject-admin/src/main/resources/spring/spring-mvc.xml +++ b/xproject-admin/src/main/resources/spring/spring-mvc.xml @@ -19,13 +19,9 @@ http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd"> - - - - - - - + + + @@ -40,12 +36,16 @@ - + + + + + - + diff --git a/xproject-admin/src/main/webapp/WEB-INF/web.xml b/xproject-admin/src/main/webapp/WEB-INF/web.xml index f8b7e85..3f653e3 100644 --- a/xproject-admin/src/main/webapp/WEB-INF/web.xml +++ b/xproject-admin/src/main/webapp/WEB-INF/web.xml @@ -33,6 +33,7 @@ org.springframework.web.util.IntrospectorCleanupListener + shiroFilter org.springframework.web.filter.DelegatingFilterProxy @@ -45,7 +46,8 @@ shiroFilter /* - + + characterEncodingFilter org.springframework.web.filter.CharacterEncodingFilter @@ -63,21 +65,20 @@ /* - - SpringMVC - org.springframework.web.servlet.DispatcherServlet + + + httpAccessLoggingStreamFilter + com.certusnet.xproject.common.web.filter.HttpAccessLoggingServletStreamFilter - contextConfigLocation - classpath:spring/spring-mvc.xml + supportedReqContentTypes + application/json - 1 - - - - SpringMVC - / - - + + + httpAccessLoggingStreamFilter + /* + + default @@ -111,6 +112,21 @@ default *.html + + + SpringMVC + org.springframework.web.servlet.DispatcherServlet + + contextConfigLocation + classpath:spring/spring-mvc.xml + + 1 + + + + SpringMVC + / + 30 diff --git a/xproject-admin/src/main/webapp/resources/scripts/common.js b/xproject-admin/src/main/webapp/resources/scripts/common.js index d5bfcbd..b454a92 100644 --- a/xproject-admin/src/main/webapp/resources/scripts/common.js +++ b/xproject-admin/src/main/webapp/resources/scripts/common.js @@ -35,7 +35,7 @@ if(axios){ }, function (error) { var statusCode = error.response.status; if(statusCode == 401){ - window.top.href = ADMIN_CONTEXT_PATH + '/login'; + window.top.location.href = ADMIN_CONTEXT_PATH + '/login'; /*if(window.parent){ window.parent.location.href = ADMIN_CONTEXT_PATH + '/login'; }else{ diff --git a/xproject-base/src/main/java/com/certusnet/xproject/admin/model/AdminUserAccessLog.java b/xproject-base/src/main/java/com/certusnet/xproject/admin/model/AdminUserAccessLog.java new file mode 100644 index 0000000..1fb69c2 --- /dev/null +++ b/xproject-base/src/main/java/com/certusnet/xproject/admin/model/AdminUserAccessLog.java @@ -0,0 +1,279 @@ +package com.certusnet.xproject.admin.model; + +/** + * 后天管理用户操作日志 + * + * @author pengpeng + * @date 2017年5月13日 下午12:19:28 + * @version 1.0 + */ +public class AdminUserAccessLog { + + private Long id; + + /** + * 日志标题 + */ + private String title; + + /** + * 请求URI + */ + private String uri; + + /** + * 请求方法(GET/POST/PUT/DELETE/INPUT) + */ + private String method; + + /** + * 请求头 + */ + private String requestHeader; + + /** + * 请求体类型 + */ + private String requestContentType; + + /** + * 请求参数 + */ + private String requestParameter; + + /** + * 访问者 + */ + private Long accessUserId; + + /** + * 访问时间 + */ + private String accessTime; + + /** + * 访问者ip地址 + */ + private String clientIpAddr; + + /** + * 被访问的服务器地址+端口号 + */ + private String serverIpAddr; + + /** + * 控制器方法的执行时长(毫秒) + */ + private Long processTime1; + + /** + * 控制器方法执行完毕到页面渲染时长(毫秒) + */ + private Long processTime2; + + /** + * 日志记录是否结束 + */ + private Boolean loggingCompleted = false; + + /** + * 请求是否是异步的 + */ + private Boolean asynRequest = false; + + /** + * 响应体类型 + */ + private String responseContentType; + + /** + * 响应结果 + */ + private String responseResult; + + private String createTime; + + //以下属于辅助字段 + private String userName; + private String startAccessTime; + private String endAccessTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getUri() { + return uri; + } + + public void setUri(String uri) { + this.uri = uri; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + public String getRequestHeader() { + return requestHeader; + } + + public void setRequestHeader(String requestHeader) { + this.requestHeader = requestHeader; + } + + public String getRequestContentType() { + return requestContentType; + } + + public void setRequestContentType(String requestContentType) { + this.requestContentType = requestContentType; + } + + public String getRequestParameter() { + return requestParameter; + } + + public void setRequestParameter(String requestParameter) { + this.requestParameter = requestParameter; + } + + public Long getAccessUserId() { + return accessUserId; + } + + public void setAccessUserId(Long accessUserId) { + this.accessUserId = accessUserId; + } + + public String getAccessTime() { + return accessTime; + } + + public void setAccessTime(String accessTime) { + this.accessTime = accessTime; + } + + public String getClientIpAddr() { + return clientIpAddr; + } + + public void setClientIpAddr(String clientIpAddr) { + this.clientIpAddr = clientIpAddr; + } + + public String getServerIpAddr() { + return serverIpAddr; + } + + public void setServerIpAddr(String serverIpAddr) { + this.serverIpAddr = serverIpAddr; + } + + public Long getProcessTime1() { + return processTime1; + } + + public void setProcessTime1(Long processTime1) { + this.processTime1 = processTime1; + } + + public Long getProcessTime2() { + return processTime2; + } + + public void setProcessTime2(Long processTime2) { + this.processTime2 = processTime2; + } + + public Boolean getLoggingCompleted() { + return loggingCompleted; + } + + public void setLoggingCompleted(Boolean loggingCompleted) { + this.loggingCompleted = loggingCompleted; + } + + public Boolean getAsynRequest() { + return asynRequest; + } + + public void setAsynRequest(Boolean asynRequest) { + this.asynRequest = asynRequest; + } + + public String getResponseContentType() { + return responseContentType; + } + + public void setResponseContentType(String responseContentType) { + this.responseContentType = responseContentType; + } + + public String getResponseResult() { + return responseResult; + } + + public void setResponseResult(String responseResult) { + this.responseResult = responseResult; + } + + public String getCreateTime() { + return createTime; + } + + public void setCreateTime(String createTime) { + this.createTime = createTime; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getStartAccessTime() { + return startAccessTime; + } + + public void setStartAccessTime(String startAccessTime) { + this.startAccessTime = startAccessTime; + } + + public String getEndAccessTime() { + return endAccessTime; + } + + public void setEndAccessTime(String endAccessTime) { + this.endAccessTime = endAccessTime; + } + + @Override + public String toString() { + return "AdminUserAccessLog [id=" + id + ", title=" + title + ", uri=" + uri + ", method=" + method + + ", requestHeader=" + requestHeader + ", requestParameter=" + requestParameter + ", accessUserId=" + + accessUserId + ", accessTime=" + accessTime + ", clientIpAddr=" + clientIpAddr + ", serverIpAddr=" + + serverIpAddr + ", processTime1=" + processTime1 + ", processTime2=" + processTime2 + + ", loggingCompleted=" + loggingCompleted + ", asynRequest=" + asynRequest + ", createTime=" + + createTime + "]"; + } + +} diff --git a/xproject-base/src/main/java/com/certusnet/xproject/common/consts/ContentType.java b/xproject-base/src/main/java/com/certusnet/xproject/common/consts/ContentType.java new file mode 100644 index 0000000..46584dc --- /dev/null +++ b/xproject-base/src/main/java/com/certusnet/xproject/common/consts/ContentType.java @@ -0,0 +1,34 @@ +package com.certusnet.xproject.common.consts; + +/** + * HTTP媒体类型 + * + * @author pengpeng + * @date 2017年5月20日 下午12:56:35 + * @version 1.0 + */ +public class ContentType { + + public static final String TEXT_HTML = "text/html"; + + public static final String TEXT_PLAIN = "text/plain"; + + public static final String TEXT_XML = "text/xml"; + + public static final String APPLICATION_JSON = "application/json;charset=UTF-8"; + + public static final String APPLICATION_XML = "application/xml"; + + public static final String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded"; + + public static final String APPLICATION_OCTET_STREAM = "application/octet-stream"; + + public static final String MULTIPART_FORM_DATA = "multipart/form-data"; + + public static final String IMAGE_PNG = "image/png"; + + public static final String IMAGE_JPEG = "image/jpeg"; + + public static final String IMAGE_GIF = "image/gif"; + +} diff --git a/xproject-base/src/main/java/com/certusnet/xproject/common/consts/GlobalConstants.java b/xproject-base/src/main/java/com/certusnet/xproject/common/consts/GlobalConstants.java index b910b8a..3c6b78b 100644 --- a/xproject-base/src/main/java/com/certusnet/xproject/common/consts/GlobalConstants.java +++ b/xproject-base/src/main/java/com/certusnet/xproject/common/consts/GlobalConstants.java @@ -18,7 +18,7 @@ public class GlobalConstants extends AbstractConstants { /** * 系统默认字符编码 */ - public static final String SYSTEM_DEFAULT_ENCODING = valueOf("UTF-8"); + public static final String SYSTEM_DEFAULT_CHARSET = valueOf("UTF-8"); /** * 系统默认Locale diff --git a/xproject-common/pom.xml b/xproject-common/pom.xml index fe21b2a..1ebf0f2 100644 --- a/xproject-common/pom.xml +++ b/xproject-common/pom.xml @@ -54,6 +54,12 @@ shiro-spring + + + joda-time + joda-time + + org.apache.commons diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/initializer/ApplicationBootingInitializer.java b/xproject-common/src/main/java/com/certusnet/xproject/common/initializer/ApplicationBootingInitializer.java index 2d7aaa5..d5aab0f 100644 --- a/xproject-common/src/main/java/com/certusnet/xproject/common/initializer/ApplicationBootingInitializer.java +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/initializer/ApplicationBootingInitializer.java @@ -29,7 +29,11 @@ public void initialize(ApplicationContext applicationContext) throws Exception { } setFinalFieldValue(ApplicationConstants.class, "APPLICATION_CONTEXT", rootApplicationContext); SpringUtils.setApplicationContext(rootApplicationContext); - Messages.setMessageSource(rootApplicationContext.getBean(AbstractMessageSource.class)); + try { + Messages.setMessageSource(rootApplicationContext.getBean(AbstractMessageSource.class)); + } catch (Exception e) { + logger.error(e.getMessage()); + } } } diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/support/HttpRequestLogging.java b/xproject-common/src/main/java/com/certusnet/xproject/common/support/HttpAccessLogging.java similarity index 56% rename from xproject-common/src/main/java/com/certusnet/xproject/common/support/HttpRequestLogging.java rename to xproject-common/src/main/java/com/certusnet/xproject/common/support/HttpAccessLogging.java index fe0a8e4..0732fe0 100644 --- a/xproject-common/src/main/java/com/certusnet/xproject/common/support/HttpRequestLogging.java +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/support/HttpAccessLogging.java @@ -17,10 +17,34 @@ @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented -public @interface HttpRequestLogging { +public @interface HttpAccessLogging { String title(); - boolean persistIntoDatabase() default true; + LoggingType loggingType() default LoggingType.DB; + + boolean isLogin() default false; + + String[] excludeParamNames() default {}; + + public static enum LoggingType { + + DB("db"), FILE("file"); + + private String type; + + private LoggingType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + } } diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/util/DateTimeUtils.java b/xproject-common/src/main/java/com/certusnet/xproject/common/util/DateTimeUtils.java index ef645a8..54f3f64 100644 --- a/xproject-common/src/main/java/com/certusnet/xproject/common/util/DateTimeUtils.java +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/util/DateTimeUtils.java @@ -1,10 +1,11 @@ package com.certusnet.xproject.common.util; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; import java.util.Date; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; import org.springframework.util.Assert; /** @@ -31,40 +32,36 @@ public class DateTimeUtils { */ public static final String DEFAULT_DATETIME_PATTERN = DEFAULT_DATE_PATTERN + " " + DEFAULT_TIME_PATTERN; - private static ZoneId DEFAULT_ZONE = ZoneId.systemDefault(); + /** + * 默认带毫秒数的时间戳格式 + */ + private static final Pattern TIMESTAMP_MSEC_REGEX_PATTERN = Pattern.compile("\\d{2}:\\d{2}:\\d{2}\\.\\d{1,3}"); /** - * java.util.Date转java.time.LocalDateTime - * @param date - * @return + * 默认不带毫秒数的时间戳格式 */ - public static LocalDateTime toDateTime(Date date){ - Assert.notNull(date, "Parameter 'date' can not be null!"); - return LocalDateTime.ofInstant(date.toInstant(), DEFAULT_ZONE); - } + private static final Pattern TIMESTAMP_REGEX_PATTERN = Pattern.compile("\\d{2}:\\d{2}:\\d{2}"); /** - * java.time.LocalDateTime转java.util.Date + *

将@{code java.util.Date}转换为@{code org.joda.time.DateTime} * - * @param dateTime + * @param date * @return */ - public static Date toDate(LocalDateTime dateTime){ - Assert.notNull(dateTime, "Parameter 'dateTime' can not be null!"); - return Date.from(dateTime.atZone(DEFAULT_ZONE).toInstant()); + public static DateTime from(Date date){ + Assert.notNull(date, "Parameter 'date' can not be null!"); + return new DateTime(date); } /** - *

将@{code java.time.LocalDateTime}以指定的日期格式格式化为字符串

+ *

将@{code java.util.Date}转换为@{code org.joda.time.DateTime} * * @param date - * @param pattern * @return */ - public static String format(LocalDateTime dateTime, String pattern){ + public static Date from(DateTime dateTime){ Assert.notNull(dateTime, "Parameter 'dateTime' can not be null!"); - Assert.hasText(pattern, "Parameter 'pattern' can not be empty!"); - return dateTime.format(DateTimeFormatter.ofPattern(pattern)); + return dateTime.toDate(); } /** @@ -77,7 +74,7 @@ public static String format(LocalDateTime dateTime, String pattern){ public static String format(Date date, String pattern){ Assert.notNull(date, "Parameter 'date' can not be null!"); Assert.hasText(pattern, "Parameter 'pattern' can not be empty!"); - return format(toDateTime(date), pattern); + return new DateTime(date).toString(pattern); } /** @@ -89,7 +86,7 @@ public static String format(Date date, String pattern){ */ public static String formatNow(String pattern){ Assert.hasText(pattern, "Parameter 'pattern' can not be empty!"); - return format(LocalDateTime.now(), pattern); + return new DateTime(new Date()).toString(pattern); } /** @@ -100,27 +97,60 @@ public static String formatNow(String pattern){ * @return */ public static String formatNow(){ - return formatNow(DEFAULT_DATETIME_PATTERN); + return new DateTime(new Date()).toString(DEFAULT_DATETIME_PATTERN); } /** - *

将字符串格式的日期转换为@{code java.util.Date}

+ *

将字符串格式的日期转换为@{org.joda.time.DateTime}

* * @param dateTimeText - 日期字符串形式的值 * @param pattern - 针对dateTimeText的日期格式 * @return */ - public static LocalDateTime parse(String dateTimeText, String pattern){ + public static DateTime parse2DateTime(String dateTimeText, String pattern){ Assert.hasText(dateTimeText, "Parameter 'dateTimeText' can not be empty!"); Assert.hasText(dateTimeText, "Parameter 'pattern' can not be empty!"); - return LocalDateTime.parse(dateTimeText, DateTimeFormatter.ofPattern(pattern)); + String format = pattern; + String text = dateTimeText; + Matcher matcher = null; + String suffix = ".SSS"; + //dateTimeText以毫秒结尾 && 格式pattern中没有以.SSS结尾 + if((matcher = TIMESTAMP_MSEC_REGEX_PATTERN.matcher(dateTimeText)).find() && matcher.end() == dateTimeText.length() && !pattern.endsWith(suffix)){ + format = format + suffix; + //dateTimeText没有以毫秒结尾 && 格式pattern中以.SSS结尾 + }else if((matcher = TIMESTAMP_REGEX_PATTERN.matcher(dateTimeText)).find() && matcher.end() == dateTimeText.length() && pattern.endsWith(suffix)){ + text = text + ".0"; + } + return DateTimeFormat.forPattern(format).parseDateTime(text); } - public static void main(String[] args) { - System.out.println(DEFAULT_ZONE); - Date date = new Date(); - System.out.println(date); - System.out.println(format(date, DEFAULT_DATETIME_PATTERN)); + /** + *

将字符串格式的日期转换为@{code java.util.Date}

+ * + * @param dateTimeText - 日期字符串形式的值 + * @param pattern - 针对dateTimeText的日期格式 + * @return + */ + public static Date parse2Date(String dateTimeText, String pattern){ + return parse2DateTime(dateTimeText, pattern).toDate(); + } + + /** + * 检测dateTimeText的日期格式是否是pattern + * @param dateTimeText + * @param pattern + * @return + */ + public static boolean checkDatePattern(String dateTimeText, String pattern) { + if(dateTimeText != null){ + try { + DateTime dateTime = DateTimeFormat.forPattern(pattern).parseDateTime(dateTimeText); + return dateTime != null; + } catch (Exception e) { + return false; + } + } + return false; } } diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/util/HttpUtils.java b/xproject-common/src/main/java/com/certusnet/xproject/common/util/HttpUtils.java index 316c9bb..198bdfa 100644 --- a/xproject-common/src/main/java/com/certusnet/xproject/common/util/HttpUtils.java +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/util/HttpUtils.java @@ -66,7 +66,7 @@ public static boolean isAsynRequest(HttpServletRequest request) { */ public static void asynOutputResponse(HttpServletResponse response, ContentType contentType, String content) throws IOException { response.setContentType(contentType.toString()); - response.setCharacterEncoding(GlobalConstants.SYSTEM_DEFAULT_ENCODING); + response.setCharacterEncoding(GlobalConstants.SYSTEM_DEFAULT_CHARSET); PrintWriter out = response.getWriter(); out.print(content); out.flush(); diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/util/SpringMvcUtils.java b/xproject-common/src/main/java/com/certusnet/xproject/common/util/SpringMvcUtils.java new file mode 100644 index 0000000..d1063b1 --- /dev/null +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/util/SpringMvcUtils.java @@ -0,0 +1,43 @@ +package com.certusnet.xproject.common.util; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.method.HandlerMethod; +/** + * SpringMVC的工具类 + * + * @author pengpeng + * @date 2017年5月13日 上午10:08:47 + * @version 1.0 + */ +public class SpringMvcUtils { + + /** + * 判断请求是否是异步请求 + * @param request + * @param handler + * @return + */ + public static boolean isAsyncRequest(HttpServletRequest request, Object handler){ + boolean isAsync = false; + if(handler instanceof HandlerMethod){ + HandlerMethod handlerMethod = (HandlerMethod) handler; + isAsync = handlerMethod.hasMethodAnnotation(ResponseBody.class); + if(!isAsync){ + Class controllerClass = handlerMethod.getBeanType(); + isAsync = controllerClass.isAnnotationPresent(ResponseBody.class) || controllerClass.isAnnotationPresent(RestController.class); + } + if(!isAsync){ + isAsync = ResponseEntity.class.equals(handlerMethod.getMethod().getReturnType()); + } + } + if(!isAsync){ + isAsync = HttpUtils.isAsynRequest(request); + } + return isAsync; + } + +} diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/filter/HttpAccessLoggingServletStreamFilter.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/filter/HttpAccessLoggingServletStreamFilter.java new file mode 100644 index 0000000..57740de --- /dev/null +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/web/filter/HttpAccessLoggingServletStreamFilter.java @@ -0,0 +1,125 @@ +package com.certusnet.xproject.common.web.filter; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; + +import org.springframework.http.MediaType; +import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.util.ContentCachingRequestWrapper; +import org.springframework.web.util.ContentCachingResponseWrapper; + +import com.certusnet.xproject.common.util.StringUtils; + +/** + * Http访问日志记录之Servlet输入输出流过滤器,解决: + * 1、HttpServletRequest的输入流可重读, + * 2、HttpServletResponse的输出流可缓存 + * + * @author pengpeng + * @date 2017年5月16日 下午12:47:22 + * @version 1.0 + */ +public class HttpAccessLoggingServletStreamFilter extends OncePerRequestFilter { + + private static final MediaType DEFAULT_SUPPORTED_REQ_CONTENTTYPE = MediaType.APPLICATION_JSON; + + /** + * 对于支持的请求体类型进行请求Wrapper + */ + private final Set supportedReqContentTypes = new HashSet(); + + public HttpAccessLoggingServletStreamFilter() { + super(); + supportedReqContentTypes.add(DEFAULT_SUPPORTED_REQ_CONTENTTYPE); + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + HttpServletRequest requestToUse = request; + HttpServletResponse responseToUse = response; + if(isRequestBodySupport(request)){ + requestToUse = new ContentCachingRequestWrapper(request); + responseToUse = new ContentCachingResponseWrapper(response); + } + filterChain.doFilter(requestToUse, responseToUse); + ContentCachingResponseWrapper contentCachedResponse = getContentCachingResponseWrapper(responseToUse); + if(contentCachedResponse != null){ + contentCachedResponse.copyBodyToResponse(); //重写响应到response.OutputStream中去,否则客户端响应会出现NO CONTENT + } + } + + public Set getSupportedReqContentTypes() { + return supportedReqContentTypes; + } + + public void setSupportedReqContentTypes(String supportedReqContentTypes) { + addSupportedContentTypes(this.supportedReqContentTypes, supportedReqContentTypes); + } + + protected void addSupportedContentTypes(Set supportedContentTypes,String supportedContentTypeValues) { + if(!StringUtils.isEmpty(supportedContentTypeValues)){ + String[] contentTypes = supportedContentTypeValues.split(","); + for(String contentType : contentTypes){ + if(!StringUtils.isEmpty(contentType)){ + supportedContentTypes.add(MediaType.valueOf(contentType.trim())); + } + } + } + } + + protected boolean isRequestBodySupport(HttpServletRequest request) { + boolean asyncRequest = !isAsyncDispatch(request) && !isAsyncStarted(request); + String contentTypeValue = request.getContentType(); + MediaType contentType = getContentType(contentTypeValue); + boolean supported = false; + if(asyncRequest && contentType != null){ + if(supportedReqContentTypes.isEmpty()){ + supported = false; + }else{ + for(MediaType mediaType : supportedReqContentTypes){ + if(mediaType.getType().equals(contentType.getType())){ //主类型相同即可 + supported = true; + break; + } + } + } + } + return supported; + } + + /** + * 获取ContentCachingResponseWrapper + * (考虑到Wrapper是可以重复的,故需要递归获取) + * @param response + * @return + */ + protected ContentCachingResponseWrapper getContentCachingResponseWrapper(ServletResponse response) { + if(response instanceof ContentCachingResponseWrapper){ + return (ContentCachingResponseWrapper) response; + }else if(response instanceof HttpServletResponseWrapper) { + HttpServletResponseWrapper responseToUse = (HttpServletResponseWrapper) response; + return getContentCachingResponseWrapper(responseToUse.getResponse()); + } + return null; + } + + protected MediaType getContentType(String contentType) { + try { + if(!StringUtils.isEmpty(contentType)){ + return MediaType.valueOf(contentType); + } + } catch (Exception e) { + } + return null; + } + +} diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/AbstractHttpRequestLoggerHandler.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/AbstractHttpRequestLoggerHandler.java deleted file mode 100644 index 958fd05..0000000 --- a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/AbstractHttpRequestLoggerHandler.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.certusnet.xproject.common.web.interceptor; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -/** - * 日志处理类,如将日志写入数据库、日志文件等等 - * - * @param - * @author pengpeng - * @date 2014年10月17日 下午7:24:08 - * @version 1.0 - */ -public abstract class AbstractHttpRequestLoggerHandler implements Runnable { - - private static final Logger logger = LoggerFactory.getLogger(AbstractHttpRequestLoggerHandler.class); - - private final HttpRequestLogger httpRequestLogger; - - public AbstractHttpRequestLoggerHandler(HttpRequestLogger httpRequestLogger) { - super(); - this.httpRequestLogger = httpRequestLogger; - } - - public void run() { - try { - handleLogger(httpRequestLogger); - } catch (Exception e) { - logger.error(e.getMessage(), e); - } - } - - /** - * 日志处理方法,如将日志写入数据库、日志文件等等 - * @param httpRequestLogger - * @throws Exception - */ - public abstract void handleLogger(HttpRequestLogger httpRequestLogger) throws Exception; - -} diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/AbstractHttpRequestLoggingInterceptor.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/AbstractHttpRequestLoggingInterceptor.java deleted file mode 100644 index 3c07195..0000000 --- a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/AbstractHttpRequestLoggingInterceptor.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.certusnet.xproject.common.web.interceptor; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.core.NamedThreadLocal; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.HandlerInterceptor; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.util.UrlPathHelper; - -import com.certusnet.xproject.common.support.HttpRequestLogging; -import com.certusnet.xproject.common.support.NamedThreadFactory; -import com.certusnet.xproject.common.util.DateTimeUtils; -import com.certusnet.xproject.common.util.HttpUtils; -import com.certusnet.xproject.common.util.NetUtils; -import com.certusnet.xproject.common.util.StringUtils; - -/** - * Http请求日志记录拦截器 - * - * @author pengpeng - * @date 2014年10月16日 下午9:21:35 - * @version 1.0 - */ -public abstract class AbstractHttpRequestLoggingInterceptor implements HandlerInterceptor, DisposableBean { - - private static final Pattern messageSourceCodePattern = Pattern.compile("\\$\\{([a-zA-Z0-9_.]+)\\}"); - - private static final Logger logger = LoggerFactory.getLogger(AbstractHttpRequestLoggingInterceptor.class); - - private static final UrlPathHelper urlPathHelper = new UrlPathHelper(); - - private static final ExecutorService httpRequestLoggingExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2, new NamedThreadFactory("HTTP-REQUEST-LOGGING-EXECUTE-WORKER-")); - - private static final ThreadLocal> httpRequestLoggerThreadLocal = new NamedThreadLocal>("httpRequestLogger ThreadLocal"); - - /** - * 请求进入处理器方法之前调用 - */ - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - try { - String currentRequestURI = urlPathHelper.getRequestUri(request); - Map originalParamMap = request.getParameterMap(); - Map paramMap = new HashMap(); - if(originalParamMap != null && !originalParamMap.isEmpty()){ - for(Map.Entry entry : originalParamMap.entrySet()){ - paramMap.put(entry.getKey(), getStringParameterValue(entry.getValue())); - } - } - HttpRequestLogger httpRequestLogger = new HttpRequestLogger(); - httpRequestLogger.setOptBeginMillis(System.currentTimeMillis()); - httpRequestLogger.setUri(currentRequestURI); - httpRequestLogger.setOptTime(DateTimeUtils.formatNow()); - httpRequestLogger.setMethod(request.getMethod()); - httpRequestLogger.setOptUser(getOptUser(request)); - httpRequestLogger.setParams(paramMap); - httpRequestLogger.setClientIpAddr(NetUtils.getRemoteIpAddr(request)); - httpRequestLogger.setServerIpAddr(NetUtils.getLocalIpAddr(request)); - httpRequestLogger.setOptEndMillis(null); - httpRequestLogger.setProcessTime1(null); - httpRequestLogger.setProcessTime2(null); - httpRequestLogger.setAsynRequest(HttpUtils.isAsynRequest(request)); - httpRequestLoggerThreadLocal.set(httpRequestLogger); - logger.debug(">>> do request logging[preHandle] : " + httpRequestLogger); - if(handler != null && handler instanceof HandlerMethod){ - HandlerMethod handlerMethod = (HandlerMethod) handler; - HttpRequestLogging httpRequestLoggingAnnotation = handlerMethod.getMethodAnnotation(HttpRequestLogging.class); - if(httpRequestLoggingAnnotation != null){ - String title = httpRequestLoggingAnnotation.title(); - if(!StringUtils.isEmpty(title)){ - Matcher matcher = messageSourceCodePattern.matcher(title); - if(matcher.find()){ - title = getMessage(matcher.group(1)); - } - } - if(StringUtils.isEmpty(title)){ - title = getMessage("logging.title.default"); - } - httpRequestLogger.setTitle(title); - } - } - } catch (Exception e) { - logger.error(e.getMessage()); - } - return true; - } - - /** - * Action方法执行完毕以后调用 - */ - public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { - HttpRequestLogger httpRequestLogger = httpRequestLoggerThreadLocal.get(); - if (httpRequestLogger != null) { - try { - httpRequestLogger.setOptEndMillis(System.currentTimeMillis()); - httpRequestLogger.setProcessTime1(httpRequestLogger.getOptEndMillis() - httpRequestLogger.getOptBeginMillis()); - httpRequestLogger.setLoggingCompleted(true); - logger.debug(">>> do request logging[postHandle] : " + httpRequestLogger); - if(handler != null && handler instanceof HandlerMethod){ - HandlerMethod handlerMethod = (HandlerMethod) handler; - HttpRequestLogging httpRequestLoggingAnnotation = handlerMethod.getMethodAnnotation(HttpRequestLogging.class); - if(httpRequestLoggingAnnotation != null && httpRequestLoggingAnnotation.persistIntoDatabase() && httpRequestLogger.getOptUser() != null){ - httpRequestLoggingExecutor.execute(createHttpRequestLoggerHandler(httpRequestLogger)); - } - } - } finally { - httpRequestLoggerThreadLocal.remove(); - } - } - } - - /** - * 渲染页面完成以后调用 - */ - public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { - } - - public void destroy() throws Exception { - httpRequestLoggingExecutor.shutdown(); - } - - /** - * 获取操作人的LoginUser对象 - * @param request - * @return - */ - protected abstract T getOptUser(HttpServletRequest request); - - /** - * 从国际化资源文件中获取message - * @param code - * @return - */ - protected abstract String getMessage(String code); - - /** - * 创建HttpRequestLogger处理器(如将日志写入数据库、日志文件等等) - * @return - */ - protected abstract AbstractHttpRequestLoggerHandler createHttpRequestLoggerHandler(HttpRequestLogger httpRequestLogger); - - protected String getStringParameterValue(String[] values){ - if(values == null){ - return null; - }else{ - return values.length == 1 ? values[0] : Arrays.toString(values); - } - } - -} diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/HttpRequestLogger.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/HttpRequestLogger.java deleted file mode 100644 index b7778fb..0000000 --- a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/HttpRequestLogger.java +++ /dev/null @@ -1,211 +0,0 @@ -package com.certusnet.xproject.common.web.interceptor; - -import java.util.Map; - -/** - * 对Http请求的日志记录bean - * - * @param - * @author pengpeng - * @date 2014年10月17日 下午7:24:39 - * @version 1.0 - */ -public class HttpRequestLogger { - - /** - * 日志标题 - * 由注解@HttpRequestLogging(title=${xxxx})从国际化资源文件中获取 - */ - private String title; - - /** - * 请求URI - */ - private String uri; - - /** - * 请求方法(GET/POST/PUT/DELETE/INPUT) - */ - private String method; - - /** - * 请求参数列表(字符串形式) - */ - private Map params; - - /** - * 访问者 - */ - private T optUser; - - /** - * 访问时间 - */ - private String optTime; - - /** - * 访问者ip地址 - */ - private String clientIpAddr; - - /** - * 被访问的服务器地址+端口号 - */ - private String serverIpAddr; - - /** - * 访问开始系统毫秒数 - */ - private Long optBeginMillis; - - /** - * 访问结束系统毫秒数 - */ - private Long optEndMillis; - - /** - * 从请求到达至控制器处理完毕业务逻辑准备渲染页面时的这段操作时长(毫秒) - * 理论上processTime1 < processTime2 - */ - private Long processTime1; - - /** - * 从请求到达至渲染页面完毕时的这段操作时长(毫秒) - * 理论上processTime1 < processTime2 - */ - private Long processTime2; - - /** - * 日志记录是否结束 - */ - private boolean isLoggingCompleted = false; - - /** - * 请求是否是异步的(ajax请求) - */ - private boolean isAsynRequest = false; - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getUri() { - return uri; - } - - public void setUri(String uri) { - this.uri = uri; - } - - public String getMethod() { - return method; - } - - public void setMethod(String method) { - this.method = method; - } - - public Map getParams() { - return params; - } - - public void setParams(Map params) { - this.params = params; - } - - public T getOptUser() { - return optUser; - } - - public void setOptUser(T optUser) { - this.optUser = optUser; - } - - public String getOptTime() { - return optTime; - } - - public void setOptTime(String optTime) { - this.optTime = optTime; - } - - public String getClientIpAddr() { - return clientIpAddr; - } - - public void setClientIpAddr(String clientIpAddr) { - this.clientIpAddr = clientIpAddr; - } - - public String getServerIpAddr() { - return serverIpAddr; - } - - public void setServerIpAddr(String serverIpAddr) { - this.serverIpAddr = serverIpAddr; - } - - public Long getOptBeginMillis() { - return optBeginMillis; - } - - public void setOptBeginMillis(Long optBeginMillis) { - this.optBeginMillis = optBeginMillis; - } - - public Long getOptEndMillis() { - return optEndMillis; - } - - public void setOptEndMillis(Long optEndMillis) { - this.optEndMillis = optEndMillis; - } - - public Long getProcessTime1() { - return processTime1; - } - - public void setProcessTime1(Long processTime1) { - this.processTime1 = processTime1; - } - - public Long getProcessTime2() { - return processTime2; - } - - public void setProcessTime2(Long processTime2) { - this.processTime2 = processTime2; - } - - public boolean isLoggingCompleted() { - return isLoggingCompleted; - } - - public void setLoggingCompleted(boolean isLoggingCompleted) { - this.isLoggingCompleted = isLoggingCompleted; - } - - public boolean isAsynRequest() { - return isAsynRequest; - } - - public void setAsynRequest(boolean isAsynRequest) { - this.isAsynRequest = isAsynRequest; - } - - public String toString() { - return "HttpRequestLogger [title=" + title + ", uri=" + uri - + ", method=" + method + ", params=" + params + ", optUser=" - + optUser + ", optTime=" + optTime + ", clientIpAddr=" - + clientIpAddr + ", serverIpAddr=" + serverIpAddr - + ", optBeginMillis=" + optBeginMillis + ", optEndMillis=" - + optEndMillis + ", processTime1=" + processTime1 - + ", processTime2=" + processTime2 + ", isLoggingCompleted=" - + isLoggingCompleted + ", isAsynRequest=" + isAsynRequest + "]"; - } - -} diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/request/RereadableStreamHttpServletRequest.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/request/RereadableStreamHttpServletRequest.java new file mode 100644 index 0000000..56cd27d --- /dev/null +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/web/request/RereadableStreamHttpServletRequest.java @@ -0,0 +1,87 @@ +package com.certusnet.xproject.common.web.request; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +import org.apache.commons.io.IOUtils; +import org.springframework.web.util.WebUtils; + +/** + * 可重读的HttpServletRequest请求体 + * + * @author pengpeng + * @date 2017年5月18日 下午12:39:59 + * @version 1.0 + */ +public class RereadableStreamHttpServletRequest extends HttpServletRequestWrapper { + + private final byte[] rawData; + + public byte[] getRawData() { + return rawData; + } + + public RereadableStreamHttpServletRequest(HttpServletRequest request) { + super(request); + try { + rawData = IOUtils.toByteArray(request.getInputStream()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public ServletInputStream getInputStream() throws IOException { + return new RereadableServletInputStream(new ByteArrayInputStream(getRawData())); + } + + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(getInputStream(), getCharacterEncoding())); + } + + public String getCharacterEncoding() { + String enc = super.getCharacterEncoding(); + return (enc != null ? enc : WebUtils.DEFAULT_CHARACTER_ENCODING); + } + + private class RereadableServletInputStream extends ServletInputStream { + + private boolean finished = false; + + private InputStream stream; + + public RereadableServletInputStream(InputStream stream) { + super(); + this.stream = stream; + } + + public boolean isFinished() { + return finished; + } + + public boolean isReady() { + return true; + } + + public void setReadListener(ReadListener readListener) { + + } + + public int read() throws IOException { + int b = stream.read(); + if(b == -1){ + finished = true; + } + return b; + } + + } + +} diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/handler/AbstractGlobalHandlerExceptionResolver.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/handler/AbstractGlobalHandlerExceptionResolver.java similarity index 74% rename from xproject-common/src/main/java/com/certusnet/xproject/common/web/handler/AbstractGlobalHandlerExceptionResolver.java rename to xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/handler/AbstractGlobalHandlerExceptionResolver.java index c78dcbe..88fe609 100644 --- a/xproject-common/src/main/java/com/certusnet/xproject/common/web/handler/AbstractGlobalHandlerExceptionResolver.java +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/handler/AbstractGlobalHandlerExceptionResolver.java @@ -1,19 +1,16 @@ -package com.certusnet.xproject.common.web.handler; +package com.certusnet.xproject.common.web.springmvc.handler; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver; import com.certusnet.xproject.common.exception.SystemException; -import com.certusnet.xproject.common.util.HttpUtils; +import com.certusnet.xproject.common.util.SpringMvcUtils; /** * 全局异常处理器 * @@ -62,19 +59,7 @@ protected ModelAndView doResolveException(HttpServletRequest request, HttpServle * @return */ protected boolean isAsyncRequest(HttpServletRequest request, HttpServletResponse response, Object handler){ - HandlerMethod handlerMethod = (HandlerMethod) handler; - boolean isAsync = handlerMethod.hasMethodAnnotation(ResponseBody.class); - if(!isAsync){ - Class controllerClass = handlerMethod.getBeanType(); - isAsync = controllerClass.isAnnotationPresent(ResponseBody.class) || controllerClass.isAnnotationPresent(RestController.class); - } - if(!isAsync){ - isAsync = ResponseEntity.class.equals(handlerMethod.getMethod().getReturnType()); - } - if(!isAsync){ - isAsync = HttpUtils.isAsynRequest(request); - } - return isAsync; + return SpringMvcUtils.isAsyncRequest(request, handler); } /** diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/handler/DefaultMvcHandlerExceptionResolver.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/handler/DefaultMvcHandlerExceptionResolver.java similarity index 96% rename from xproject-common/src/main/java/com/certusnet/xproject/common/web/handler/DefaultMvcHandlerExceptionResolver.java rename to xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/handler/DefaultMvcHandlerExceptionResolver.java index fdb91b6..ec76a7d 100644 --- a/xproject-common/src/main/java/com/certusnet/xproject/common/web/handler/DefaultMvcHandlerExceptionResolver.java +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/handler/DefaultMvcHandlerExceptionResolver.java @@ -1,4 +1,4 @@ -package com.certusnet.xproject.common.web.handler; +package com.certusnet.xproject.common.web.springmvc.handler; import java.util.HashMap; import java.util.Map; diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/AbstractHttpAccessLogHandler.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/AbstractHttpAccessLogHandler.java new file mode 100644 index 0000000..5bfc554 --- /dev/null +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/AbstractHttpAccessLogHandler.java @@ -0,0 +1,47 @@ +package com.certusnet.xproject.common.web.springmvc.interceptor; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.certusnet.xproject.common.support.HttpAccessLogging; +/** + * 日志处理类,如将日志写入数据库、日志文件等等 + * + * @param + * @author pengpeng + * @date 2014年10月17日 下午7:24:08 + * @version 1.0 + */ +public abstract class AbstractHttpAccessLogHandler implements Runnable { + + private static final Logger logger = LoggerFactory.getLogger(AbstractHttpAccessLogHandler.class); + + private final HttpAccessLog httpAccessLog; + + public AbstractHttpAccessLogHandler(HttpAccessLog httpAccessLog) { + super(); + this.httpAccessLog = httpAccessLog; + } + + public void run() { + try { + handleLogger(httpAccessLog); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } + + /** + * 获取日志的记录方式 + * @return + */ + public abstract HttpAccessLogging.LoggingType getLoggingType(); + + /** + * 日志处理方法,如将日志写入数据库、日志文件等等 + * @param httpAccessLog + * @throws Exception + */ + public abstract void handleLogger(HttpAccessLog httpAccessLog) throws Exception; + +} diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/AbstractHttpAccessLoggingInterceptor.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/AbstractHttpAccessLoggingInterceptor.java new file mode 100644 index 0000000..c6bc56e --- /dev/null +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/AbstractHttpAccessLoggingInterceptor.java @@ -0,0 +1,453 @@ +package com.certusnet.xproject.common.web.springmvc.interceptor; + +import java.util.Arrays; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; + +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.core.NamedThreadLocal; +import org.springframework.http.MediaType; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.util.ContentCachingRequestWrapper; +import org.springframework.web.util.ContentCachingResponseWrapper; + +import com.certusnet.xproject.common.consts.GlobalConstants; +import com.certusnet.xproject.common.support.HttpAccessLogging; +import com.certusnet.xproject.common.support.Messages; +import com.certusnet.xproject.common.support.NamedThreadFactory; +import com.certusnet.xproject.common.util.CollectionUtils; +import com.certusnet.xproject.common.util.DateTimeUtils; +import com.certusnet.xproject.common.util.JsonUtils; +import com.certusnet.xproject.common.util.NetUtils; +import com.certusnet.xproject.common.util.SpringMvcUtils; +import com.certusnet.xproject.common.util.StringUtils; +import com.certusnet.xproject.common.web.springmvc.interceptor.HttpAccessLog.HttpRequestParameter; +import com.fasterxml.jackson.core.type.TypeReference; + +/** + * Http请求日志记录拦截器 + * + * @author pengpeng + * @date 2014年10月16日 下午9:21:35 + * @version 1.0 + */ +public abstract class AbstractHttpAccessLoggingInterceptor implements HandlerInterceptor, DisposableBean { + + private static final Pattern messageSourceCodePattern = Pattern.compile("\\$\\{([a-zA-Z0-9_.]+)\\}"); + + private static final Logger logger = LoggerFactory.getLogger(AbstractHttpAccessLoggingInterceptor.class); + + private static final ExecutorService httpAccessLogHandlerExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2, new NamedThreadFactory("HTTP-REQUEST-LOGGING-EXECUTE-WORKER-")); + + private static final ThreadLocal loggingContextThreadLocal = new NamedThreadLocal("LoggingContext ThreadLocal"); + + private static final String DEFAULT_LOG_TITLE = "用户访问日志"; + + private String defaultLogTitle = DEFAULT_LOG_TITLE; + + private boolean loggingRequestHeader = false; + + public String getDefaultLogTitle() { + return defaultLogTitle; + } + + public void setDefaultLogTitle(String defaultLogTitle) { + this.defaultLogTitle = defaultLogTitle; + } + + public boolean isLoggingRequestHeader() { + return loggingRequestHeader; + } + + public void setLoggingRequestHeader(boolean loggingRequestHeader) { + this.loggingRequestHeader = loggingRequestHeader; + } + + public static ExecutorService getHttpAccessLogHandlerExecutor() { + return httpAccessLogHandlerExecutor; + } + + public static ThreadLocal getLoggingContextThreadLocal() { + return loggingContextThreadLocal; + } + + /** + * 请求进入处理器方法之前调用 + */ + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + try { + String requestURI = request.getRequestURI(); + logger.debug(requestURI); + if(handler != null && handler instanceof HandlerMethod){ + HandlerMethod handlerMethod = (HandlerMethod) handler; + HttpAccessLogging httpAccessLogging = handlerMethod.getMethodAnnotation(HttpAccessLogging.class); + if(httpAccessLogging != null){ + HttpAccessLog httpAccessLog = new HttpAccessLog(); + LoggingContext loggingContext = new LoggingContext(); + loggingContext.setHandlerMethod(handlerMethod); + loggingContext.setHttpAccessLogging(httpAccessLogging); + loggingContext.setHttpAccessLog(httpAccessLog); + httpAccessLog.setTitle(getLogTitle(httpAccessLogging.title())); + httpAccessLog.setAccessBeginMillis(System.currentTimeMillis()); + httpAccessLog.setUri(requestURI); + httpAccessLog.setAccessTime(DateTimeUtils.formatNow()); + httpAccessLog.setMethod(request.getMethod()); + httpAccessLog.setClientIpAddr(NetUtils.getRemoteIpAddr(request)); + httpAccessLog.setServerIpAddr(NetUtils.getLocalIpAddr(request)); + httpAccessLog.setRequestContentType(getContentType(request.getContentType())); + httpAccessLog.setAccessEndMillis(null); + httpAccessLog.setProcessTime1(null); + httpAccessLog.setProcessTime2(null); + httpAccessLog.setAsynRequest(SpringMvcUtils.isAsyncRequest(request, handler)); + if(isLoggingRequestHeader()){ + httpAccessLog.setRequestHeader(extractRequestHeader(request, loggingContext)); + } + getLoggingContextThreadLocal().set(loggingContext); + logger.debug(">>> access logging [preHandle] : " + httpAccessLog); + } + } + } catch (Throwable e) { + logger.error(e.getMessage(), e); + } + return true; + } + + /** + * Action方法执行完毕以后调用 + */ + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + LoggingContext loggingContext = getLoggingContextThreadLocal().get(); + if(loggingContext != null && handler.equals(loggingContext.getHandlerMethod())){ + HttpAccessLog httpAccessLog = loggingContext.getHttpAccessLog(); + if(httpAccessLog != null){ + httpAccessLog.setAccessEndMillis(System.currentTimeMillis()); + httpAccessLog.setProcessTime1(httpAccessLog.getAccessEndMillis() - httpAccessLog.getAccessBeginMillis()); + logger.debug(">>> access logging [postHandle] : " + httpAccessLog); + } + } + } + + /** + * 渲染页面完成以后调用 + */ + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + try { + LoggingContext loggingContext = getLoggingContextThreadLocal().get(); + if(loggingContext != null && handler.equals(loggingContext.getHandlerMethod())){ + HttpAccessLog httpAccessLog = loggingContext.getHttpAccessLog(); + if(httpAccessLog != null){ + long nowTimeMillis = System.currentTimeMillis(); + httpAccessLog.setProcessTime2(nowTimeMillis - httpAccessLog.getAccessEndMillis()); + httpAccessLog.setAccessEndMillis(nowTimeMillis); + httpAccessLog.setLoggingCompleted(true); + httpAccessLog.setRequestParameter(extractRequestParameter(request, loggingContext)); + httpAccessLog.setAccessUser(getAccessUser(request, loggingContext)); + httpAccessLog.setResponseContentType(getContentType(response.getContentType())); + httpAccessLog.setResponseResult(extractResponseResult(response, loggingContext)); + logger.debug(">>> access logging [postHandle] : " + httpAccessLog); + AbstractHttpAccessLogHandler httpAccessLogHandler = createHttpAccessLoggerHandler(loggingContext); + if(httpAccessLogHandler != null){ + getHttpAccessLogHandlerExecutor().execute(httpAccessLogHandler); + } + } + } + } finally { + getLoggingContextThreadLocal().remove(); + } + } + + /** + * 获取日志标题 + * @param title + * @return + */ + protected String getLogTitle(String title) { + if(!StringUtils.isEmpty(title)){ + Matcher matcher = messageSourceCodePattern.matcher(title); + if(matcher.find()){ + title = getMessage(matcher.group(1)); + } + } + return StringUtils.defaultIfEmpty(title, defaultLogTitle); + } + + /** + * 从国际化资源文件中获取message + * @param code + * @return + */ + protected String getMessage(String code) { + return Messages.getMessage(code); + } + + protected String getStringParameterValue(String[] values){ + if(values == null){ + return null; + }else{ + return values.length == 1 ? values[0] : Arrays.toString(values); + } + } + + /** + * 从HttpServletRequest中提取请求参数(包括请求体中的参数) + * @param request + * @param loggingContext + * @return + * @throws Exception + */ + protected HttpRequestParameter extractRequestParameter(HttpServletRequest request, LoggingContext loggingContext) throws Exception { + HttpRequestParameter parameter = new HttpRequestParameter(); + Map originalParamMap = request.getParameterMap(); + Map paramMap = new HashMap(); + if(originalParamMap != null && !originalParamMap.isEmpty()){ + for(Map.Entry entry : originalParamMap.entrySet()){ + paramMap.put(entry.getKey(), getStringParameterValue(entry.getValue())); + } + } + parameter.setParameter(paramMap); + MediaType contentType = loggingContext.getHttpAccessLog().getRequestContentType(); + if(contentType != null){ + if(isContentCachingRequest(request)){ + String charset = request.getCharacterEncoding(); + if(StringUtils.isEmpty(charset)){ + charset = StringUtils.defaultIfEmpty(contentType.getCharset().name(), GlobalConstants.SYSTEM_DEFAULT_CHARSET); + } + ContentCachingRequestWrapper requestToUse = (ContentCachingRequestWrapper) request; + byte[] bytes = requestToUse.getContentAsByteArray(); + if(bytes != null){ + String body = IOUtils.toString(bytes, charset); + Object bodyObj = body; + if(MediaType.APPLICATION_JSON.getType().equals(contentType.getType())){ //目前只处理JSON类型的数据 + if(body.startsWith("[") && body.endsWith("]")){ //JSON Array String -> List> + bodyObj = JsonUtils.json2Object(body, new TypeReference>>(){}); + }else if(body.startsWith("{") && body.endsWith("}")){ //JSON Object String -> Map + bodyObj = JsonUtils.json2Object(body, new TypeReference>(){}); + } + } + parameter.setBody(bodyObj); + } + + } + } + return excludeRequestParameter(parameter, loggingContext); + } + + /** + * 记录请求参数时剔除一些敏感数据,如用户密码明文 + * @param parameter + * @param loggingContext + * @return + */ + @SuppressWarnings("unchecked") + protected HttpRequestParameter excludeRequestParameter(HttpRequestParameter parameter, LoggingContext loggingContext) { + HttpAccessLogging httpAccessLogging = loggingContext.httpAccessLogging; + String[] excludeNameParams = httpAccessLogging.excludeParamNames(); + if(excludeNameParams != null && excludeNameParams.length > 0){ + try { + for(String paramName : excludeNameParams){ + if(parameter.getParameter() != null){ + parameter.getParameter().remove(paramName); + } + MediaType contentType = loggingContext.getHttpAccessLog().getRequestContentType(); + if (contentType != null && parameter.getBody() != null) { + if(parameter.getBody() instanceof List){ //JSON Array + for(Map item : (List>)parameter.getBody()){ + excludeParameter(item, paramName); + } + }else if(parameter.getBody() instanceof Map){ //JSON Object + excludeParameter((Map)parameter.getBody(), paramName); + } + } + } + } catch (Exception e) { + logger.error(">>> 排除参数出错! " + e.getMessage()); + } + } + return parameter; + } + + /** + * 递归剔除参数 + * @param parameter + * @param paramName + */ + @SuppressWarnings("unchecked") + protected void excludeParameter(Map parameter, String paramName) { + if(!CollectionUtils.isEmpty(parameter)){ + parameter.remove(paramName); + for(Map.Entry entry : parameter.entrySet()){ + Object value = entry.getValue(); + if(value != null){ + if(value instanceof List){ + List> list = (List>) value; + for(Map item : list){ + excludeParameter(item, paramName); + } + }else if(value instanceof Map){ + Map item = (Map) value; + excludeParameter(item, paramName); + } + } + } + } + } + + /** + * 从HttpServletRequest中提取请求头信息 + * @param request + * @param loggingContext + * @return + */ + protected Map extractRequestHeader(HttpServletRequest request, LoggingContext loggingContext) { + Map headerMap = new HashMap(); + Enumeration headerNames = request.getHeaderNames(); + if(headerNames != null){ + while(headerNames.hasMoreElements()){ + String headerName = headerNames.nextElement(); + headerMap.put(headerName, request.getHeader(headerName)); + } + } + return headerMap; + } + + /** + * 提取请求结果 + * @param request + * @param loggingContext + * @return + */ + protected Object extractResponseResult(HttpServletResponse response, LoggingContext loggingContext) throws Exception { + MediaType contentType = loggingContext.getHttpAccessLog().getResponseContentType(); + if(contentType != null){ + if(isContentCachingResponse(response)){ + String charset = response.getCharacterEncoding(); + if(StringUtils.isEmpty(charset)){ + charset = StringUtils.defaultIfEmpty(contentType.getCharset().name(), GlobalConstants.SYSTEM_DEFAULT_CHARSET); + } + ContentCachingResponseWrapper responseToUse = (ContentCachingResponseWrapper) response; + byte[] bytes = responseToUse.getContentAsByteArray(); + if(bytes != null){ + return IOUtils.toString(bytes, charset); + } + } + } + return null; + } + + protected MediaType getContentType(String contentType) { + try { + return MediaType.valueOf(contentType); + } catch (Exception e) { + return null; + } + } + + protected boolean isContentCachingRequest(ServletRequest request) { + if(request instanceof ContentCachingRequestWrapper){ + return true; + }else if(request instanceof HttpServletRequestWrapper) { + HttpServletRequestWrapper requestToUse = (HttpServletRequestWrapper) request; + return isContentCachingRequest(requestToUse.getRequest()); + } + return false; + } + + protected boolean isContentCachingResponse(ServletResponse response) { + if(response instanceof ContentCachingResponseWrapper){ + return true; + }else if(response instanceof HttpServletResponseWrapper) { + HttpServletResponseWrapper responseToUse = (HttpServletResponseWrapper) response; + return isContentCachingResponse(responseToUse.getResponse()); + } + return false; + } + + public void destroy() throws Exception { + getHttpAccessLogHandlerExecutor().shutdown(); + } + + /** + * 获取操作人的LoginUser对象 + * @param request + * @param loggingContext + * @return + */ + protected abstract T getAccessUser(HttpServletRequest request, LoggingContext loggingContext); + + /** + * 创建HttpRequestLogger处理器(如将日志写入数据库、日志文件等等) + * @param loggingContext + * @return + */ + protected abstract AbstractHttpAccessLogHandler createHttpAccessLoggerHandler(LoggingContext loggingContext); + + /** + * 日志记录上下文 + * + * @author pengpeng + * @date 2017年5月18日 下午1:16:18 + * @version 1.0 + */ + public static class LoggingContext { + + private HandlerMethod handlerMethod; + + private HttpAccessLogging httpAccessLogging; + + private HttpAccessLog httpAccessLog; + + private ModelAndView modelAndView; + + public HandlerMethod getHandlerMethod() { + return handlerMethod; + } + + public void setHandlerMethod(HandlerMethod handlerMethod) { + this.handlerMethod = handlerMethod; + } + + public HttpAccessLogging getHttpAccessLogging() { + return httpAccessLogging; + } + + public void setHttpAccessLogging(HttpAccessLogging httpAccessLogging) { + this.httpAccessLogging = httpAccessLogging; + } + + public HttpAccessLog getHttpAccessLog() { + return httpAccessLog; + } + + public void setHttpAccessLog(HttpAccessLog httpAccessLog) { + this.httpAccessLog = httpAccessLog; + } + + public ModelAndView getModelAndView() { + return modelAndView; + } + + public void setModelAndView(ModelAndView modelAndView) { + this.modelAndView = modelAndView; + } + + } + +} diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/DefaultTokenValueDAO.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/DefaultTokenValueDAO.java similarity index 92% rename from xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/DefaultTokenValueDAO.java rename to xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/DefaultTokenValueDAO.java index 4f09432..fc311c3 100644 --- a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/DefaultTokenValueDAO.java +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/DefaultTokenValueDAO.java @@ -1,4 +1,4 @@ -package com.certusnet.xproject.common.web.interceptor; +package com.certusnet.xproject.common.web.springmvc.interceptor; import java.util.UUID; diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/HttpAccessLog.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/HttpAccessLog.java new file mode 100644 index 0000000..8b4aa32 --- /dev/null +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/HttpAccessLog.java @@ -0,0 +1,298 @@ +package com.certusnet.xproject.common.web.springmvc.interceptor; + +import java.util.Map; + +import org.springframework.http.MediaType; + +/** + * 对Http请求的日志记录 + * + * @param + * @author pengpeng + * @date 2014年10月17日 下午7:24:39 + * @version 1.0 + */ +public class HttpAccessLog { + + /** + * 日志标题 + */ + private String title; + + /** + * 请求URI + */ + private String uri; + + /** + * 请求方法(GET/POST/PUT/DELETE/INPUT) + */ + private String method; + + /** + * 请求头 + */ + private Map requestHeader; + + /** + * 请求体类型 + */ + private MediaType requestContentType; + + /** + * 请求参数 + */ + private HttpRequestParameter requestParameter; + + /** + * 访问者 + */ + private T accessUser; + + /** + * 访问时间 + */ + private String accessTime; + + /** + * 访问者ip地址 + */ + private String clientIpAddr; + + /** + * 被访问的服务器地址+端口号 + */ + private String serverIpAddr; + + /** + * 访问开始系统毫秒数 + */ + private Long accessBeginMillis; + + /** + * 访问结束系统毫秒数 + */ + private Long accessEndMillis; + + /** + * 控制器方法的执行时长(毫秒) + * 理论上processTime1 < processTime2 + */ + private Long processTime1; + + /** + * 控制器方法执行完毕到页面渲染时长(毫秒) + * 理论上processTime1 < processTime2 + */ + private Long processTime2; + + /** + * 日志记录是否结束 + */ + private boolean loggingCompleted = false; + + /** + * 请求是否是异步的 + */ + private boolean asynRequest = false; + + /** + * 响应体类型 + */ + private MediaType responseContentType; + + /** + * 响应结果 + */ + private Object responseResult; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getUri() { + return uri; + } + + public void setUri(String uri) { + this.uri = uri; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + public Map getRequestHeader() { + return requestHeader; + } + + public void setRequestHeader(Map requestHeader) { + this.requestHeader = requestHeader; + } + + public MediaType getRequestContentType() { + return requestContentType; + } + + public void setRequestContentType(MediaType requestContentType) { + this.requestContentType = requestContentType; + } + + public HttpRequestParameter getRequestParameter() { + return requestParameter; + } + + public void setRequestParameter(HttpRequestParameter requestParameter) { + this.requestParameter = requestParameter; + } + + public T getAccessUser() { + return accessUser; + } + + public void setAccessUser(T accessUser) { + this.accessUser = accessUser; + } + + public String getAccessTime() { + return accessTime; + } + + public void setAccessTime(String accessTime) { + this.accessTime = accessTime; + } + + public String getClientIpAddr() { + return clientIpAddr; + } + + public void setClientIpAddr(String clientIpAddr) { + this.clientIpAddr = clientIpAddr; + } + + public String getServerIpAddr() { + return serverIpAddr; + } + + public void setServerIpAddr(String serverIpAddr) { + this.serverIpAddr = serverIpAddr; + } + + public Long getAccessBeginMillis() { + return accessBeginMillis; + } + + public void setAccessBeginMillis(Long accessBeginMillis) { + this.accessBeginMillis = accessBeginMillis; + } + + public Long getAccessEndMillis() { + return accessEndMillis; + } + + public void setAccessEndMillis(Long accessEndMillis) { + this.accessEndMillis = accessEndMillis; + } + + public Long getProcessTime1() { + return processTime1; + } + + public void setProcessTime1(Long processTime1) { + this.processTime1 = processTime1; + } + + public Long getProcessTime2() { + return processTime2; + } + + public void setProcessTime2(Long processTime2) { + this.processTime2 = processTime2; + } + + public boolean isLoggingCompleted() { + return loggingCompleted; + } + + public void setLoggingCompleted(boolean loggingCompleted) { + this.loggingCompleted = loggingCompleted; + } + + public boolean isAsynRequest() { + return asynRequest; + } + + public void setAsynRequest(boolean asynRequest) { + this.asynRequest = asynRequest; + } + + public MediaType getResponseContentType() { + return responseContentType; + } + + public void setResponseContentType(MediaType responseContentType) { + this.responseContentType = responseContentType; + } + + public Object getResponseResult() { + return responseResult; + } + + public void setResponseResult(Object responseResult) { + this.responseResult = responseResult; + } + + @Override + public String toString() { + return "HttpAccessLog [title=" + title + ", uri=" + uri + ", method=" + method + ", requestHeader=" + + requestHeader + ", requestContentType=" + requestContentType + ", requestParameter=" + + requestParameter + ", accessUser=" + accessUser + ", accessTime=" + accessTime + ", clientIpAddr=" + + clientIpAddr + ", serverIpAddr=" + serverIpAddr + ", accessBeginMillis=" + accessBeginMillis + + ", accessEndMillis=" + accessEndMillis + ", processTime1=" + processTime1 + ", processTime2=" + + processTime2 + ", loggingCompleted=" + loggingCompleted + ", asynRequest=" + asynRequest + + ", responseContentType=" + responseContentType + ", responseResult=" + responseResult + "]"; + } + + public static class HttpRequestParameter { + + /** + * 请求参数 + */ + private Map parameter; + + /** + * 请求体 + */ + private Object body; + + public Map getParameter() { + return parameter; + } + + public void setParameter(Map parameter) { + this.parameter = parameter; + } + + public Object getBody() { + return body; + } + + public void setBody(Object body) { + this.body = body; + } + + public String toString() { + return "[parameter=" + parameter + ", body=" + body + "]"; + } + + } + +} diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/RepeatSubmitException.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/RepeatSubmitException.java similarity index 84% rename from xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/RepeatSubmitException.java rename to xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/RepeatSubmitException.java index 1b518d8..27f5a0d 100644 --- a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/RepeatSubmitException.java +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/RepeatSubmitException.java @@ -1,4 +1,4 @@ -package com.certusnet.xproject.common.web.interceptor; +package com.certusnet.xproject.common.web.springmvc.interceptor; import com.certusnet.xproject.common.exception.SystemException; diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/ShiroTokenValueDAO.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/ShiroTokenValueDAO.java similarity index 93% rename from xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/ShiroTokenValueDAO.java rename to xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/ShiroTokenValueDAO.java index 981f330..cf43e2d 100644 --- a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/ShiroTokenValueDAO.java +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/ShiroTokenValueDAO.java @@ -1,4 +1,4 @@ -package com.certusnet.xproject.common.web.interceptor; +package com.certusnet.xproject.common.web.springmvc.interceptor; import java.util.UUID; diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/Token.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/Token.java similarity index 89% rename from xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/Token.java rename to xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/Token.java index 27b778d..1e98507 100644 --- a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/Token.java +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/Token.java @@ -1,4 +1,4 @@ -package com.certusnet.xproject.common.web.interceptor; +package com.certusnet.xproject.common.web.springmvc.interceptor; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/TokenAction.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/TokenAction.java similarity index 82% rename from xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/TokenAction.java rename to xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/TokenAction.java index cb8e162..b301f49 100644 --- a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/TokenAction.java +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/TokenAction.java @@ -1,4 +1,4 @@ -package com.certusnet.xproject.common.web.interceptor; +package com.certusnet.xproject.common.web.springmvc.interceptor; /** * 防重复提交token的动作 * diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/TokenInterceptor.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/TokenInterceptor.java similarity index 98% rename from xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/TokenInterceptor.java rename to xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/TokenInterceptor.java index e13fc5e..4d7a6ee 100644 --- a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/TokenInterceptor.java +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/TokenInterceptor.java @@ -1,4 +1,4 @@ -package com.certusnet.xproject.common.web.interceptor; +package com.certusnet.xproject.common.web.springmvc.interceptor; import java.lang.reflect.Method; diff --git a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/TokenValueDAO.java b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/TokenValueDAO.java similarity index 92% rename from xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/TokenValueDAO.java rename to xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/TokenValueDAO.java index d1f27ea..d6009a3 100644 --- a/xproject-common/src/main/java/com/certusnet/xproject/common/web/interceptor/TokenValueDAO.java +++ b/xproject-common/src/main/java/com/certusnet/xproject/common/web/springmvc/interceptor/TokenValueDAO.java @@ -1,4 +1,4 @@ -package com.certusnet.xproject.common.web.interceptor; +package com.certusnet.xproject.common.web.springmvc.interceptor; import javax.servlet.http.HttpServletRequest; /** diff --git a/xproject-iface/src/main/java/com/certusnet/xproject/admin/service/AdminUserAccessLogService.java b/xproject-iface/src/main/java/com/certusnet/xproject/admin/service/AdminUserAccessLogService.java new file mode 100644 index 0000000..95b037a --- /dev/null +++ b/xproject-iface/src/main/java/com/certusnet/xproject/admin/service/AdminUserAccessLogService.java @@ -0,0 +1,39 @@ +package com.certusnet.xproject.admin.service; + +import com.certusnet.xproject.admin.model.AdminUserAccessLog; +import com.certusnet.xproject.common.support.OrderBy; +import com.certusnet.xproject.common.support.Pager; +import com.certusnet.xproject.common.support.PagingList; + +/** + * 用户操作日志Service + * + * @author pengpeng + * @date 2017年5月13日 上午11:29:18 + * @version 1.0 + */ +public interface AdminUserAccessLogService { + + /** + * 记录用户操作日志 + * @param accessLog + */ + public void recordUserAccessLog(AdminUserAccessLog accessLog); + + /** + * 根据日志ID获取日志详情 + * @param id + * @return + */ + public AdminUserAccessLog getUserAccessLogById(Long id); + + /** + * 根据条件查询日志列表 + * @param condition + * @param pager + * @param orderBy + * @return + */ + public PagingList getUserAccessLogList(AdminUserAccessLog condition, Pager pager, OrderBy orderBy); + +} diff --git a/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/AdminRoleDAO.java b/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/AdminRoleDAO.java index 22ed69b..4726895 100644 --- a/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/AdminRoleDAO.java +++ b/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/AdminRoleDAO.java @@ -49,12 +49,12 @@ public interface AdminRoleDAO { /** * 根据【角色名称、角色代码】查询角色列表(分页) - * @param role + * @param condition * @param pager - * @param orderby + * @param orderBy * @return */ - public List getRoleList(AdminRole role, Pager pager, OrderBy orderby); + public List getRoleList(AdminRole condition, Pager pager, OrderBy orderBy); /** * 获取该角色的看见资源 diff --git a/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/AdminUserAccessLogDAO.java b/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/AdminUserAccessLogDAO.java new file mode 100644 index 0000000..c8c72a2 --- /dev/null +++ b/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/AdminUserAccessLogDAO.java @@ -0,0 +1,40 @@ +package com.certusnet.xproject.admin.dao; + +import java.util.List; + +import com.certusnet.xproject.admin.model.AdminUserAccessLog; +import com.certusnet.xproject.common.support.OrderBy; +import com.certusnet.xproject.common.support.Pager; + +/** + * 用户操作日志DAO + * + * @author pengpeng + * @date 2017年5月13日 上午11:29:18 + * @version 1.0 + */ +public interface AdminUserAccessLogDAO { + + /** + * 插入操作日志 + * @param accessLog + */ + public void insertUserAccessLog(AdminUserAccessLog accessLog); + + /** + * 根据日志ID获取日志详情 + * @param id + * @return + */ + public AdminUserAccessLog getUserAccessLogById(Long id); + + /** + * 根据条件查询日志列表 + * @param condition + * @param pager + * @param orderBy + * @return + */ + public List getUserAccessLogList(AdminUserAccessLog condition, Pager pager, OrderBy orderBy); + +} diff --git a/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/AdminUserDAO.java b/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/AdminUserDAO.java index 4ff58c2..f0f5fe2 100644 --- a/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/AdminUserDAO.java +++ b/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/AdminUserDAO.java @@ -16,8 +16,7 @@ * @date 2015年12月10日 下午1:49:33 * @version 1.0 */ -public interface AdminUserDAO -{ +public interface AdminUserDAO { /** * 新增用户 * @@ -81,12 +80,12 @@ public interface AdminUserDAO /** * 根据[用户名、用户状态、用户类型]查询用户列表(分页、排序) * - * @param user + * @param condition * @param pager - * @param orderby + * @param orderBy * @return */ - public List getUserList(AdminUser user, Pager pager, OrderBy orderby); + public List getUserList(AdminUser condition, Pager pager, OrderBy orderBy); /** * 获取用户所拥有的角色 diff --git a/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/impl/AdminResourceDAOImpl.java b/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/impl/AdminResourceDAOImpl.java index 7fbe7b5..53b04d4 100644 --- a/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/impl/AdminResourceDAOImpl.java +++ b/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/impl/AdminResourceDAOImpl.java @@ -30,26 +30,26 @@ public void deleteResourceByIds(Long... resourceIds) { } public AdminResource getResourceById(Long resourceId) { - return this.getSqlSessionTemplate().selectOne(getMapperKey("selectResourceById"), resourceId, new AdminResourceModelHandler()); + return this.getSqlSessionTemplate().selectOne(getMapperKey("getResourceById"), resourceId, new AdminResourceModelHandler()); } public AdminResource getThinResourceById(Long resourceId, boolean fetchInuse) { Map paramMap = new HashMap(); paramMap.put("resourceId", resourceId); paramMap.put("fetchInuse", fetchInuse); - return this.getSqlSessionTemplate().selectOne(getMapperKey("selectThinResourceById"), paramMap); + return this.getSqlSessionTemplate().selectOne(getMapperKey("getThinResourceById"), paramMap); } public List getAllResourceList(Integer actionType) { Map paramMap = new HashMap(); paramMap.put("actionType", actionType); - return this.getSqlSessionTemplate().selectList(getMapperKey("selectAllResourceList"), paramMap, new AdminResourceModelHandler()); + return this.getSqlSessionTemplate().selectList(getMapperKey("getAllResourceList"), paramMap, new AdminResourceModelHandler()); } public List getAllThinResourceList(boolean fetchInuse) { Map paramMap = new HashMap(); paramMap.put("fetchInuse", fetchInuse); - return this.getSqlSessionTemplate().selectList(getMapperKey("selectAllThinResourceList"), paramMap); + return this.getSqlSessionTemplate().selectList(getMapperKey("getAllThinResourceList"), paramMap); } protected Class getBoundModelClass() { diff --git a/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/impl/AdminRoleDAOImpl.java b/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/impl/AdminRoleDAOImpl.java index 5c9215d..a672427 100644 --- a/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/impl/AdminRoleDAOImpl.java +++ b/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/impl/AdminRoleDAOImpl.java @@ -31,24 +31,22 @@ public void deleteRoleById(Long roleId) { } public AdminRole getThinRoleById(Long roleId) { - return this.getSqlSessionTemplate().selectOne(getMapperKey("selectThinRoleById"), roleId); + return this.getSqlSessionTemplate().selectOne(getMapperKey("getThinRoleById"), roleId); } public AdminRole getRoleById(Long roleId) { - return this.getSqlSessionTemplate().selectOne(getMapperKey("selectRoleById"), roleId, new AdminRoleModelHandler()); + return this.getSqlSessionTemplate().selectOne(getMapperKey("getRoleById"), roleId, new AdminRoleModelHandler()); } - public List getRoleList(AdminRole role, Pager pager, OrderBy orderby) { + public List getRoleList(AdminRole condition, Pager pager, OrderBy orderBy) { Map paramMap = new HashMap(); - paramMap.put("roleName", role.getRoleName()); - paramMap.put("roleCode", role.getRoleCode()); - paramMap.put("orderby", orderby.getOrderby()); - paramMap.put("order", orderby.getOrder()); - return this.getSqlSessionTemplate().selectList(getMapperKey("selectRoleList"), paramMap, new AdminRoleModelHandler(), pager); + paramMap.put("condition", condition); + paramMap.put("orderBy", orderBy); + return this.getSqlSessionTemplate().selectList(getMapperKey("getRoleList"), paramMap, new AdminRoleModelHandler(), pager); } public List getResourceListByRoleId(Long roleId) { - return this.getSqlSessionTemplate().selectList(getMapperKey("selectResourceListByRoleId"), roleId); + return this.getSqlSessionTemplate().selectList(getMapperKey("getResourceListByRoleId"), roleId); } public void deleteRoleResourcesByRoleId(Long roleId) { diff --git a/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/impl/AdminUserAccessLogDAOImpl.java b/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/impl/AdminUserAccessLogDAOImpl.java new file mode 100644 index 0000000..c2e562c --- /dev/null +++ b/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/impl/AdminUserAccessLogDAOImpl.java @@ -0,0 +1,37 @@ +package com.certusnet.xproject.admin.dao.impl; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Repository; + +import com.certusnet.xproject.admin.dao.AdminUserAccessLogDAO; +import com.certusnet.xproject.admin.model.AdminUserAccessLog; +import com.certusnet.xproject.common.mybatis.DefaultBaseMybatisDAO; +import com.certusnet.xproject.common.support.OrderBy; +import com.certusnet.xproject.common.support.Pager; + +@Repository("adminUserAccessLogDAO") +public class AdminUserAccessLogDAOImpl extends DefaultBaseMybatisDAO implements AdminUserAccessLogDAO { + + public void insertUserAccessLog(AdminUserAccessLog accessLog) { + this.getSqlSessionTemplate().insert(getMapperKey("insertUserAccessLog"), accessLog); + } + + public AdminUserAccessLog getUserAccessLogById(Long id) { + return this.getSqlSessionTemplate().selectOne(getMapperKey("getUserAccessLogById"), id); + } + + public List getUserAccessLogList(AdminUserAccessLog condition, Pager pager, OrderBy orderBy) { + Map paramMap = new HashMap(); + paramMap.put("condition", condition); + paramMap.put("orderBy", orderBy); + return this.getSqlSessionTemplate().selectList(getMapperKey("getUserAccessLogList"), paramMap, pager); + } + + protected Class getBoundModelClass() { + return AdminUserAccessLog.class; + } + +} diff --git a/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/impl/AdminUserDAOImpl.java b/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/impl/AdminUserDAOImpl.java index 0649993..6ad1868 100644 --- a/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/impl/AdminUserDAOImpl.java +++ b/xproject-service/src/main/java/com/certusnet/xproject/admin/dao/impl/AdminUserDAOImpl.java @@ -63,14 +63,10 @@ public AdminUser getThinUserById(Long userId) { return getSqlSessionTemplate().selectOne(getMapperKey("getThinUserById"), userId); } - public List getUserList(AdminUser user, Pager pager, OrderBy orderby) { + public List getUserList(AdminUser condition, Pager pager, OrderBy orderBy) { Map paramMap = new HashMap(); - paramMap.put("userName", user.getUserName()); - paramMap.put("realName", user.getRealName()); - paramMap.put("userType", user.getUserType()); - paramMap.put("status", user.getStatus()); - paramMap.put("orderby", orderby.getOrderby()); - paramMap.put("order", orderby.getOrder()); + paramMap.put("condition", condition); + paramMap.put("orderBy", orderBy); return getSqlSessionTemplate().selectList(getMapperKey("getUserList"), paramMap, new AdminUserModelHandler(), pager); } diff --git a/xproject-service/src/main/java/com/certusnet/xproject/admin/service/impl/AdminResourceServiceImpl.java b/xproject-service/src/main/java/com/certusnet/xproject/admin/service/impl/AdminResourceServiceImpl.java index 7cdd147..82bcaf7 100644 --- a/xproject-service/src/main/java/com/certusnet/xproject/admin/service/impl/AdminResourceServiceImpl.java +++ b/xproject-service/src/main/java/com/certusnet/xproject/admin/service/impl/AdminResourceServiceImpl.java @@ -23,7 +23,7 @@ public class AdminResourceServiceImpl implements AdminResourceService { @Resource(name="adminResourceDAO") - private AdminResourceDAO resourceDAO; + private AdminResourceDAO adminResourceDAO; @Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRED) public void createResource(AdminResource resource) { @@ -31,7 +31,7 @@ public void createResource(AdminResource resource) { try { resource.setPermissionExpression(StringUtils.defaultIfEmpty(resource.getPermissionExpression(), null)); resource.setResourceUrl(StringUtils.defaultIfEmpty(resource.getResourceUrl(), null)); - resourceDAO.insertResource(resource); + adminResourceDAO.insertResource(resource); } catch(DuplicateKeyException e) { BusinessAssert.isTrue(!e.getCause().getMessage().toUpperCase().contains("RESOURCE_NAME"), "新增资源失败,该资源名称已经存在!"); BusinessAssert.isTrue(!e.getCause().getMessage().toUpperCase().contains("PERMISSION_EXPRESSION"), "新增资源失败,该权限表达式已经存在!"); @@ -45,10 +45,10 @@ public void updateResource(AdminResource resource) { ValidationAssert.notNull(resource.getResourceId(), "资源id不能为空!"); resource.setPermissionExpression(StringUtils.defaultIfEmpty(resource.getPermissionExpression(), null)); resource.setResourceUrl(StringUtils.defaultIfEmpty(resource.getResourceUrl(), null)); - AdminResource presource = resourceDAO.getThinResourceById(resource.getResourceId(), true); + AdminResource presource = adminResourceDAO.getThinResourceById(resource.getResourceId(), true); ValidationAssert.notNull(presource, "该资源已经不存在了!"); try { - resourceDAO.updateResource(resource); + adminResourceDAO.updateResource(resource); } catch(DuplicateKeyException e) { BusinessAssert.isTrue(!e.getCause().getMessage().toUpperCase().contains("RESOURCE_NAME"), "修改资源失败,该资源名称已经存在!"); BusinessAssert.isTrue(!e.getCause().getMessage().toUpperCase().contains("PERMISSION_EXPRESSION"), "修改资源失败,该权限表达式已经存在!"); @@ -59,12 +59,12 @@ public void updateResource(AdminResource resource) { @Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRED) public void deleteResourceById(Long resourceId, boolean cascadeDelete) { ValidationAssert.notNull(resourceId, "资源id不能为空!"); - AdminResource delResource = resourceDAO.getThinResourceById(resourceId, true); + AdminResource delResource = adminResourceDAO.getThinResourceById(resourceId, true); ValidationAssert.notNull(delResource, "该资源已经不存在了!"); BusinessAssert.isTrue(!AdminResourceTypeEnum.ADMIN_RESOURCE_TYPE_SYSTEM.getTypeCode().equals(delResource.getResourceType()), "删除资源失败,系统资源不允许删除!"); BusinessAssert.isTrue(!delResource.isInuse(), String.format("删除资源失败,资源[%s]已经在使用不允许删除!", delResource.getResourceName())); if(cascadeDelete){ - List allThinResourceList = resourceDAO.getAllThinResourceList(true); + List allThinResourceList = adminResourceDAO.getAllThinResourceList(true); if(!CollectionUtils.isEmpty(allThinResourceList)){ List childResourceList = new ArrayList(); for(AdminResource resource : allThinResourceList){ @@ -81,10 +81,10 @@ public void deleteResourceById(Long resourceId, boolean cascadeDelete) { for(int i = 0, len = childResourceList.size(); i < len; i++){ delResourceIds[i] = childResourceList.get(i).getResourceId(); } - resourceDAO.deleteResourceByIds(delResourceIds); + adminResourceDAO.deleteResourceByIds(delResourceIds); } }else{ - resourceDAO.deleteResourceByIds(resourceId); + adminResourceDAO.deleteResourceByIds(resourceId); } } @@ -124,19 +124,19 @@ public void loadTreeResources(List objTreeList, List getAllThinResourceList(boolean fetchInuse) { - return resourceDAO.getAllThinResourceList(fetchInuse); + return adminResourceDAO.getAllThinResourceList(fetchInuse); } public List getAllResourceList(Integer actionType) { - return resourceDAO.getAllResourceList(actionType); + return adminResourceDAO.getAllResourceList(actionType); } } \ No newline at end of file diff --git a/xproject-service/src/main/java/com/certusnet/xproject/admin/service/impl/AdminRoleServiceImpl.java b/xproject-service/src/main/java/com/certusnet/xproject/admin/service/impl/AdminRoleServiceImpl.java index abe1ea4..68da656 100644 --- a/xproject-service/src/main/java/com/certusnet/xproject/admin/service/impl/AdminRoleServiceImpl.java +++ b/xproject-service/src/main/java/com/certusnet/xproject/admin/service/impl/AdminRoleServiceImpl.java @@ -25,13 +25,13 @@ public class AdminRoleServiceImpl implements AdminRoleService { @Resource(name="adminRoleDAO") - private AdminRoleDAO roleDAO; + private AdminRoleDAO adminRoleDAO; @Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRED) public void createRole(AdminRole role) { ValidationAssert.notNull(role, "参数不能为空!"); try { - roleDAO.insertRole(role); + adminRoleDAO.insertRole(role); } catch(DuplicateKeyException e) { BusinessAssert.isTrue(!e.getCause().getMessage().toUpperCase().contains("ROLE_NAME"), "新增角色失败,该角色名称已经存在!"); BusinessAssert.isTrue(!e.getCause().getMessage().toUpperCase().contains("ROLE_CODE"), "新增角色失败,该角色代码已经存在!"); @@ -42,10 +42,10 @@ public void createRole(AdminRole role) { public void updateRole(AdminRole role) { ValidationAssert.notNull(role, "参数不能为空!"); ValidationAssert.notNull(role.getRoleId(), "角色ID不能为空!"); - AdminRole prole = roleDAO.getThinRoleById(role.getRoleId()); + AdminRole prole = adminRoleDAO.getThinRoleById(role.getRoleId()); ValidationAssert.notNull(prole, "该角色已经不存在了!"); try { - roleDAO.updateRole(role); + adminRoleDAO.updateRole(role); } catch(DuplicateKeyException e) { BusinessAssert.isTrue(!e.getCause().getMessage().toUpperCase().contains("ROLE_NAME"), "修改角色失败,该角色名称已经存在!"); BusinessAssert.isTrue(!e.getCause().getMessage().toUpperCase().contains("ROLE_CODE"), "修改角色失败,该角色代码已经存在!"); @@ -55,34 +55,34 @@ public void updateRole(AdminRole role) { @Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRED) public void deleteRoleById(Long roleId) { ValidationAssert.notNull(roleId, "角色ID不能为空!"); - AdminRole role = roleDAO.getThinRoleById(roleId); + AdminRole role = adminRoleDAO.getThinRoleById(roleId); ValidationAssert.notNull(role, "该角色已经不存在了!"); BusinessAssert.isTrue(!AdminRoleTypeEnum.ADMIN_ROLE_TYPE_SYSTEM.getTypeCode().equals(role.getRoleType()), "删除角色失败,系统角色不允许删除!"); BusinessAssert.isTrue(!role.isInuse(), "删除角色失败,该角色已经在使用不允许删除!"); - roleDAO.deleteRoleById(roleId); //删除角色信息 - roleDAO.deleteRoleResourcesByRoleId(roleId); //删除该角色下的所有资源关系 + adminRoleDAO.deleteRoleById(roleId); //删除角色信息 + adminRoleDAO.deleteRoleResourcesByRoleId(roleId); //删除该角色下的所有资源关系 } public AdminRole getRoleById(Long roleId) { - return roleDAO.getRoleById(roleId); + return adminRoleDAO.getRoleById(roleId); } public PagingList getRoleList(AdminRole role, Pager pager, OrderBy orderby) { - List dataList = roleDAO.getRoleList(role, pager, orderby); + List dataList = adminRoleDAO.getRoleList(role, pager, orderby); return new PagingList(dataList, pager.getTotalRowCount()); } public List getResourceListByRoleId(Long roleId) { - return roleDAO.getResourceListByRoleId(roleId); + return adminRoleDAO.getResourceListByRoleId(roleId); } @Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRED) public void configRoleResources(Long roleId, List resourceIdList, Long optUserId, String optTime) { - AdminRole role = roleDAO.getThinRoleById(roleId); + AdminRole role = adminRoleDAO.getThinRoleById(roleId); ValidationAssert.notNull(role, "该角色已经不存在了!"); - roleDAO.deleteRoleResourcesByRoleId(roleId); + adminRoleDAO.deleteRoleResourcesByRoleId(roleId); if(!CollectionUtils.isEmpty(resourceIdList)){ - roleDAO.insertRoleResources(roleId, resourceIdList, optUserId, optTime); + adminRoleDAO.insertRoleResources(roleId, resourceIdList, optUserId, optTime); } } diff --git a/xproject-service/src/main/java/com/certusnet/xproject/admin/service/impl/AdminUserAccessLogServiceImpl.java b/xproject-service/src/main/java/com/certusnet/xproject/admin/service/impl/AdminUserAccessLogServiceImpl.java new file mode 100644 index 0000000..e163692 --- /dev/null +++ b/xproject-service/src/main/java/com/certusnet/xproject/admin/service/impl/AdminUserAccessLogServiceImpl.java @@ -0,0 +1,38 @@ +package com.certusnet.xproject.admin.service.impl; + +import java.util.List; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import com.certusnet.xproject.admin.dao.AdminUserAccessLogDAO; +import com.certusnet.xproject.admin.model.AdminUserAccessLog; +import com.certusnet.xproject.admin.service.AdminUserAccessLogService; +import com.certusnet.xproject.common.support.OrderBy; +import com.certusnet.xproject.common.support.Pager; +import com.certusnet.xproject.common.support.PagingList; + +@Service("adminUserAccessLogService") +public class AdminUserAccessLogServiceImpl implements AdminUserAccessLogService { + + @Resource(name="adminUserAccessLogDAO") + private AdminUserAccessLogDAO adminUserAccessLogDAO; + + @Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRED) + public void recordUserAccessLog(AdminUserAccessLog accessLog) { + adminUserAccessLogDAO.insertUserAccessLog(accessLog); + } + + public AdminUserAccessLog getUserAccessLogById(Long id) { + return adminUserAccessLogDAO.getUserAccessLogById(id); + } + + public PagingList getUserAccessLogList(AdminUserAccessLog condition, Pager pager, OrderBy orderBy) { + List dataList = adminUserAccessLogDAO.getUserAccessLogList(condition, pager, orderBy); + return new PagingList(dataList, pager.getTotalRowCount()); + } + +} diff --git a/xproject-service/src/main/java/com/certusnet/xproject/admin/service/impl/AdminUserServiceImpl.java b/xproject-service/src/main/java/com/certusnet/xproject/admin/service/impl/AdminUserServiceImpl.java index 12072ad..be782ab 100644 --- a/xproject-service/src/main/java/com/certusnet/xproject/admin/service/impl/AdminUserServiceImpl.java +++ b/xproject-service/src/main/java/com/certusnet/xproject/admin/service/impl/AdminUserServiceImpl.java @@ -29,14 +29,14 @@ public class AdminUserServiceImpl implements AdminUserService { @Resource(name = "adminUserDAO") - private AdminUserDAO userDAO; + private AdminUserDAO adminUserDAO; @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) public void createUser(AdminUser user) { ValidationAssert.notNull(user, "参数不能为空!"); try { user.setEncryptedPassword(UserPasswdUtils.encryptPassword(user.getPassword(), user.getPasswordSalt(), GlobalConstants.DEFAULT_PASSWORD_HASH_ITERATIONS)); - userDAO.insertUser(user); + adminUserDAO.insertUser(user); } catch (DuplicateKeyException e) { BusinessAssert.isTrue(!e.getCause().getMessage().toUpperCase().contains("USER_NAME"), "对不起,该用户名已存在!"); @@ -49,7 +49,7 @@ public void updateUser(AdminUser user) { ValidationAssert.notNull(user, "参数不能为空!"); ValidationAssert.notNull(user.getUserId(), "用户id不能为空!"); try { - userDAO.updateUser(user); + adminUserDAO.updateUser(user); } catch (DuplicateKeyException e) { BusinessAssert.isTrue(!e.getCause().getMessage().toUpperCase().contains("USER_NAME"), "对不起,该用户名已存在!"); @@ -64,7 +64,7 @@ public void updatePassword(AdminUser user, boolean forceUpdate) { ValidationAssert.notEmpty(user.getPassword(), "新密码不能为空!"); ValidationAssert.notEmpty(user.getRepassword(), "重复新密码不能为空!"); ValidationAssert.isTrue(user.getPassword().equals(user.getRepassword()), "两次输入新密码不一致!"); - AdminUser puser = userDAO.getThinUserById(user.getUserId()); + AdminUser puser = adminUserDAO.getThinUserById(user.getUserId()); ValidationAssert.notNull(user, "该用户已经不存在了!"); if (!forceUpdate) { ValidationAssert.notNull(user.getOldpassword(), "旧密码不能为空!"); @@ -75,19 +75,19 @@ public void updatePassword(AdminUser user, boolean forceUpdate) { user.setCreateTime(puser.getCreateTime()); user.setEncryptedPassword(UserPasswdUtils.encryptPassword(user.getPassword(), user.getPasswordSalt(), GlobalConstants.DEFAULT_PASSWORD_HASH_ITERATIONS)); user.setUpdateTime(DateTimeUtils.formatNow()); - userDAO.updatePassword(user); + adminUserDAO.updatePassword(user); } @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) public void deleteUserById(AdminUser user) { ValidationAssert.notNull(user, "参数不能为空!"); ValidationAssert.notNull(user.getUserId(), "用户id不能为空!"); - AdminUser puser = userDAO.getThinUserById(user.getUserId()); + AdminUser puser = adminUserDAO.getThinUserById(user.getUserId()); ValidationAssert.notNull(puser, "该用户已经不存在了!"); BusinessAssert.isTrue(!AdminUserTypeEnum.ADMIN_USER_TYPE_SYSTEM.getTypeCode().equals(puser.getUserType()), "系统级用户不能被删除!"); user.setUserName(puser.getUserName()); - userDAO.deleteUserById(user.getUserId()); //删除用户信息 - userDAO.deleteUserAllRoles(user.getUserId()); //删除用户的所有角色关系 + adminUserDAO.deleteUserById(user.getUserId()); //删除用户信息 + adminUserDAO.deleteUserAllRoles(user.getUserId()); //删除用户的所有角色关系 } @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) @@ -96,62 +96,62 @@ public void updateUserStatus(AdminUser user) { ValidationAssert.notNull(user.getUserId(), "用户id不能为空!"); AdminUserStatusEnum emStatus = AdminUserStatusEnum.getStatus(user.getStatus()); ValidationAssert.notNull(emStatus, String.format("无法识别的用户状态(status=%s)!", user.getStatus())); - AdminUser puser = userDAO.getThinUserById(user.getUserId()); + AdminUser puser = adminUserDAO.getThinUserById(user.getUserId()); ValidationAssert.notNull(puser, "该用户已经不存在了!"); user.setUserName(puser.getUserName()); - userDAO.updateUserStatus(user.getUserId(), emStatus); + adminUserDAO.updateUserStatus(user.getUserId(), emStatus); } @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) public void updateLoginTime(Long userId, String lastLoginTime) { ValidationAssert.notNull(userId, "用户id不能为空!"); ValidationAssert.notEmpty(lastLoginTime, "登录时间不能为空!"); - userDAO.updateLoginTime(userId, lastLoginTime); + adminUserDAO.updateLoginTime(userId, lastLoginTime); } public AdminUser getUserById(Long userId) { - return userDAO.getUserById(userId); + return adminUserDAO.getUserById(userId); } public PagingList getUserList(AdminUser user, Pager pager, OrderBy orderby) { - List dataList = userDAO.getUserList(user, pager, orderby); + List dataList = adminUserDAO.getUserList(user, pager, orderby); return new PagingList(dataList, pager.getTotalRowCount()); } public List getUserRoleList(Long userId, AdminRole filterParam) { - return userDAO.getUserRoleList(userId, filterParam); + return adminUserDAO.getUserRoleList(userId, filterParam); } public List getUserRoleList(Long userId) { - return userDAO.getUserRoleList(userId, null); + return adminUserDAO.getUserRoleList(userId, null); } public List getUserResourceList(Long userId) { - return userDAO.getUserResourceList(userId); + return adminUserDAO.getUserResourceList(userId); } @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) public void addUserRoles(AdminUser user, List roleIdList, Long optUserId, String optTime) { ValidationAssert.notNull(user, "参数不能为空!"); ValidationAssert.notNull(user.getUserId(), "用户id不能为空!"); - AdminUser puser = userDAO.getThinUserById(user.getUserId()); + AdminUser puser = adminUserDAO.getThinUserById(user.getUserId()); ValidationAssert.notNull(puser, "该用户已经不存在了!"); user.setUserName(puser.getUserName()); - userDAO.insertUserRoles(user.getUserId(), roleIdList, optUserId, optTime); + adminUserDAO.insertUserRoles(user.getUserId(), roleIdList, optUserId, optTime); } @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) public void delUserRoles(AdminUser user, List roleIdList) { ValidationAssert.notNull(user, "参数不能为空!"); ValidationAssert.notNull(user.getUserId(), "用户id不能为空!"); - AdminUser puser = userDAO.getThinUserById(user.getUserId()); + AdminUser puser = adminUserDAO.getThinUserById(user.getUserId()); ValidationAssert.notNull(puser, "该用户已经不存在了!"); user.setUserName(puser.getUserName()); - userDAO.deleteUserRoles(user.getUserId(), roleIdList); + adminUserDAO.deleteUserRoles(user.getUserId(), roleIdList); } public AdminUser getUserByUserName(String userName, boolean fatUser) { - return userDAO.getUserByUserName(userName, fatUser); + return adminUserDAO.getUserByUserName(userName, fatUser); } } diff --git a/xproject-service/src/main/resources/mybatis/mapper/AdminResourceMapper.xml b/xproject-service/src/main/resources/mybatis/mapper/AdminResourceMapper.xml index 5164fd6..27e5de4 100644 --- a/xproject-service/src/main/resources/mybatis/mapper/AdminResourceMapper.xml +++ b/xproject-service/src/main/resources/mybatis/mapper/AdminResourceMapper.xml @@ -49,7 +49,7 @@ WHERE a.resource_id = #{resourceId, jdbcType=BIGINT} - SELECT a.resource_id resourceId, a.resource_name resourceName, a.parent_resource_id parentResourceId, @@ -71,7 +71,7 @@ WHERE a.resource_id = #{resourceId, jdbcType=BIGINT} - SELECT a.resource_id resourceId, a.resource_name resourceName, a.parent_resource_id parentResourceId, @@ -84,7 +84,7 @@ WHERE a.resource_id = #{resourceId, jdbcType=BIGINT} - SELECT a.resource_id resourceId, a.resource_name resourceName, a.parent_resource_id parentResourceId, @@ -103,7 +103,7 @@ - SELECT a.resource_id resourceId, a.resource_name resourceName, a.parent_resource_id parentResourceId, diff --git a/xproject-service/src/main/resources/mybatis/mapper/AdminRoleMapper.xml b/xproject-service/src/main/resources/mybatis/mapper/AdminRoleMapper.xml index 8cd93c6..b8e527d 100644 --- a/xproject-service/src/main/resources/mybatis/mapper/AdminRoleMapper.xml +++ b/xproject-service/src/main/resources/mybatis/mapper/AdminRoleMapper.xml @@ -37,7 +37,7 @@ WHERE a.role_id = #{roleId, jdbcType=BIGINT} - SELECT a.role_id roleId, a.role_name roleName, a.role_code roleCode, @@ -47,7 +47,7 @@ WHERE a.role_id = #{roleId, jdbcType=BIGINT} - SELECT a.role_id roleId, a.role_name roleName, a.role_code roleCode, @@ -64,7 +64,7 @@ WHERE a.role_id = #{roleId, jdbcType=BIGINT} - SELECT a.role_id roleId, a.role_name roleName, a.role_code roleCode, @@ -78,30 +78,30 @@ (SELECT count(*) FROM admin_user_role b WHERE a.role_id = b.role_id) inuse FROM admin_role a WHERE 1=1 - - AND a.role_name like CONCAT('%', #{roleName, jdbcType=VARCHAR}, '%') + + AND a.role_name like CONCAT('%', #{condition.roleName, jdbcType=VARCHAR}, '%') - - AND a.role_code like CONCAT('%', #{roleCode, jdbcType=VARCHAR}, '%') + + AND a.role_code like CONCAT('%', #{condition.roleCode, jdbcType=VARCHAR}, '%') - - ORDER BY ${orderby} ${order} + + ORDER BY ${orderBy.orderby} ${orderBy.order} - SELECT count(*) FROM admin_role a WHERE 1=1 - - AND a.role_name like CONCAT('%', #{roleName, jdbcType=VARCHAR}, '%') + + AND a.role_name like CONCAT('%', #{condition.roleName, jdbcType=VARCHAR}, '%') - - AND a.role_code like CONCAT('%', #{roleCode, jdbcType=VARCHAR}, '%') + + AND a.role_code like CONCAT('%', #{condition.roleCode, jdbcType=VARCHAR}, '%') - SELECT a.resource_id resourceId, a.resource_name resourceName, a.parent_resource_id parentResourceId, diff --git a/xproject-service/src/main/resources/mybatis/mapper/AdminUserAccessLogMapper.xml b/xproject-service/src/main/resources/mybatis/mapper/AdminUserAccessLogMapper.xml new file mode 100644 index 0000000..ba4ef12 --- /dev/null +++ b/xproject-service/src/main/resources/mybatis/mapper/AdminUserAccessLogMapper.xml @@ -0,0 +1,146 @@ + + + + + + INSERT INTO admin_user_access_log ( + id, + title, + uri, + method, + request_header, + request_contenttype, + request_parameter, + access_user_id, + access_time, + client_ipaddr, + server_ipaddr, + process_time1, + process_time2, + logging_completed, + asyn_request, + response_contenttype, + response_result, + create_time + ) VALUES ( + #{id, jdbcType=BIGINT}, + #{title, jdbcType=VARCHAR}, + #{uri, jdbcType=VARCHAR}, + #{method, jdbcType=VARCHAR}, + #{requestHeader, jdbcType=VARCHAR}, + #{requestContentType, jdbcType=VARCHAR}, + #{requestParameter, jdbcType=VARCHAR}, + #{accessUserId, jdbcType=BIGINT}, + #{accessTime, jdbcType=VARCHAR}, + #{clientIpAddr, jdbcType=VARCHAR}, + #{serverIpAddr, jdbcType=VARCHAR}, + #{processTime1, jdbcType=BIGINT}, + #{processTime2, jdbcType=BIGINT}, + #{loggingCompleted, jdbcType=BOOLEAN}, + #{asynRequest, jdbcType=BOOLEAN}, + #{responseContentType, jdbcType=VARCHAR}, + #{responseResult, jdbcType=VARCHAR}, + #{createTime, jdbcType=VARCHAR} + ) + + + + + + + + + \ No newline at end of file diff --git a/xproject-service/src/main/resources/mybatis/mapper/AdminUserMapper.xml b/xproject-service/src/main/resources/mybatis/mapper/AdminUserMapper.xml index ac428d7..3e94e9c 100644 --- a/xproject-service/src/main/resources/mybatis/mapper/AdminUserMapper.xml +++ b/xproject-service/src/main/resources/mybatis/mapper/AdminUserMapper.xml @@ -147,20 +147,20 @@ (SELECT u.user_name FROM admin_user u WHERE u.user_id = a.create_by) createByName FROM admin_user a WHERE 1=1 - - AND a.user_name like CONCAT('%', #{userName, jdbcType=VARCHAR}, '%') + + AND a.user_name like CONCAT('%', #{condition.userName, jdbcType=VARCHAR}, '%') - - AND a.real_name like CONCAT('%', #{realName, jdbcType=VARCHAR}, '%') + + AND a.real_name like CONCAT('%', #{condition.realName, jdbcType=VARCHAR}, '%') - - AND a.user_type = #{userType, jdbcType=INTEGER} + + AND a.user_type = #{condition.userType, jdbcType=INTEGER} - - AND a.status = #{status, jdbcType=INTEGER} + + AND a.status = #{condition.status, jdbcType=INTEGER} - - ORDER BY ${orderby} ${order} + + ORDER BY ${orderBy.orderby} ${orderBy.order} @@ -168,17 +168,17 @@ SELECT count(*) FROM admin_user a WHERE 1=1 - - AND a.user_name like CONCAT('%', #{userName, jdbcType=VARCHAR}, '%') + + AND a.user_name like CONCAT('%', #{condition.userName, jdbcType=VARCHAR}, '%') - - AND a.real_name like CONCAT('%', #{realName, jdbcType=VARCHAR}, '%') + + AND a.real_name like CONCAT('%', #{condition.realName, jdbcType=VARCHAR}, '%') - - AND a.user_type = #{userType, jdbcType=INTEGER} + + AND a.user_type = #{condition.userType, jdbcType=INTEGER} - - AND a.status = #{status, jdbcType=INTEGER} + + AND a.status = #{condition.status, jdbcType=INTEGER} diff --git a/xproject-service/src/main/resources/mybatis/mybatis-config.xml b/xproject-service/src/main/resources/mybatis/mybatis-config.xml index 14814bb..6fe7167 100644 --- a/xproject-service/src/main/resources/mybatis/mybatis-config.xml +++ b/xproject-service/src/main/resources/mybatis/mybatis-config.xml @@ -19,6 +19,7 @@ + @@ -29,6 +30,7 @@ + \ No newline at end of file