Tag Archives: java

When SSM + Maven project is running, it is prompted that org.springframework.web.servlet.dispatcherserservlet cannot be found

When SSM + Maven project is running, it is prompted that org.springframework.web.servlet.dispatcherserservlet cannot be found

When running SSM project today, an error is reported:
HTTP status 500 – error identifying servlet class org. Springframework. Web. Servlet. Dispatcherservlet
java. Lang. classnotfoundexception: org. Springframework. Web. Servlet. Dispatcherservlet

You can confirm that org. Springframework. Web. Servlet. Dispatcherservlet exists and Maven is imported normally

Problem solving method:
select item – & gt; Right click Properties – & gt; Select deployment asset – & gt; Select Add – & gt; Select Java build path entries – & gt; Next-> Select Maven dependencies – & gt; Finish-> Apply-> OK

It can solve the problem

————————————————
Link to the original text: https://blog.csdn.net/cd19930508/article/details/80256595

NettyAvroRpcClient RPC connection error

2014-12-19 01:05:42,141 (lifecycleSupervisor-1-1) [WARN – org.apache.flume.sink.AbstractRpcSink.start(AbstractRpcSink. java:294 )] Unable to create Rpc client using hostname: xxx.xxx.xxx.xxx, port: 41100
org.apache.flume.FlumeException: NettyAvroRpcClient { host: 121.41.49.51, port: 41100 }: RPC connection error

This problem occurs when flume uses Avro to accept data.

First, let’s see if the port of the connected server is monitored

If you want to send data to port 4383 of 192.168.1.1, you need a server listening to this window, otherwise RPC connection failure will occur

[go] solve the fatal error of go: concurrent map writes map non concurrent security

Map is not concurrency safe, when there are multiple concurrent growths reading and writing the same map  
A panic error occurs

concurrent map writes

For example, this error occurs in the following code:

var mMap map[int]int

func TestMyMap(t *testing.T) {
    mMap = make(map[int]int)

    for i := 0; i < 5000; i++ {
        go func() {
            mMap[i] = i
        }()
        go readMap(i)
    }
}
func readMap(i int) int {
    return mMap[i]
}

There are many ways to solve this problem. Now we use read-write lock,

Concurrent access to map is not safe, and undefined behavior will appear, leading to program exit. Therefore, if you want to access the map concurrently in multiple coroutines, you must provide some synchronization mechanism. Generally, you can control the concurrent access to the map by reading and writing the lock sync.rwmutex. Encapsulating the map and sync.rwmutex can realize the secure concurrent access to the map

Code after transformation

type SMap struct {
    sync.RWMutex
    Map map[int]int
}

func (l *SMap) readMap(key int) (int, bool) {
    l.RLock()
    value, ok := l.Map[key]
    l.RUnlock()
    return value, ok
}

func (l *SMap) writeMap(key int, value int) {
    l.Lock()
    l.Map[key] = value
    l.Unlock()
}

var mMap *SMap

func TestMyMap(t *testing.T) {
    mMap = &SMap{
        Map: make(map[int]int),
    }

    for i := 0; i < 5000; i++ {
        go func() {
            mMap.writeMap(i, i)
        }()
        go readMap(i)
    }
}
func readMap(i int) (int, bool) {
    return mMap.readMap(i)
}

  There are three ways:

1. Use channel
2. Use sync. Map
3. Use map but lock it

Hystrix fuse of spring cloud system

Problem phenomenon: continuous clicking causes the fusing of hystrix

The solution on the Internet is to adjust the maxqueuesize property. After the modification, the following error still appears. Why does the maxqueuesize property not work?Later, by checking the official documents, we found that hystrix also has a queuesizerejectionthreshold property, which controls the maximum threshold of the queue. By default, hystrix only has five, Therefore, even if we set the maxqueuesize value to be larger, it will not work. Both properties must be configured at the same time

could not be queued for execution and no fallback available

Solution

hystrix:
  threadpool:
    default:
      coreSize: 200 #Maximum number of threads for concurrent execution, default 10
      maxQueueSize: 1000 #Max queue size of BlockingQueue, default -1
      queueSizeRejectionThreshold: 800 #Even if maxQueueSize is not reached, the request will be rejected after reaching the value of queueSizeRejectionThreshold

Aspecj cannot intercept method annotations on an interface

Aspecj cannot intercept method annotations on an interface

Aspecj can’t intercept the method annotation on the interface, it can only act on the method of the implementation class. At this time, it needs to use methodinterceptor to implement.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface AopTest {
}

Interface

public interface TestAOPI {
    @AopTest
    public String test();

}

Implementation class 1

@Service
public class TestAOPService implements TestAOPI{
    @Override
    public String test() {
        return "service";
    }
}

Implementation class 2

@Service
public class TestAOPService2 implements TestAOPI{
	@AopTest
    @Override
    public String test() {
        return "service";
    }
}

Aspecj (partially valid)

If and only if the @ aoptest annotation is added to the method of the implementation class, it will take effect (implementation class 2), but implementation class 1 will not

@Aspect
@Configuration
public class AopTestAspect {
  /**
     * Identifies the method annotated with OperationLog
     */
    @Pointcut("@annotation(com.example.demo1.config.AopTest)")
    public void methodHasAopTestAnnotation() {
    }
    
    @Around("methodHasAopTestAnnotation()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("aop!!!");
        return joinPoint.proceed();
    }
}

Solution

It needs to be changed to the following way by manual

@Configuration
public class AopTestConfiguration {
	@Bean
    public Advisor methodPointcutAdvisor() {
        AopTestMethodPointcutAdvisor advisor = new AopTestMethodPointcutAdvisor();
        advisor.setAdvice(new AopTestInterceptor());
        return advisor;
    }

    class AopTestInterceptor implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            String name = invocation.getMethod().getName();
            System.out.println("==============" + name + " before ================");
            Object result = invocation.proceed();
            System.out.println("==============" + name + " after ================");
            return result;
        }
    }
    public class AopTestMethodPointcutAdvisor extends StaticMethodMatcherPointcutAdvisor {
        @Override
        public boolean matches(Method method, Class<?> targetClass) {
        	// Implementing a class method with a target annotation on it
            if(method.isAnnotationPresent(AopTest.class)){
                return true;
            }
            // The method has a corresponding interface method and the interface method is annotated
            Class<?>[] interfaces = method.getDeclaringClass().getInterfaces();
            for (int i = 0; i < interfaces.length; i++) {
                Method[] methods = interfaces[i].getMethods();
                for (int j = 0; j < methods.length; j++) {
                    if(methods[j].getName().equals(method.getName())){
                        return methods[j].isAnnotationPresent(AopTest.class);
                    }
                }
            }
            return false;
        }
    }
}

After Nacos started, the client worker log was printed all the time

After Nacos started, the client worker log was printed all the time

Phenomenon

Print the clientworker log all the time

2020-08-24 00:57:30.977 INFO  [12932] --- [.cn_8848-public] c.a.n.client.config.impl.ClientWorker    : [fixed-nacos.itlym.cn_8848-public] [data-received] dataId=common.yml, group=DEFAULT_GROUP, tenant=public, md5=8c191cace81179b01fb745b5d027c1c8, content=xxx
2020-08-24 00:57:30.989 INFO  [12932] --- [.cn_8848-public] c.a.n.client.config.impl.ClientWorker    : [fixed-nacos.itlym.cn_8848-public] [data-received] dataId=sms-center.yml, group=DEFAULT_GROUP, tenant=public, md5=f12bc945ba0c1d39f3dea2e0977db712, content=xxx
...

Cause analysis

Root cause

Having seen the source code of Nacos before, Nacos will check whether the configuration items are consistent with the server configuration items every 10ms. If not, it will pull the latest configuration from the server therefore, if the MD5 algorithms of Nacos client and Nacos server are different, it will lead to misjudgment, thus constantly refreshing and printing the client worker logs.

Direct cause

My Nacos server is 1.3, and the client uses spring cloud Alibaba. Version . Click to find that the Nacos client version is 1.2

			<dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.1.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

Here, the spring-cloud-alibaba-dependencies‘s official website and warehouse have not been updated for a long time, which is easy to make complaints about users and waste a lot of investigation time.

Other possible reasons

The public is set in the namespace. See the Nacos GitHub

At this time, the best way to solve this problem is not to set the namespace. Otherwise, when Nacos releases a new version, it may be 1.4

Solution

Method 1:

Change the version of client and Nacos server to the same, as follows

client:
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>${spring-cloud-alibaba.version}</version>
    <type>pom</type>
    <scope>import</scope>
    <exclusions>
    <exclusion>
        <artifactId>com.alibaba.nacos</artifactId>
        <groupId>nacos-client</groupId>
    </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>com.alibaba.nacos</groupId>
    <artifactId>nacos-client</artifactId>
    <version>1.3.2</version>
</dependency>

Method 2:

Because spring cloud Alibaba dependencies leaves the gap of properties specified version (default < nacos.client.version> 1.2.1)
so you only need to add

<properties>
	<nacos.client.version>1.2.1</nacos.client.version>
</properties>

Note: if spring cloud starter Nacos config is introduced, it can’t be avoided by this scheme, because ‘spring cloud Alibaba dependencies’ has hard coding problems. When importing, you should actively specify the version.

			 <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
                <version>1.3.0</version>
            </dependency>

Method 3 (middleware upgrade scheme suitable for existing system):

Download the Nacos client Version 1.2.1 code, modify its md5util package path to a new one, and then re publish it to the local or private warehouse.

How to Solve Spring Cloud Error context has been closed already

Context has been closed already solution

Error code

With such a piece of code, the context has been closed already error may occur during running, and once it occurs, it will make an error every time it runs in the future.

@Component
public class SpringContextUtil implements ApplicationContextAware {

    private static ApplicationContext context = null;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextExt.context = applicationContext;
    }

	/**
	 * This static method allows you to retrieve the desired bean from the Spring context.
	 */
	public static <T> T getBean(Class<T> cls) {
        if (context == null)
            throw new IllegalStateException("no application context aviliable.");
        try {
            return (T) context.getBean(cls); // Wrong!
        } catch (BeansException e) {
			throw new RuntimeException(e);
        }
        return (T) null;
    }
}    

Cause analysis

However, when spring cloud context. Jar is included in the classpath, because the contextrefresher class will close the old context when the context is refreshed, so that the context in the static class has been closed, so this error will occur.

Trigger exploration

Find out the direct reason. Find out that a jar that you depend on listens to a notification from MQ. When you hear the message to be refreshed, you will refresh the context, which leads to this phenomenon.

Maven plugin development report error- plugin:3.2 :descriptor fai

Maven plugin error execution default descriptor of goal org. Apache. Maven plugins:maven-plugin-plugin :3.2:descriptor failed

The above error occurred when writing Maven plug-in.

Solution

Display the version number of the specified Maven plugin plugin in POM. XML

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-plugin-plugin</artifactId>
                <version>3.5.2</version>
            </plugin>
        </plugins>
    </build>

other error
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-plugin-plugin:3.2:descriptor (default-descriptor) on project maven-project: Error extracting plugin descriptor: ‘No mojo definitions were found for plugin
How to Solve
Show the version number of the specified maven-plugin-plugin in pom.xml

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-plugin-plugin</artifactId>
                <version>3.5.2</version>
                <configuration>
                    <!-- Or add a descriptor to the mojo class comment -->
                    <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
                </configuration>
            </plugin>
        </plugins>
    </build>

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:testCompile (default-testCompile) on project xxx: Fatal error compiling: basedir D:\xxx\target\generated-test-sources\test-annotations does not exist -> [Help 1]

Solution
Skip the test during installation

mvn install -DskipTests=true

Notes for migrating Oracle jdk8 to openjdk11

Java 8 upgrade Java 11

Because orcle stopped the free follow-up security update of jdk8, the decision to upgrade JDK to 11 was adopted after the decision.

Specific version:

current version

java -version
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)

Target version

java -version
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.2+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.2+9, mixed mode)

Upgrade process:

Download and install jdk11

JDK download
the selection of jdk11 version is: adptopen JDK 11.0.2 + 9
1 https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/tag/jdk-11.0.2+9
Download
https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.2%2B9/OpenJDK11U-jdk_ x64_ windows_ hotspot_ 11.0.2_ 9. Zip
latest or more versions: GitHub view all the released versions of open JDK (change the environment variable to jdk11, if you don’t start a java program such as Tomcat on the command line, you can skip this step, generally you don’t need to use ide on Windows)

Add jdk11: Ctrl Shift Alt + s — & gt; SDKs –> + Select JDK — & gt; Make sure that the compiler of the specified project in the directory is jdk11: Ctrl Shift Alt + S – & gt; Project ——> The project SDK and project SDK level are changed to the newly added 11, and the rest remain unchanged (the project is controlled by Maven’s pom.xml)
update the project compiler to jdk11pom.xml. See the following for the detailed process

Pom.xml transformation

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.0</version>
    <configuration>
        <release>11</release>
    </configuration>
</plugin> 

This plug-in is used to compile the source code; The configuration in it represents the use of 11 to compile

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.22.0</version>
    <configuration>
        <argLine>
            --illegal-access=permit
        </argLine>
    </configuration>
</plugin>

Surefire plug-in is used to execute unit test of an application in the test phase of Maven build life cycle. It will produce two different forms of test results

<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.23.1-GA</version>
</dependency>

The questions are listed as follows:

if the method provided in this paper can not be solved, you can try the following </ H6>
    1. clean the whole project/project and recompile it with Java 11
    1. in idea:
    1. build — build artifacts — all — clean
    1. build — build artifacts — all — build delete the corresponding components under Tomcat/webapps (clear the cache) </ OL>

Question 1

Symptom
resource cannot be resolved to a type
javax. Annotation. Resource
cause
resource class cannot be found; Java 11 has been removed as an alternative solution

Solutions

Add in pom.xml:

<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.1</version>
</dependency>

Reference from stack overflow


Question 2

E rror:java : symbol not found
symbol: class resource
location: package javax.annotation

Solution:

        <dependency>
			<groupId>javax.annotation</groupId>
			<artifactId>javax.annotation-api</artifactId>
			<version>1.3.1</version>
		</dependency>   


Question 3

JAXB (Java. XML. Bind) problems are as follows:

Error:(10, 33) java: Package javax.xml.bind.annotation does not exist
Error:(24, 2) java: Symbol not found
  Symbol: Class XmlRootElement
Error:(28, 6) java: Symbol not found
  Symbol: Class XmlElement
  Location: Class com.xxx.xxx.xxxx.xxx.entity.xxx
  .....

Reasons
openjdk11 has deleted some packages. The following is an announcement:

Removal Of Java EE Modules
There used to be a lot of code in Java SE that was actually related to Java EE. It ended up in six modules that were deprecated for removal in Java 9 and removed from Java 11. Here are the removed technologies and packages:)
 
 
the JavaBeans Activation Framework (JAF) in javax.activation
CORBA in the packages javax.activity, javax.rmi, javax.rmi.CORBA, and org.omg.*
the Java Transaction API (JTA) in the package javax.transaction
JAXB in the packages javax.xml.bind.*   ############ This package is the cause of the problem
JAX-WS in the packages javax.jws, javax.jws.soap, javax.xml.soap, and javax.xml.ws.*
Commons Annotation in the package javax.annotation

The corresponding version is as follows:

<!-- Java 6 = JAXB version 2.0   -->
<!-- Java 7 = JAXB version 2.2.3 -->
<!-- Java 8 = JAXB version 2.2.8 -->
<!-- Java 9 = JAXB version 2.3.0 -->

Note: before the project is which version of JDK to introduce which version, for example, I was java8, so I want to introduce the JAXB version of 2.2.8

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.2.8</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.2.8</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.2.8</version>
</dependency>

Reference from stack overflow


Question 4

Warning: (54,44) newinstance() in Java: Java. Lang. class is obsolete

Solution:

Check the source code of newinstance() in open JDK 11 Java. Lang. class. Some comments are as follows

    /* can be replaced by
     *
     * <pre>{@code
     * clazz.getDeclaredConstructor().newInstance()
     *}</pre>
     */

It can be replaced by the above method

clazz.newInstance();

replace with

clazz.getDeclaredConstructor().newInstance();

Question 5
After starting Tomcat
Artifact upm-web:war: Error during artifact deployment. See server log for details.
View the logs as follows.

19-Mar-2019 09:50:31.061 [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.core.StandardContext.listenerStart Error configuring application listener of class [com.xxx.xxx.xxx.WebContextLoaderListener]
 java.lang.UnsupportedClassVersionError: com/xxx/xxx/xxx/WebContextLoaderListener has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0 (unable to load class [com.xxx.xxx.xxx.WebContextLoaderListener])
	at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2377)
	at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:846)
	...
19-Mar-2019 09:50:31.061 [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.core.StandardContext.listenerStart Skipped installing application listeners due to previous error(s)

Reason
according to the description of exception information (unsupported version of XXX. Class), it means that the current class version to be loaded is 55 (Java 11), which cannot be loaded. The current Java runtime supports 52 (Java 8) versions of. Class files at most
where the java version corresponds to the class version as follows:

J2SE 11 = 55 (0x33 hex),
J2SE 10 = 54 (0x33 hex),
J2SE 9 = 53 (0x33 hex),
J2SE 8 = 52 (0x33 hex),
J2SE 7 = 51 (0x33 hex),
J2SE 6.0 = 50 (0x32 hex),
J2SE 5.0 = 49 (0x31 hex),
JDK 1.4 = 48 (0x30 hex),
JDK 1.3 = 47 (0x2F hex),
JDK 1.2 = 46 (0x2E hex),
JDK 1.1 = 45 (0x2D hex).

It can be seen that the actual cause of the problem is that the program compiled by java8 (Tomcat) calls the program compiled by java11.

Solution:

Using higher version Tomcat 9

Detailed process:

Go to Tomcat official website to download tomcat9, unzip the downloaded zip (modify the Tomcat environment variable and do not use it in the command line, which can be skipped). Modify the Tomcat set in IDE to the newly installed tomcat9. Take idea as an example:

Run edit configurations on the top right — configure on the right side of application server… Click on the top left + add the file location of newly installed tomcat9, OK, confirm to save the modification below, change JRE to newly added JDK 11, save the settings (note whether there are errors in the prompt area below) and run to check whether the configuration is correct


The above is my JDK version upgrade problems. Welcome to add!

There is more than one Web fragment with the same name: “spring_web”.

There is more than one web fragment with the same name: “spring”_ Web “. Error
software used: idea

Error location:

According to the error prompt, say there are duplicate modules, that is, find the duplicate module and delete it.

Solution:

In the upper right running setting of idea, open edit configuration – select your Tomcat server on the left – Deployment – select your component – Pencil Icon on the right – arts to see if there is any extra XXX explored (XXX is the project name)

Monitoring session to determine whether the user is online or not

Contents of articles

Scenario description session container add session remove session logout session failure

Supplement: listen to the change of session property. Session is independent of other session sharing schemes

Scene description

In the spring boot project, in order to simplify the message module, if there is a new message, write it to the database first. If the user is online, set newmessage flag = true in the session of the user receiving the message. The front end only needs to poll the session each time, and does not need to visit the database each time
the session needs to be obtained according to the user ID, so if the user logs in successfully, call the put method, log out or if the session fails, call remove.

Session container

Stores the session of the logged in user

public class LoggedUserSessionContext{
	//The default capacity is 16, you can set a reasonable initial value according to the number of visits to your site to avoid frequent expansion at the beginning.
    private static Map<Integer, HttpSession> sessionMap = new ConcurrentHashMap<>(128);

    public static HttpSession putIfAbsent(Integer userId, HttpSession session) {
    	// previously logged in a client, then return that session, to achieve multi-party login session sharing
	    return sessionMap.putIfAbsent(userId, session);        
    }

    public static void remove(Integer userId) {
        sessionMap.remove(userId);
    }
 
    public static HttpSession getSession(Integer userId) {
        return sessionMap.get(userId);
    }

}

Add session

After the user logs in successfully, execute the following code snippet

HttpSession session = LoggedUserSessionContext.getSession(user.getId());
            if(session != null){
                //Use the previously logged in id
                SpringUtil.setCookie("JSESSIONID", session.getId(), 60 * 30);
			}else{
				session = SpringUtil.getRequest().getSession();
				session.setAttribute(SessionKey.USER, user);
				LoggedUserSessionContext.putIfAbsent(user.getId(), session);
			}

After successful registration, execute the following code snippet

HttpSession session = SpringUtil.getRequest().getSession();
			session.setAttribute(SessionKey.USER, user);
			LoggedUserSessionContext.putIfAbsent(user.getId(), session);

Remove session

On cancellation

User user = (User)session.getAttribute(SessionKey.USER);
LoggedUserSessionContext.remove(user.getId());
session.invalidate();

When session fails

Use the listener to monitor the implementation of session and implement the HttpSessionListener interface


import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebListener
public class SessionListener implements HttpSessionListener {

    //Note: HttpServletRequest's getSession() method, if the current request does not correspond to the session will automatically create a session.
    //Using getSession(false) will not create session, if there is no session corresponding to the current request, it will return null.

   
    //New session created if unknown user browsing
    @Override
    public void sessionCreated(HttpSessionEvent event) {

    }

    //session Destroy User offline, logout login
    @Override
    public void sessionDestroyed(HttpSessionEvent event) throws ClassCastException {
        HttpSession session = event.getSession();
        Object userObj = session.getAttribute(SessionKey.USER);
        if(userObj != null){
        	User user = (User)userObj;
        	LoggedUserSessionContext.remove(user.getId());
        }
        
    }

}

Supplement:

Listen for the change of session property


With HttpSessionAttributeListener * * it is not recommended to listen to HttpSessionAttributeListener * * because it is too frequent

import java.util.HashSet;

import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebListener
public class SessionListener implements HttpSessionListener, HttpSessionAttributeListener {

    //注Meaning: HttpServletRequest's getSession() method, if the current request does not correspond to the session will automatically create a session.
    //use getSession(false) will not create session, if there is no session corresponding to the current request, it will return null.

    //add property user login 
    @Override
    public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
        HttpSession session = httpSessionBindingEvent.getSession();
    }

    //Delete Properties User Logout
    @Override
    public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
        logger.info("--attributeRemoved--");
    }

    //Property substitution Information change
    @Override
    public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
        
    }

    //New session creation If unknown user browsing
    @Override
    public void sessionCreated(HttpSessionEvent event) {
        HttpSession session = event.getSession();
        MySessionContext.AddSession(event.getSession());
    }

    //session Destroy User offline, logout login
    @Override
    public void sessionDestroyed(HttpSessionEvent event) throws ClassCastException {
        HttpSession session = event.getSession();
        MySessionContext.DelSession(session);
    }

}

Session independence

Instead of sharing sessions, you can use code logic to set pseudo sharing and change the container and data structure where sessions are stored

 private static Map<Integer, List<HttpSession>> sessionMap  = new ConcurrentHashMap<>(128);

In this way, each terminal can use session without affecting each other.