wenhongquan 8 лет назад
Родитель
Сommit
9487b1a3c2
11 измененных файлов с 589 добавлено и 35 удалено
  1. 30 0
      Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/CorsConfig.java
  2. 41 0
      Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/FastJson2JsonRedisSerializer.java
  3. 78 0
      Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/JwtAuthenticationTokenFilter.java
  4. 133 0
      Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/JwtTokenUtil.java
  5. 29 0
      Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/RedisCacheUtil.java
  6. 66 0
      Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/RedisConf.java
  7. 43 0
      Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/ThreadConfig.java
  8. 18 0
      Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/WebMvcConfig.java
  9. 93 0
      Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/WebSecurityConfig.java
  10. 58 33
      Visuallnspection_fjq/visuallnspectioninteface/.idea/workspace.xml
  11. 0 2
      Visuallnspection_fjq/visuallnspectioninteface/visuallnspectioninteface.iml

+ 30 - 0
Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/CorsConfig.java

@@ -0,0 +1,30 @@
+package com.xintong.visualinspection.visuallnspection_fjq.securityTools;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 文件名:CorsConfig
+ * 版本信息:日期:2017/4/7 Copyright 江苏省交通规划设计院 Corporation 2017 版权所有.
+ */
+
+
+@Configuration
+public class CorsConfig {
+    private CorsConfiguration buildConfig() {
+        CorsConfiguration corsConfiguration = new CorsConfiguration();
+        corsConfiguration.addAllowedOrigin("*"); // 1
+        corsConfiguration.addAllowedHeader("*"); // 2
+        corsConfiguration.addAllowedMethod("*"); // 3
+        return corsConfiguration;
+    }
+
+    @Bean
+    public CorsFilter corsFilter() {
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        source.registerCorsConfiguration("/**", buildConfig()); // 4
+        return new CorsFilter(source);
+    }
+}

+ 41 - 0
Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/FastJson2JsonRedisSerializer.java

@@ -0,0 +1,41 @@
+package com.xintong.visualinspection.visuallnspection_fjq.securityTools;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.SerializationException;
+
+import java.nio.charset.Charset;
+
+/**
+ * 文件名:FastJson2JsonRedisSerializer
+ * 版本信息:日期:2017/4/25 Copyright 江苏省交通规划设计院 Corporation 2017 版权所有.
+ */
+public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
+
+    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
+
+    private Class<T> clazz;
+
+    public FastJson2JsonRedisSerializer(Class<T> clazz) {
+        super();
+        this.clazz = clazz;
+    }
+
+    public byte[] serialize(T t) throws SerializationException {
+        if (t == null) {
+            return new byte[0];
+        }
+        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
+    }
+
+    public T deserialize(byte[] bytes) throws SerializationException {
+        if (bytes == null || bytes.length <= 0) {
+            return null;
+        }
+        String str = new String(bytes, DEFAULT_CHARSET);
+
+        return (T) JSON.parseObject(str, clazz);
+    }
+
+}

+ 78 - 0
Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/JwtAuthenticationTokenFilter.java

@@ -0,0 +1,78 @@
+package com.xintong.visualinspection.visuallnspection_fjq.securityTools;
+
+import com.alibaba.fastjson.JSON;
+import com.xintong.visualinspection.bean.User;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Component
+public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
+
+	@Autowired
+	private UserDetailsService userDetailsService;
+
+	@Autowired
+	private JwtTokenUtil jwtTokenUtil;
+	
+	@Autowired
+	private RedisCacheUtil redisCacheUtil;
+	
+
+	@Value("${jwt.header}")
+	private String tokenHeader;
+	
+	@Value("${jwt.expiration}")
+	private int expiration;
+	
+
+	@Value("${jwt.tokenHead}")
+	private String tokenHead;
+
+	@Override
+	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+			throws ServletException, IOException {
+		String authHeader = request.getHeader(this.tokenHeader);
+		if (authHeader != null && authHeader.startsWith(tokenHead)) {
+			final String authToken = authHeader.substring(tokenHead.length()); // The  part after "XingTong "
+			String username = jwtTokenUtil.getUsernameFromToken(authToken);
+
+			logger.info("checking authentication " + username);
+
+			if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
+
+				UserDetails u = redisCacheUtil.getUserByUserName(username);
+				// 验证是否跟缓存中有无
+				if (u != null) {
+					UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
+
+					User u_t = (User) JSON.parseObject(JSON.toJSONString(u),User.class) ; 
+	                //判定token中的用户名是否数据库中一致 是与缓存中的用户token一致
+					if (jwtTokenUtil.validateToken(authToken, userDetails)&& authToken.equals(u_t.getToken())) {
+						((User)userDetails).setToken(u_t.getToken());
+						redisCacheUtil.setUser(username, userDetails, expiration);
+						UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
+								userDetails, null, userDetails.getAuthorities());
+						authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+						logger.info("authenticated user " + username + ", setting security context");
+						SecurityContextHolder.getContext().setAuthentication(authentication);
+					}
+				}
+			}
+		}
+
+		chain.doFilter(request, response);
+	}
+}

+ 133 - 0
Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/JwtTokenUtil.java

@@ -0,0 +1,133 @@
+package com.xintong.visualinspection.visuallnspection_fjq.securityTools;
+
+import com.xintong.visualinspection.bean.User;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Component;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class JwtTokenUtil implements Serializable {
+
+    private static final long serialVersionUID = -3301605591108950415L;
+
+    private static final String CLAIM_KEY_USERNAME = "sub";
+    private static final String CLAIM_KEY_CREATED = "created";
+
+    @Value("${jwt.secret}")
+    private String secret;
+
+    @Value("${jwt.expiration}")
+    private Long expiration;
+
+    public String getUsernameFromToken(String token) {
+        String username;
+        try {
+            final Claims claims = getClaimsFromToken(token);
+            username = claims.getSubject();
+        } catch (Exception e) {
+            username = null;
+        }
+        return username;
+    }
+
+    public Date getCreatedDateFromToken(String token) {
+        Date created;
+        try {
+            final Claims claims = getClaimsFromToken(token);
+            created = new Date((Long) claims.get(CLAIM_KEY_CREATED));
+        } catch (Exception e) {
+            created = null;
+        }
+        return created;
+    }
+
+    public Date getExpirationDateFromToken(String token) {
+        Date expiration;
+        try {
+            final Claims claims = getClaimsFromToken(token);
+            expiration = claims.getExpiration();
+        } catch (Exception e) {
+            expiration = null;
+        }
+        return expiration;
+    }
+
+    private Claims getClaimsFromToken(String token) {
+        Claims claims;
+        try {
+            claims = Jwts.parser()
+                    .setSigningKey(secret)
+                    .parseClaimsJws(token)
+                    .getBody();
+        } catch (Exception e) {
+            claims = null;
+        }
+        return claims;
+    }
+
+    private Date generateExpirationDate() {
+        return new Date(System.currentTimeMillis() + expiration * 1000);
+    }
+
+    private Boolean isTokenExpired(String token) {
+        final Date expiration = getExpirationDateFromToken(token);
+        return expiration.before(new Date());
+    }
+
+    private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {
+        return (lastPasswordReset != null && created.before(lastPasswordReset));
+    }
+
+    public String generateToken(UserDetails userDetails) {
+        Map<String, Object> claims = new HashMap<>();
+        claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername());
+        claims.put(CLAIM_KEY_CREATED, new Date());
+        return generateToken(claims);
+    }
+
+    String generateToken(Map<String, Object> claims) {
+        return Jwts.builder()
+                .setClaims(claims)
+                .setExpiration(generateExpirationDate())
+                .signWith(SignatureAlgorithm.HS512, secret)
+                .compact();
+    }
+
+    public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) {
+        final Date created = getCreatedDateFromToken(token);
+        return !isCreatedBeforeLastPasswordReset(created, lastPasswordReset)
+                && !isTokenExpired(token);
+    }
+
+    public String refreshToken(String token) {
+        String refreshedToken;
+        try {
+            final Claims claims = getClaimsFromToken(token);
+            claims.put(CLAIM_KEY_CREATED, new Date());
+            refreshedToken = generateToken(claims);
+        } catch (Exception e) {
+            refreshedToken = null;
+        }
+        return refreshedToken;
+    }
+    // 只是判定用户名是否一致 不去判定是否失效
+    public Boolean validateToken(String token, UserDetails userDetails) {
+        User user = (User) userDetails;
+        final String username = getUsernameFromToken(token);
+//        final Date created = getCreatedDateFromToken(token);
+        //final Date expiration = getExpirationDateFromToken(token);
+        return username.equals(user.getUsername());
+//        return (
+//                username.equals(user.getUsername())
+//                        && !isTokenExpired(token)
+//                        && !isCreatedBeforeLastPasswordReset(created, null));
+    }
+}

+ 29 - 0
Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/RedisCacheUtil.java

@@ -0,0 +1,29 @@
+package com.xintong.visualinspection.visuallnspection_fjq.securityTools;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class RedisCacheUtil {
+	@Autowired
+	private RedisTemplate redisTemplate;
+	
+	
+	public UserDetails getUserByUserName(String username){
+		return (UserDetails)redisTemplate.opsForValue().get(username);
+	}
+	
+	public void setUser(String username,UserDetails user,int timeout){
+		redisTemplate.opsForValue().set(username, user, timeout, TimeUnit.MILLISECONDS);
+	}
+	
+	public void removeForUserName(String username){
+		redisTemplate.delete(username);
+	}
+	
+
+}

+ 66 - 0
Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/RedisConf.java

@@ -0,0 +1,66 @@
+package com.xintong.visualinspection.visuallnspection_fjq.securityTools;
+
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cache.interceptor.KeyGenerator;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.serializer.RedisSerializer;
+
+import java.lang.reflect.Method;
+
+/**
+ * 文件名:RedisConf
+ * 版本信息:日期:2017/4/25 Copyright 江苏省交通规划设计院 Corporation 2017 版权所有.
+ */
+@Configuration
+@EnableCaching
+public class RedisConf extends CachingConfigurerSupport{
+
+    @Bean
+    public KeyGenerator keyGenerator(){
+        return new KeyGenerator() {
+            @Override
+            public Object generate(Object target, Method method, Object... params) {
+                StringBuilder sb = new StringBuilder();
+
+                sb.append(target.getClass().getName());
+                sb.append(method.getName());
+                for (Object obj : params) {
+                    sb.append(obj.toString());
+                }
+                return sb.toString();
+            }
+        };
+
+    }
+
+    @Bean
+    public CacheManager cacheManager(
+            @SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {
+        return new RedisCacheManager(redisTemplate);
+    }
+
+    @Bean
+    @SuppressWarnings("rawtypes")
+    public RedisSerializer fastJson2JsonRedisSerializer() {
+        return new FastJson2JsonRedisSerializer<Object>(Object.class);
+    }
+
+    @Bean
+    @SuppressWarnings("rawtypes")
+    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory, RedisSerializer fastJson2JsonRedisSerializer) {
+        StringRedisTemplate template = new StringRedisTemplate(factory);
+
+        template.setValueSerializer(fastJson2JsonRedisSerializer);
+
+        template.afterPropertiesSet();
+        return template;
+    }
+
+}

+ 43 - 0
Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/ThreadConfig.java

@@ -0,0 +1,43 @@
+package com.xintong.visualinspection.visuallnspection_fjq.securityTools;
+
+/**
+ * 文件名:ThreadConfig
+ * 版本信息:日期:2018/2/5 Copyright 江苏省交通规划设计院 Corporation 2018 版权所有.
+ */
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+@Configuration
+@EnableAsync
+public class ThreadConfig {
+
+    private int corePoolSize = 10;//线程池维护线程的最少数量
+
+    private int maxPoolSize = 30;//线程池维护线程的最大数量
+
+    private int queueCapacity = 8; //缓存队列
+
+    private int keepAlive = 60;//允许的空闲时间
+
+    @Bean
+    public Executor threadExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(corePoolSize);
+        executor.setMaxPoolSize(maxPoolSize);
+        executor.setQueueCapacity(queueCapacity);
+        executor.setThreadNamePrefix("myExecutor-");
+        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
+        // CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //对拒绝task的处理策略
+        executor.setKeepAliveSeconds(keepAlive);
+        executor.initialize();
+        return executor;
+    }
+
+}

+ 18 - 0
Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/WebMvcConfig.java

@@ -0,0 +1,18 @@
+package com.xintong.visualinspection.visuallnspection_fjq.securityTools;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+
+/**
+ * 文件名:WebMvcConfig
+ * 版本信息:日期:2017/3/31 Copyright 江苏省交通规划设计院 Corporation 2017 版权所有.
+ */
+@Configuration
+public class WebMvcConfig extends WebMvcConfigurerAdapter {
+
+    @Override
+    public void addViewControllers(ViewControllerRegistry registry) {
+        registry.addViewController("/login").setViewName("login");
+    }
+}

+ 93 - 0
Visuallnspection_fjq/visuallnspection_fjq/src/main/java/com/xintong/visualinspection/visuallnspection_fjq/securityTools/WebSecurityConfig.java

@@ -0,0 +1,93 @@
+package com.xintong.visualinspection.visuallnspection_fjq.securityTools;
+
+import com.xintong.visualinspection.service.UserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+/**
+ * 文件名:WebSecurityConfig
+ * 版本信息:日期:2017/3/31 Copyright 江苏省交通规划设计院 Corporation 2017 版权所有.
+ */
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled=true)
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+    @Autowired
+    private UserService userService;
+
+    @Bean
+    public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
+        return new JwtAuthenticationTokenFilter();
+    }
+    
+    @Override
+    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());//user Details Service验证
+    }
+
+    @Override
+    public void configure(WebSecurity web) throws Exception {
+        super.configure(web);
+        web.ignoring().antMatchers("/css/**","/js/**");
+    }
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+    	
+    	http
+         // 由于使用的是JWT,我们这里不需要csrf
+         .csrf().disable()
+         .cors().and()
+         // 基于token,所以不需要session
+         .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
+         .authorizeRequests()
+         //.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
+         // 允许对于网站静态资源的无授权访问
+         .antMatchers(
+                 HttpMethod.GET,
+                 "/",
+                 "/*.html",
+                 "/favicon.ico",
+                 "/**/*.html",
+                 "/**/*.css",
+                 "/**/*.js"
+         ).permitAll()
+         // 对于获取token的rest api要允许匿名访问
+         .antMatchers("/user/auth/**","/file/**","/druid/**").permitAll()
+         // 除上面外的所有请求全部需要鉴权认证
+         .anyRequest().authenticated();
+    	
+    	// 禁用缓存
+        http.headers().cacheControl();
+        
+        http
+        .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
+    	
+    	
+  
+    }
+
+    /**
+     * 设置用户密码的加密方式为MD5加密
+     * @return
+     */
+    @Bean
+    public Md5PasswordEncoder passwordEncoder() {
+        return new Md5PasswordEncoder();
+
+    }
+    
+  
+}

+ 58 - 33
Visuallnspection_fjq/visuallnspectioninteface/.idea/workspace.xml

@@ -12,12 +12,12 @@
     <option name="LAST_RESOLUTION" value="IGNORE" />
   </component>
   <component name="FileEditorManager">
-    <leaf>
+    <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
       <file leaf-file-name="pom.xml" pinned="false" current-in-tab="true">
         <entry file="file://$PROJECT_DIR$/pom.xml">
           <provider selected="true" editor-type-id="text-editor">
-            <state relative-caret-position="630">
-              <caret line="42" lean-forward="true" selection-start-line="42" selection-end-line="42" />
+            <state relative-caret-position="798">
+              <caret line="42" selection-start-line="42" selection-end-line="42" />
             </state>
           </provider>
         </entry>
@@ -40,29 +40,47 @@
   <component name="MavenImportPreferences">
     <option name="generalSettings">
       <MavenGeneralSettings>
-        <option name="mavenHome" value="$USER_HOME$/Documents/apache-maven-3.3.9" />
+        <option name="mavenHome" value="D:/dev/apache-maven-3.3.9-bin/apache-maven-3.3.9" />
         <option name="userSettingsFile" value="$USER_HOME$/Documents/apache-maven-3.3.9/conf/settings.xml" />
       </MavenGeneralSettings>
     </option>
+    <option name="importingSettings">
+      <MavenImportingSettings>
+        <option name="importAutomatically" value="true" />
+      </MavenImportingSettings>
+    </option>
   </component>
   <component name="ProjectFrameBounds" fullScreen="true">
-    <option name="width" value="1440" />
-    <option name="height" value="900" />
+    <option name="x" value="205" />
+    <option name="y" value="403" />
+    <option name="width" value="1640" />
+    <option name="height" value="956" />
   </component>
   <component name="ProjectView">
-    <navigator proportions="" version="1">
+    <navigator currentView="PackagesPane" proportions="" version="1">
       <foldersAlwaysOnTop value="true" />
     </navigator>
     <panes>
-      <pane id="ProjectPane" />
-      <pane id="PackagesPane" />
-      <pane id="AndroidView" />
+      <pane id="ProjectPane">
+        <subPane>
+          <expand>
+            <path>
+              <item name="visuallnspectioninteface" type="b2602c69:ProjectViewProjectNode" />
+              <item name="visuallnspectioninteface" type="462c0819:PsiDirectoryNode" />
+            </path>
+          </expand>
+          <select />
+        </subPane>
+      </pane>
       <pane id="Scope" />
+      <pane id="AndroidView" />
+      <pane id="PackagesPane" />
     </panes>
   </component>
   <component name="PropertiesComponent">
     <property name="WebServerToolWindowFactoryState" value="false" />
     <property name="aspect.path.notification.shown" value="true" />
+    <property name="last_opened_file_path" value="$PROJECT_DIR$" />
     <property name="nodejs_interpreter_path.stuck_in_default_project" value="/usr/local/bin/node" />
     <property name="nodejs_npm_path_reset_for_default_project" value="true" />
     <property name="settings.editor.selected.configurable" value="MavenSettings" />
@@ -151,43 +169,43 @@
       <option name="presentableId" value="Default" />
       <updated>1522662684790</updated>
       <workItem from="1522662689077" duration="39000" />
+      <workItem from="1522721071000" duration="1221000" />
     </task>
     <servers />
   </component>
   <component name="TimeTrackingManager">
-    <option name="totallyTimeSpent" value="39000" />
+    <option name="totallyTimeSpent" value="1260000" />
   </component>
   <component name="ToolWindowManager">
-    <frame x="0" y="0" width="1440" height="900" extended-state="0" />
-    <editor active="true" />
+    <frame x="0" y="0" width="1920" height="1080" extended-state="0" />
     <layout>
-      <window_info anchor="right" id="Palette" />
+      <window_info anchor="right" id="Palette" order="3" />
       <window_info anchor="bottom" id="TODO" order="6" />
-      <window_info anchor="right" id="Palette&#9;" />
-      <window_info id="Image Layers" />
-      <window_info anchor="right" id="Capture Analysis" />
-      <window_info anchor="bottom" id="Event Log" side_tool="true" />
-      <window_info anchor="right" id="Maven Projects" />
-      <window_info anchor="bottom" id="Database Changes" show_stripe_button="false" />
+      <window_info anchor="right" id="Palette&#9;" order="3" />
+      <window_info id="Image Layers" order="2" />
+      <window_info anchor="right" id="Capture Analysis" order="3" />
+      <window_info anchor="bottom" id="Event Log" order="7" side_tool="true" />
+      <window_info anchor="right" id="Maven Projects" order="3" />
+      <window_info anchor="bottom" id="Database Changes" order="7" show_stripe_button="false" />
       <window_info anchor="bottom" id="Run" order="2" />
-      <window_info anchor="bottom" id="Version Control" show_stripe_button="false" />
-      <window_info anchor="bottom" id="Terminal" />
-      <window_info id="Capture Tool" />
-      <window_info id="Designer" />
-      <window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.24964234" />
-      <window_info anchor="right" id="Database" />
+      <window_info anchor="bottom" id="Version Control" order="7" show_stripe_button="false" />
+      <window_info anchor="bottom" id="Terminal" order="7" />
+      <window_info id="Capture Tool" order="2" />
+      <window_info id="Designer" order="2" />
+      <window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.24947916" />
+      <window_info anchor="right" id="Database" order="3" />
       <window_info id="Structure" order="1" side_tool="true" weight="0.25" />
       <window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
-      <window_info id="UI Designer" />
-      <window_info anchor="right" id="Theme Preview" />
+      <window_info id="UI Designer" order="2" />
+      <window_info anchor="right" id="Theme Preview" order="3" />
       <window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
-      <window_info id="Favorites" side_tool="true" />
-      <window_info anchor="bottom" id="Find" order="1" />
-      <window_info anchor="right" id="Commander" order="0" weight="0.4" />
-      <window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
+      <window_info id="Favorites" order="2" side_tool="true" />
       <window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
+      <window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
+      <window_info anchor="right" id="Commander" order="0" weight="0.4" />
       <window_info anchor="bottom" id="Message" order="0" />
       <window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
+      <window_info anchor="bottom" id="Find" order="1" />
     </layout>
   </component>
   <component name="TypeScriptGeneratedFilesManager">
@@ -199,11 +217,18 @@
   <component name="editorHistoryManager">
     <entry file="file://$PROJECT_DIR$/pom.xml">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="630">
+        <state relative-caret-position="798">
           <caret line="42" lean-forward="true" selection-start-line="42" selection-end-line="42" />
         </state>
       </provider>
     </entry>
+    <entry file="file://$PROJECT_DIR$/pom.xml">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="798">
+          <caret line="42" selection-start-line="42" selection-end-line="42" />
+        </state>
+      </provider>
+    </entry>
   </component>
   <component name="masterDetails">
     <states>

+ 0 - 2
Visuallnspection_fjq/visuallnspectioninteface/visuallnspectioninteface.iml

@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4" />