registration = new FilterRegistrationBean<>();
+ registration.setFilter((Filter) Objects.requireNonNull(shiroFilterFactoryBean.getObject()));
+ registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
+ return registration;
+ }
+
+ @Bean
+ public MemoryConstrainedCacheManager memoryConstrainedCacheManager() {
+ return new MemoryConstrainedCacheManager();
+ }
+
+ /**
+ * securityManager 不用直接注入shiroDBRealm,可能会导致事务失效
+ * 解决方法见 handleContextRefresh
+ * http://www.debugrun.com/a/NKS9EJQ.html
+ */
+ @Bean(name = "securityManager")
+ public DefaultWebSecurityManager securityManager(SessionManager sessionManager, MemoryConstrainedCacheManager memoryConstrainedCacheManager) {
+ DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
+ dwsm.setSessionManager(sessionManager);
+ dwsm.setCacheManager(memoryConstrainedCacheManager);
+ return dwsm;
+ }
+
+ @Bean(name = "shiroDBRealm")
+ @DependsOn("lifecycleBeanPostProcessor")
+ public ShiroDBRealm getShiroDBRealm() {
+ return new ShiroDBRealm();
+ }
+
+ @Bean(name = "lifecycleBeanPostProcessor")
+ public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
+ return new LifecycleBeanPostProcessor();
+ }
+
+ @Bean
+ public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
+ DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
+ daap.setProxyTargetClass(true);
+ return daap;
+ }
+
+ @Bean
+ public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager sessionManager) {
+ AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
+ aasa.setSecurityManager(sessionManager);
+ return new AuthorizationAttributeSourceAdvisor();
+ }
+
+ @Bean
+ public SessionManager sessionManager(MemoryConstrainedCacheManager memoryConstrainedCacheManager) {
+ DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
+ sessionManager.setSessionIdUrlRewritingEnabled(false);
+ sessionManager.setGlobalSessionTimeout(1800000L);
+ sessionManager.setDeleteInvalidSessions(true);
+ sessionManager.setSessionValidationSchedulerEnabled(true);
+ SimpleCookie sessionIdCookie = new SimpleCookie();
+ sessionManager.setSessionIdCookie(sessionIdCookie);
+ sessionIdCookie.setPath("/");
+ sessionIdCookie.setName("MS_SESSION_ID");
+ sessionManager.setCacheManager(memoryConstrainedCacheManager);
+ return sessionManager;
+ }
+
+ /**
+ * 等到ApplicationContext 加载完成之后 装配shiroRealm
+ */
+ @EventListener
+ public void handleContextRefresh(ContextRefreshedEvent event) {
+ ApplicationContext context = event.getApplicationContext();
+ ShiroDBRealm shiroDBRealm = (ShiroDBRealm) context.getBean("shiroDBRealm");
+ ((DefaultWebSecurityManager) context.getBean("securityManager")).setRealm(shiroDBRealm);
+ }
+}
diff --git a/src/main/java/com/fit2cloud/metersphere/config/WebConfig.java b/src/main/java/com/fit2cloud/metersphere/config/WebConfig.java
new file mode 100644
index 0000000000..09d42c5455
--- /dev/null
+++ b/src/main/java/com/fit2cloud/metersphere/config/WebConfig.java
@@ -0,0 +1,15 @@
+package com.fit2cloud.metersphere.config;
+
+import com.fit2cloud.metersphere.interceptor.TestInterceptor;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(new TestInterceptor());
+ }
+}
diff --git a/src/main/java/com/fit2cloud/metersphere/config/WebSocketConfig.java b/src/main/java/com/fit2cloud/metersphere/config/WebSocketConfig.java
new file mode 100644
index 0000000000..ca71eb80d7
--- /dev/null
+++ b/src/main/java/com/fit2cloud/metersphere/config/WebSocketConfig.java
@@ -0,0 +1,15 @@
+package com.fit2cloud.metersphere.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+@Configuration
+public class WebSocketConfig {
+
+ @Bean
+ public ServerEndpointExporter serverEndpointExporter() {
+ return new ServerEndpointExporter();
+ }
+
+}
diff --git a/src/main/java/com/fit2cloud/metersphere/controller/IndexController.java b/src/main/java/com/fit2cloud/metersphere/controller/IndexController.java
new file mode 100644
index 0000000000..ecf2aad575
--- /dev/null
+++ b/src/main/java/com/fit2cloud/metersphere/controller/IndexController.java
@@ -0,0 +1,29 @@
+package com.fit2cloud.metersphere.controller;
+
+import com.fit2cloud.metersphere.user.SessionUtils;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+@Controller
+@RequestMapping
+public class IndexController {
+
+ @RequestMapping(value = "/", method = RequestMethod.GET)
+ public ModelAndView index() {
+ ModelAndView modelAndView = new ModelAndView();
+ modelAndView.setViewName("index");
+ return modelAndView;
+ }
+
+ @GetMapping(value = "/login")
+ public String login() {
+ if (SessionUtils.getUser() == null) {
+ return "login";
+ } else {
+ return "redirect:/";
+ }
+ }
+}
diff --git a/src/main/java/com/fit2cloud/metersphere/controller/LoginController.java b/src/main/java/com/fit2cloud/metersphere/controller/LoginController.java
new file mode 100644
index 0000000000..1946b3e13c
--- /dev/null
+++ b/src/main/java/com/fit2cloud/metersphere/controller/LoginController.java
@@ -0,0 +1,64 @@
+package com.fit2cloud.metersphere.controller;
+
+import com.fit2cloud.metersphere.controller.request.LoginRequest;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.*;
+import org.apache.shiro.authz.UnauthorizedException;
+import org.apache.shiro.subject.Subject;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping
+public class LoginController {
+
+ @GetMapping(value = "/isLogin")
+ public ResultHolder isLogin() {
+ if (SecurityUtils.getSubject().isAuthenticated()) {
+ return ResultHolder.success("");
+ }
+ return ResultHolder.error("");
+ }
+
+ @PostMapping(value = "/signin")
+ public ResultHolder login(@RequestBody LoginRequest request) {
+ String msg;
+ String username = StringUtils.trim(request.getUsername());
+ String password = StringUtils.trim(request.getPassword());
+ if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
+ return ResultHolder.error("user or password can't be null");
+ }
+
+ UsernamePasswordToken token = new UsernamePasswordToken(username, password);
+ Subject subject = SecurityUtils.getSubject();
+
+ try {
+ subject.login(token);
+ if (subject.isAuthenticated()) {
+ return ResultHolder.success("");
+ } else {
+ return ResultHolder.error("login fail");
+ }
+ } catch (ExcessiveAttemptsException e) {
+ msg = "excessive attempts";
+ } catch (LockedAccountException e) {
+ msg = "the user has been locked.";
+ } catch (DisabledAccountException e) {
+ msg = "the user has been disabled. ";
+ } catch (ExpiredCredentialsException e) {
+ msg = "user expires. ";
+ } catch (AuthenticationException e) {
+ msg = e.getMessage();
+ } catch (UnauthorizedException e) {
+ msg = "not authorized. " + e.getMessage();
+ }
+ return ResultHolder.error(msg);
+ }
+
+ @GetMapping(value = "/signout")
+ public ResultHolder logout() {
+ SecurityUtils.getSubject().logout();
+ return ResultHolder.success("");
+ }
+
+}
diff --git a/src/main/java/com/fit2cloud/metersphere/controller/ResultHolder.java b/src/main/java/com/fit2cloud/metersphere/controller/ResultHolder.java
new file mode 100644
index 0000000000..0937ea7e22
--- /dev/null
+++ b/src/main/java/com/fit2cloud/metersphere/controller/ResultHolder.java
@@ -0,0 +1,73 @@
+package com.fit2cloud.metersphere.controller;
+
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+public class ResultHolder {
+ public ResultHolder() {
+ this.success = true;
+ }
+
+ private ResultHolder(Object data) {
+ this.data = data;
+ this.success = true;
+ }
+
+ private ResultHolder(boolean success, String msg) {
+ this.success = success;
+ this.message = msg;
+ }
+
+ private ResultHolder(boolean success, String msg, Object data) {
+ this.success = success;
+ this.message = msg;
+ this.data = data;
+ }
+
+ // 请求是否成功
+ private boolean success = false;
+ // 描述信息
+ private String message;
+ // 返回数据
+ private Object data = "";
+
+ public boolean isSuccess() {
+ return this.success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public static ResultHolder success(Object obj) {
+ return new ResultHolder(obj);
+ }
+
+ public static ResultHolder error(String message) {
+ return new ResultHolder(false, message, null);
+ }
+
+ public static ResultHolder error(String message, Object object) {
+ return new ResultHolder(false, message, object);
+ }
+
+ public String toString() {
+ return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
+ }
+}
diff --git a/src/main/java/com/fit2cloud/metersphere/controller/TestController.java b/src/main/java/com/fit2cloud/metersphere/controller/TestController.java
new file mode 100644
index 0000000000..e4043147f9
--- /dev/null
+++ b/src/main/java/com/fit2cloud/metersphere/controller/TestController.java
@@ -0,0 +1,31 @@
+package com.fit2cloud.metersphere.controller;
+
+import com.fit2cloud.metersphere.user.SessionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping(value = "/test")
+public class TestController {
+
+ @GetMapping(value = "/{str}")
+ public Object getString(@PathVariable String str) throws InterruptedException {
+ if (StringUtils.equals("error", str)) {
+ throw new RuntimeException("test error");
+ }
+ if (StringUtils.equals("warning", str)) {
+ return ResultHolder.error("test warning");
+ }
+ if (StringUtils.equals("user", str)) {
+ return ResultHolder.success(SessionUtils.getUser());
+ }
+ if (StringUtils.equals("sleep", str)) {
+ Thread.sleep(2000L);
+ return ResultHolder.success(str);
+ }
+ return ResultHolder.success(str);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/fit2cloud/metersphere/controller/request/LoginRequest.java b/src/main/java/com/fit2cloud/metersphere/controller/request/LoginRequest.java
new file mode 100644
index 0000000000..a9c39b66fb
--- /dev/null
+++ b/src/main/java/com/fit2cloud/metersphere/controller/request/LoginRequest.java
@@ -0,0 +1,24 @@
+package com.fit2cloud.metersphere.controller.request;
+
+public class LoginRequest {
+
+ private String username;
+
+ private String password;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+}
diff --git a/src/main/java/com/fit2cloud/metersphere/interceptor/TestInterceptor.java b/src/main/java/com/fit2cloud/metersphere/interceptor/TestInterceptor.java
new file mode 100644
index 0000000000..412c880067
--- /dev/null
+++ b/src/main/java/com/fit2cloud/metersphere/interceptor/TestInterceptor.java
@@ -0,0 +1,17 @@
+package com.fit2cloud.metersphere.interceptor;
+
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Component
+public class TestInterceptor implements HandlerInterceptor {
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+// response.setHeader("Authentication-Status", "invalid");
+ return true;
+ }
+}
diff --git a/src/main/java/com/fit2cloud/metersphere/security/LoginFilter.java b/src/main/java/com/fit2cloud/metersphere/security/LoginFilter.java
new file mode 100644
index 0000000000..8c7987d187
--- /dev/null
+++ b/src/main/java/com/fit2cloud/metersphere/security/LoginFilter.java
@@ -0,0 +1,36 @@
+package com.fit2cloud.metersphere.security;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fit2cloud.metersphere.controller.ResultHolder;
+import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class LoginFilter extends FormAuthenticationFilter {
+
+ @Override
+ protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
+ if (((HttpServletRequest) request).getMethod().toUpperCase().equals("OPTIONS")) {
+ return true;
+ }
+ return super.isAccessAllowed(request, response, mappedValue);
+ }
+
+ @Override
+ protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
+ HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+ if (httpServletRequest.getServletPath().endsWith("login")) {
+ return super.onAccessDenied(request, response);
+ }
+ HttpServletResponse httpServletResponse = (HttpServletResponse) response;
+ httpServletResponse.setCharacterEncoding("UTF-8");
+ httpServletResponse.setContentType("application/json");
+ httpServletResponse.setHeader("authentication-status", "invalid");
+ ResultHolder result = ResultHolder.error("Authentication Status Invalid");
+ httpServletResponse.getWriter().write(JSONObject.toJSON(result).toString());
+ return true;
+ }
+}
diff --git a/src/main/java/com/fit2cloud/metersphere/security/ShiroDBRealm.java b/src/main/java/com/fit2cloud/metersphere/security/ShiroDBRealm.java
new file mode 100644
index 0000000000..fff730fbe8
--- /dev/null
+++ b/src/main/java/com/fit2cloud/metersphere/security/ShiroDBRealm.java
@@ -0,0 +1,55 @@
+package com.fit2cloud.metersphere.security;
+
+
+import com.fit2cloud.metersphere.user.SessionUser;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.*;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * 自定义Realm 注入service 可能会导致在 service的aop 失效,例如@Transactional,
+ * 解决方法:
+ *
+ * 1. 这里改成注入mapper,这样mapper 中的事务失效
+ * 2. 这里仍然注入service,在配置ShiroConfig 的时候不去set realm, 等到spring 初始化完成之后
+ * set realm
+ *
+ */
+public class ShiroDBRealm extends AuthorizingRealm {
+
+ private Logger logger = LoggerFactory.getLogger(ShiroDBRealm.class);
+
+ /**
+ * 权限认证
+ */
+ @Override
+ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
+ return null;
+ }
+
+ /**
+ * 登录认证
+ */
+ @Override
+ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
+ UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
+ String userId = token.getUsername();
+ String password = String.valueOf(token.getPassword());
+ SessionUser sessionUser = new SessionUser();
+
+ sessionUser.setName(userId);
+ sessionUser.setId(userId);
+ SecurityUtils.getSubject().getSession().setAttribute("user", sessionUser);
+ return new SimpleAuthenticationInfo(userId, password, getName());
+ }
+
+ @Override
+ public boolean isPermitted(PrincipalCollection principals, String permission) {
+ return true;
+ }
+}
diff --git a/src/main/java/com/fit2cloud/metersphere/user/SessionUser.java b/src/main/java/com/fit2cloud/metersphere/user/SessionUser.java
new file mode 100644
index 0000000000..3fe412ab9c
--- /dev/null
+++ b/src/main/java/com/fit2cloud/metersphere/user/SessionUser.java
@@ -0,0 +1,26 @@
+package com.fit2cloud.metersphere.user;
+
+import java.io.Serializable;
+
+public class SessionUser implements Serializable {
+
+ private static final long serialVersionUID = -7149638440406959033L;
+ private String id;
+ private String name;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/src/main/java/com/fit2cloud/metersphere/user/SessionUtils.java b/src/main/java/com/fit2cloud/metersphere/user/SessionUtils.java
new file mode 100644
index 0000000000..ceae1ae704
--- /dev/null
+++ b/src/main/java/com/fit2cloud/metersphere/user/SessionUtils.java
@@ -0,0 +1,18 @@
+package com.fit2cloud.metersphere.user;
+
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.Subject;
+
+public class SessionUtils {
+
+ public static SessionUser getUser() {
+ try {
+ Subject subject = SecurityUtils.getSubject();
+ Session session = subject.getSession();
+ return (SessionUser) session.getAttribute("user");
+ } catch (Exception e) {
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/com/fit2cloud/metersphere/websocket/ServerEndpointConfigurator.java b/src/main/java/com/fit2cloud/metersphere/websocket/ServerEndpointConfigurator.java
new file mode 100644
index 0000000000..788cab51b3
--- /dev/null
+++ b/src/main/java/com/fit2cloud/metersphere/websocket/ServerEndpointConfigurator.java
@@ -0,0 +1,17 @@
+package com.fit2cloud.metersphere.websocket;
+
+import com.fit2cloud.metersphere.user.SessionUtils;
+
+import javax.websocket.HandshakeResponse;
+import javax.websocket.server.HandshakeRequest;
+import javax.websocket.server.ServerEndpointConfig;
+
+public class ServerEndpointConfigurator extends ServerEndpointConfig.Configurator {
+ @Override
+ public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
+ // 将用户信息存储到socket的配置里
+ System.out.println(SessionUtils.getUser());
+ sec.getUserProperties().put("user", SessionUtils.getUser());
+ super.modifyHandshake(sec, request, response);
+ }
+}
diff --git a/src/main/java/com/fit2cloud/metersphere/websocket/WebSocketServer.java b/src/main/java/com/fit2cloud/metersphere/websocket/WebSocketServer.java
new file mode 100644
index 0000000000..60187ded24
--- /dev/null
+++ b/src/main/java/com/fit2cloud/metersphere/websocket/WebSocketServer.java
@@ -0,0 +1,38 @@
+package com.fit2cloud.metersphere.websocket;
+
+import com.fit2cloud.metersphere.user.SessionUtils;
+import org.springframework.stereotype.Component;
+
+import javax.websocket.*;
+import javax.websocket.server.ServerEndpoint;
+import java.io.IOException;
+
+@ServerEndpoint(value = "/socket", configurator = ServerEndpointConfigurator.class)
+@Component
+public class WebSocketServer {
+ @OnOpen
+ public void onOpen(Session session) throws IOException {
+ // Get session and WebSocket connection
+ System.out.println("open: " + session.isOpen());
+ System.out.println("open: " + SessionUtils.getUser());
+ System.out.println("open: " + session.getUserProperties().get("user"));
+ }
+
+ @OnMessage
+ public void onMessage(Session session, String message) throws IOException {
+ // Handle new messages
+ System.out.println(message);
+ }
+
+ @OnClose
+ public void onClose(Session session) throws IOException {
+ // WebSocket connection closes
+ System.out.println("close: " + session.isOpen());
+ }
+
+ @OnError
+ public void onError(Session session, Throwable throwable) {
+ // Do error handling here
+ throwable.printStackTrace();
+ }
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000000..28ebd79da5
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,26 @@
+spring.application.name=metersphere
+
+server.port=8888
+
+# Hikari
+spring.datasource.type=com.zaxxer.hikari.HikariDataSource
+spring.datasource.hikari.minimum-idle=5
+spring.datasource.hikari.maximum-pool-size=15
+spring.datasource.hikari.auto-commit=true
+spring.datasource.hikari.idle-timeout=30000
+spring.datasource.hikari.pool-name=DatebookHikariCP
+spring.datasource.hikari.max-lifetime=1800000
+spring.datasource.hikari.connection-timeout=30000
+spring.datasource.hikari.connection-test-query=SELECT 1
+
+# mybatis
+mybatis.configuration.cache-enabled=true
+mybatis.configuration.lazy-loading-enabled=false
+mybatis.configuration.aggressive-lazy-loading=true
+mybatis.configuration.multiple-result-sets-enabled=true
+mybatis.configuration.use-column-label=true
+mybatis.configuration.auto-mapping-behavior=full
+mybatis.configuration.default-statement-timeout=25000
+mybatis.mapper-locations=classpath:mybatis/**/*.xml,classpath*:com/fit2cloud/metersphere/mapper/**/*.xml
+
+logging.file.path=/opt/fit2cloud/logs/${spring.application.name}
\ No newline at end of file
diff --git a/src/main/resources/generatorConfig.xml b/src/main/resources/generatorConfig.xml
new file mode 100644
index 0000000000..db0befeeb1
--- /dev/null
+++ b/src/main/resources/generatorConfig.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
new file mode 100644
index 0000000000..b8e00b430e
--- /dev/null
+++ b/src/main/resources/logback.xml
@@ -0,0 +1,162 @@
+
+
+
+
+
+
+
+ %d %5p %40.40c:%4L - %m%n
+
+
+
+
+
+ DEBUG
+ ACCEPT
+ DENY
+
+ ${logging.file.path}/debug.log
+
+ ${logging.file.path}/history/debug.%d{yyyyMMdd}-%i.log
+
+ 30
+
+ 50MB
+
+
+
+ UTF-8
+ %d [%thread] %-5level %logger{36} %line - %msg%n
+
+
+
+
+
+ INFO
+
+ ${logging.file.path}/info.log
+
+ ${logging.file.path}/history/info.%d{yyyyMMdd}-%i.log
+
+ 30
+
+ 50MB
+
+
+
+ UTF-8
+ %d [%thread] %-5level %logger{36} %line - %msg%n
+
+
+
+
+
+ ERROR
+ ACCEPT
+ DENY
+
+
+ ${logging.file.path}/error.log
+
+ ${logging.file.path}/history/error.%d{yyyyMMdd}-%i.log
+
+ 30
+
+ 50MB
+
+
+
+ UTF-8
+ %d [%thread] %-5level %logger{36} %line - %msg%n
+
+
+
+
+
+ WARN
+ ACCEPT
+ DENY
+
+ ${logging.file.path}/warn.log
+
+ ${logging.file.path}/history/warn.%d{yyyyMMdd}-%i.log
+
+ 30
+
+ 50MB
+
+
+
+ UTF-8
+ %d [%thread] %-5level %logger{36} %line - %msg%n
+
+
+
+
+
+ DEBUG
+
+ 10000
+
+
+
+
+
+ DEBUG
+
+ 10000
+
+
+
+
+
+ INFO
+
+ 10000
+
+
+
+
+
+ ERROR
+
+ 10000
+ true
+
+
+
+
+
+ WARN
+
+ 10000
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/java/com/fit2cloud/metersphere/ApplicationTests.java b/src/test/java/com/fit2cloud/metersphere/ApplicationTests.java
new file mode 100644
index 0000000000..e3a46a17e7
--- /dev/null
+++ b/src/test/java/com/fit2cloud/metersphere/ApplicationTests.java
@@ -0,0 +1,25 @@
+package com.fit2cloud.metersphere;
+
+
+import com.fit2cloud.metersphere.base.domain.User;
+import com.fit2cloud.metersphere.base.mapper.UserMapper;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+public class ApplicationTests {
+ @Resource
+ UserMapper userMapper;
+
+ @Test
+ public void test1() {
+ List users = userMapper.selectByExample(null);
+ System.out.println(users);
+ }
+}