Springboot JSP项目如何以war、jar方式运行

news2024/11/28 22:49:22

文章目录

  • 一,序
  • 二,样例代码
    • 1,代码结构
    • 2,完整代码备份
  • 三,准备工作
    • 1. pom.xml 引入组件
    • 2. application.yml 指定jsp配置
  • 四,war方式运行
    • 1. 修改pom.xml文件
    • 2. mvn执行打包
  • 五,jar方式运行
    • 1. 修改pom-jsp-jar.xml文件
    • 2. 修改 spring-boot-maven-plugin添加版本号
    • 3. 添加资源文件配置(`Jar运行必须`)
    • 4. mvn执行打包
  • 六,war、jar方式运行配置文件区别

一,序

Spring Boot 官方不推荐使用JSP来作为视图,但是仍有部分项目使用了JSP视图,Springboot JSP项目运行方式有war、Jar两种方式。

二,样例代码

1,代码结构

在这里插入图片描述

2,完整代码备份

如何使用下面的备份文件恢复成原始的项目代码,请移步查阅:神奇代码恢复工具

//goto Dockerfile
#基础镜像
FROM openjdk:8-jre-alpine

RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone

#把你的项目war包引入到容器的root目录下
COPY target/*.war /app.war

CMD ["--server.port=8080"]

#项目的启动方式
#ENTRYPOINT ["java","-Xmx400m","-Xms400m","-Xmn150m","-Xss1024k","-jar","/app.war", "--spring.profiles.active=prod"]
ENTRYPOINT ["java","-jar","/app.war"]
//goto pom-jsp-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.fly</groupId>
	<artifactId>docker-demo</artifactId>
	<version>0.0.1</version>
	<packaging>jar</packaging>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.4.RELEASE</version>
		<relativePath />
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.build.timestamp.format>yyyyMMdd-HH</maven.build.timestamp.format>
		<docker.hub>registry.cn-shanghai.aliyuncs.com</docker.hub>
		<java.version>1.8</java.version>
		<skipTests>true</skipTests>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-log4j2</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
		</dependency>
		<dependency>
			<groupId>com.google.guava</groupId>
			<artifactId>guava</artifactId>
			<version>20.0</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional>
		</dependency>

		<!-- JSTL for JSP -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
		</dependency>

		<!-- For JSP compilation -->
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<scope>provided</scope>
		</dependency>
	</dependencies>

	<build>
		<finalName>${project.artifactId}-${project.version}</finalName>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<version>1.4.2.RELEASE</version>
			</plugin>

			<!-- 添加docker-maven插件 -->
			<plugin>
				<groupId>io.fabric8</groupId>
				<artifactId>docker-maven-plugin</artifactId>
				<version>0.41.0</version>
				<executions>
					<execution>
						<phase>package</phase>
						<goals>
							<goal>build</goal>
							<goal>push</goal>
							<goal>remove</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<!-- 连接到带docker环境的linux服务器编译image -->
					<!-- <dockerHost>http://192.168.182.10:2375</dockerHost> -->

					<!-- Docker 推送镜像仓库地址 -->
					<pushRegistry>${docker.hub}</pushRegistry>
					<images>
						<image>
							<!--推送到私有镜像仓库,镜像名需要添加仓库地址 -->
							<name>${docker.hub}/00fly/${project.artifactId}:${project.version}-UTC-${maven.build.timestamp}</name>
							<!--定义镜像构建行为 -->
							<build>
								<dockerFileDir>${project.basedir}</dockerFileDir>
							</build>
						</image>
						<image>
							<name>${docker.hub}/00fly/${project.artifactId}:${project.version}</name>
							<build>
								<dockerFileDir>${project.basedir}</dockerFileDir>
							</build>
						</image>
					</images>
				</configuration>
			</plugin>
		</plugins>
		<resources>
			<resource>
				<directory>src/main/java</directory>
				<excludes>
					<exclude>**/*.java</exclude>
				</excludes>
			</resource>
			<resource>
				<directory>src/main/resources</directory>
				<includes>
					<include>**/**</include>
				</includes>
			</resource>
			<resource>
				<directory>src/main/webapp</directory>
				<includes>
					<include>**/**</include>
				</includes>
				<targetPath>META-INF/resources</targetPath>
			</resource>
		</resources>
	</build>
</project>
//goto pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.fly</groupId>
	<artifactId>docker-demo</artifactId>
	<version>0.0.1</version>
	<packaging>war</packaging>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.4.RELEASE</version>
		<relativePath />
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.build.timestamp.format>yyyyMMdd-HH</maven.build.timestamp.format>
		<docker.hub>registry.cn-shanghai.aliyuncs.com</docker.hub>
		<java.version>1.8</java.version>
		<skipTests>true</skipTests>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-log4j2</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
		</dependency>
		<dependency>
			<groupId>com.google.guava</groupId>
			<artifactId>guava</artifactId>
			<version>20.0</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional>
		</dependency>

		<!-- JSTL for JSP -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
		</dependency>

		<!-- For JSP compilation -->
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<scope>provided</scope>
		</dependency>
	</dependencies>

	<build>
		<finalName>${project.artifactId}-${project.version}</finalName>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>

			<!-- 添加docker-maven插件 -->
			<plugin>
				<groupId>io.fabric8</groupId>
				<artifactId>docker-maven-plugin</artifactId>
				<version>0.41.0</version>
				<executions>
					<execution>
						<phase>package</phase>
						<goals>
							<goal>build</goal>
							<goal>push</goal>
							<goal>remove</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<!-- 连接到带docker环境的linux服务器编译image -->
					<!-- <dockerHost>http://192.168.182.10:2375</dockerHost> -->

					<!-- Docker 推送镜像仓库地址 -->
					<pushRegistry>${docker.hub}</pushRegistry>
					<images>
						<image>
							<!--推送到私有镜像仓库,镜像名需要添加仓库地址 -->
							<name>${docker.hub}/00fly/${project.artifactId}:${project.version}-UTC-${maven.build.timestamp}</name>
							<!--定义镜像构建行为 -->
							<build>
								<dockerFileDir>${project.basedir}</dockerFileDir>
							</build>
						</image>
						<image>
							<name>${docker.hub}/00fly/${project.artifactId}:${project.version}</name>
							<build>
								<dockerFileDir>${project.basedir}</dockerFileDir>
							</build>
						</image>
					</images>
				</configuration>
			</plugin>
		</plugins>
		<resources>
			<resource>
				<directory>src/main/java</directory>
				<excludes>
					<exclude>**/*.java</exclude>
				</excludes>
			</resource>
			<resource>
				<directory>src/main/resources</directory>
				<includes>
					<include>**/**</include>
				</includes>
			</resource>
			<resource>
				<directory>src/main/webapp</directory>
				<includes>
					<include>**/**</include>
				</includes>
				<targetPath>META-INF/resources</targetPath>
			</resource>
		</resources>
	</build>
</project>
//goto shell\docker\1-n\docker-compose.yml
version: '3'
services:
  demo-dk:
    image: demo-dk:1.0
    build:
      context: .
      dockerfile: Dockerfile
    container_name: demo_dk
    deploy:
      resources:
        limits:
          cpus: '0.50'
          memory: 300M
        reservations:
          memory: 128M
    ports:
    - 8085:8085
    - 8086:8086
    - 8087:8087
    logging:
      driver: json-file
      options:
        max-size: 5m
        max-file: '1'
//goto shell\docker\1-n\Dockerfile
#基础镜像
FROM openjdk:8-jre-alpine

RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone

#把你的项目war包引入到容器的root目录下
COPY *.war /app.war

RUN echo \
"#!/bin/sh\n"\
"nohup java -jar /app.war --server.port=8085 &\n"\
"nohup java -jar /app.war --server.port=8086 &"\
>> /start.sh

RUN chmod +x /start.sh
CMD nohup sh -c "/start.sh && java -jar /app.war --server.port=8087"
//goto shell\docker\1-n\restart-docker.sh
#!/bin/bash
docker-compose down && docker system prune -f && docker-compose build && docker-compose up -d
//goto shell\docker\1-n\start.sh
#!/bin/bash

# 命令后加入 & ,保持程序后台持续运行
nohup java -jar /app.war --server.port=8085 & 
nohup java -jar /app.war --server.port=8086 &

# 死循环,保持docker前台运行
while [[ true ]]; do
    sleep 1
done

//goto shell\docker\1-n\start2.sh
#!/bin/bash

# 命令后加入 & ,保持程序后台持续运行
nohup java -jar /app.war --server.port=8085 & 
java -jar /app.war --server.port=8086
//goto shell\docker\scale\docker-compose.yml
version: '3.8'
services:
  nginx:
    image: nginx:alpine
    container_name: nginx
    deploy:
      resources:
        limits:
          cpus: '0.80'
          memory: 50M
        reservations:
          memory: 30M
    ports:
      - 80:80
    restart: on-failure
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/conf.d:/etc/nginx/conf.d
    logging:
      driver: 'json-file'
      options:
        max-size: '5m'
        max-file: '1'  
    depends_on:
      - demo
     
  demo:
    hostname: demo
    image: registry.cn-shanghai.aliyuncs.com/00fly/docker-demo:0.0.1
    deploy:
      resources:
        limits:
          cpus: '0.80'
          memory: 200M
        reservations:
          memory: 100M
    environment:
      - JAVA_OPTS=-server -Xms128m -Xmx128m -Djava.security.egd=file:/dev/./urandom
    restart: on-failure
    logging:
      driver: 'json-file'
      options:
        max-size: '5m'
        max-file: '1'
//goto shell\docker\scale\restart.sh
#!/bin/bash
docker-compose --compatibility restart
//goto shell\docker\scale\scale.sh
#!/bin/bash
docker-compose --compatibility up -d --scale nginx=1 --scale demo=3 
//goto shell\docker\scale\stop.sh
#!/bin/bash
docker-compose down
//goto shell\docker\single\docker-compose.yml
version: '3'
services:
  docker-demo:
    image: registry.cn-shanghai.aliyuncs.com/00fly/docker-demo:0.0.1
    container_name: docker-demo
    deploy:
      resources:
        limits:
          cpus: '0.80'
          memory: 300M
        reservations:
          cpus: '0.05'
          memory: 100M
    ports:
    - 80:8080
    restart: on-failure
    logging:
      driver: json-file
      options:
        max-size: 5m
        max-file: '1'
//goto shell\docker\single\restart.sh
#!/bin/bash
docker-compose down && docker system prune -f && docker-compose up -d
//goto shell\docker\single\stop.sh
#!/bin/bash
docker-compose down
//goto shell\init.sh
#!/bin/bash
dos2unix *
dos2unix */*
dos2unix */*/*

chmod +x *.sh
chmod +x */*.sh
//goto shell\reload-jar.sh
#!/bin/bash
# get pid

pname="springboot-cache.jar"
echo  -e  "jar-name=$pname\r\n"


get_pid(){
 pid=`ps -ef | grep $pname | grep -v grep | awk '{print $2}'`
 echo "$pid"
}

ps -ef|grep $pname

PID=$(get_pid)
if [ -z "${PID}" ] 
then
 echo -e "\r\nJava Application already stop!"
else
 echo -e '\r\nkill -9  '${PID} '\r\n'
 kill -9 ${PID}
 echo -e "Java Application is stop!"
fi

rm -rf info.log

echo -e "\r\nJava Application will startup!\r\n"
jar_path=`find .. -name $pname`

#echo "jarfile=$jar_path"

nohup java -jar $jar_path --server.port=8181 >>./info.log 2>&1 &

ps -ef|grep $pname
//goto shell\reload-war.sh
#!/bin/bash
# get pid
get_pid(){
 pname="docker-demo.war"
 pid=`ps -ef | grep $pname | grep -v grep | awk '{print $2}'`
 echo "$pid"
}

ps -ef|grep docker-demo.war

PID=$(get_pid)
if [ -z "${PID}" ] 
then
 echo -e "\r\nJava Application already stop!"
else
 echo -e '\r\nkill -9  '${PID}
 kill -9 ${PID}
 echo -e "Java Application is stop!"
fi

rm -rf info.log

echo -e "\r\nJava Application will startup!"
nohup java -jar /work/demo/web/docker-demo.war -Xms64m -Xmx64m --server.port=8181 >>./info.log 2>&1 &
#sleep 2s
#nohup java -jar /work/demo/web/docker-demo.war -Xms64m -Xmx64m --server.port=8182 >>./info.log 2>&1 &

ps -ef|grep docker-demo.war

echo -e "please visit: https://test.00fly.online/user/"

#tail -f info.log
//goto shell\start-service.sh
#!/bin/bash 
java -jar docker-demo.war -Xms64m -Xmx64m --server.port=8083 &
//goto src\main\java\com\fly\common\AnnotationHelper.java
package com.fly.common;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * 注解处理工具类
 * 
 * @author 00fly
 * @version [版本号, 2020-04-16]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Slf4j
public class AnnotationHelper
{
    private static List<String> cacheList = new ArrayList<>();
    
    private AnnotationHelper()
    {
        super();
    }
    
    /**
     * 得到类上面的注解信息
     * 
     * @param scannerClass
     * @param allowInjectClass
     * @return
     */
    private static Annotation getClassAnnotation(Class<?> scannerClass, Class<? extends Annotation> allowInjectClass)
    {
        if (!scannerClass.isAnnotationPresent(allowInjectClass))
        {
            return null;
        }
        return scannerClass.getAnnotation(allowInjectClass);
    }
    
    /**
     * 使用Java反射得到注解的信息
     * 
     * @param annotation
     * @param methodName
     * @return Exception
     */
    private static Object getAnnotationInfo(Annotation annotation, String methodName)
        throws Exception
    {
        if (annotation == null)
        {
            return null;
        }
        Method declaredMethod = annotation.getClass().getDeclaredMethod(methodName, null);
        return declaredMethod.invoke(annotation, null);
    }
    
    /**
     * 从上下文获取 Controller注解类的 RequestMapping注解url信息
     * 
     * @param applicationContext
     * @return
     * @throws Exception
     * @see [类、类#方法、类#成员]
     */
    public static List<String> getRequestMappingURL(ApplicationContext applicationContext)
        throws Exception
    {
        if (cacheList.isEmpty())
        {
            synchronized (AnnotationHelper.class)
            {
                List<String> list = new ArrayList<>();
                Map<String, Object> map = applicationContext.getBeansWithAnnotation(Controller.class);
                for (String key : map.keySet())
                {
                    Class<?> clazz = map.get(key).getClass();
                    Annotation classAnnotation = getClassAnnotation(clazz, RequestMapping.class);
                    Object object = getAnnotationInfo(classAnnotation, "value");
                    if (object != null)
                    {
                        String[] array = (String[])object;
                        log.info("{} -> {}", clazz.getName(), object);
                        for (String it : array)
                        {
                            if (!it.contains("$"))
                            {
                                list.add(it);
                            }
                        }
                    }
                }
                cacheList = list;
            }
        }
        return cacheList;
    }
}
//goto src\main\java\com\fly\common\AuthorizationInterceptor.java
package com.fly.common;

import java.net.InetAddress;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

/**
 * 
 * AuthorizationInterceptor
 * 
 * @author 00fly
 * @version [版本号, 2019年7月21日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Component
public class AuthorizationInterceptor extends HandlerInterceptorAdapter
{
    @Autowired
    ApplicationContext applicationContext;
    
    @Value("${server.port}")
    String port;
    
    @Autowired
    HttpSession session;
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception
    {
        if (session.getAttribute("urls") == null)
        {
            session.setAttribute("urls", AnnotationHelper.getRequestMappingURL(applicationContext));
            session.setAttribute("port", port);
            session.setAttribute("ip", InetAddress.getLocalHost().getHostAddress());
        }
        return true;
    }
}
//goto src\main\java\com\fly\common\WebMvcConfig.java
package com.fly.common;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 
 * WebMvcConfig
 * 
 * @author 00fly
 * @version [版本号, 2019年7月21日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer
{
    @Autowired
    private AuthorizationInterceptor authorizationInterceptor;
    
    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        registry.addInterceptor(authorizationInterceptor).addPathPatterns("/user/**");
    }
}
//goto src\main\java\com\fly\demo\model\User.java
package com.fly.demo.model;

import java.io.Serializable;

import lombok.Data;
import org.hibernate.validator.constraints.Range;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Data
public class User implements Serializable
{
    private static final long serialVersionUID = -4621975403168327735L;
    
    private Long userId;
    
    @NotBlank(message = "用户名不能为空")
    private String userName;
    
    @NotNull(message = "年龄不能为空")
    @Range(min = 10, max = 60, message = "年龄必须在{min}-{max}")
    private Integer age;
    
    private String desc;
}
//goto src\main\java\com\fly\demo\service\impl\UserServiceImpl.java
package com.fly.demo.service.impl;

import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.RandomUtils;
import org.springframework.stereotype.Service;

import com.fly.demo.model.User;
import com.fly.demo.service.UserService;
import com.google.common.collect.Lists;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class UserServiceImpl implements  UserService
{
    private List<User> users = Lists.newArrayList();
    
    private Long sequence = 1L;
    
    /**
     * 初始化
     * 
     * @see [类、类#方法、类#成员]
     */
    @PostConstruct
    public void init()
    {
        log.info("PostConstruct users");
        for (int i = 0; i < 5; i++)
        {
            User user = new User();
            user.setUserId(sequence);
            user.setUserName("user_" + sequence);
            user.setAge(RandomUtils.nextInt(10, 40));
            user.setDesc("This is a user " + sequence);
            users.add(user);
            sequence++;
        }
    }
    
    private void insert(User user)
    {
        log.info("insert user : {}", user);
        user.setUserId(sequence + 1);
        users.add(user);
        sequence++;
    }
    
    private void update(User user)
    {
        log.info("update user id = {}", user.getUserId());
        for (User it : users)
        {
            if (it.getUserId().equals(user.getUserId()))
            {
                it.setUserName(user.getUserName());
                it.setAge(user.getAge());
                it.setDesc(user.getDesc());
                return;
            }
        }
    }
    
    /**
     * 新增/根据id更新
     * 
     * @param user
     * @see [类、类#方法、类#成员]
     */
    @Override
    public void saveOrUpdate(User user)
    {
        if (user.getUserId() != null)
        {
            update(user);
            return;
        }
        insert(user);
    }
    
    @Override
    public void delete(Long userId)
    {
        log.info("delete user id = {}", userId);
        for (User user : users)
        {
            if (user.getUserId().equals(userId))
            {
                users.remove(user);
                return;
            }
        }
    }
    
    @Override
    public User get(Long userId)
    {
        log.info("get user id = {}", userId);
        for (User user : users)
        {
            if (user.getUserId().equals(userId))
            {
                return user;
            }
        }
        return null;
    }
    
    @Override
    public List<User> list()
    {
        log.info("list users");
        return users;
    }
}
//goto src\main\java\com\fly\demo\service\UserService.java
package com.fly.demo.service;

import java.util.List;

import com.fly.demo.model.User;

public interface UserService
{
    void saveOrUpdate(User user);
    
    void delete(Long userId);
    
    User get(Long userId);
    
    List<User> list();
    
}
//goto src\main\java\com\fly\demo\web\IndexController.java
package com.fly.demo.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import com.fly.common.AnnotationHelper;

/**
 * 
 * IndexController
 * 
 * @author 00fly
 * @version [版本号, 2020-04-16]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Controller
public class IndexController
{
    @Autowired
    ApplicationContext applicationContext;
    
    /**
     * 首页
     * 
     * @param model
     * @return
     * @throws Exception
     * @see [类、类#方法、类#成员]
     */
    @GetMapping("/")
    public String index(Model model)
        throws Exception
    {
        model.addAttribute("urls", AnnotationHelper.getRequestMappingURL(applicationContext));
        return "/index";
    }
}
//goto src\main\java\com\fly\demo\web\UserApi.java
package com.fly.demo.web;

import javax.validation.Valid;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.fly.demo.model.User;
import com.fly.demo.service.UserService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequestMapping("/user")
public class UserApi
{
    @Autowired
    private UserService userService;
    
    /**
     * 测试添加缓存,后续读取从缓存中取
     * 
     * @param userId
     * @return
     * @see [类、类#方法、类#成员]
     */
    @GetMapping("get")
    public User get(Long userId)
    {
        return userService.get(userId);
    }
    
    /**
     * 新增/更新数据
     * 
     * @param user
     * @return
     * @see [类、类#方法、类#成员]
     */
    @PostMapping("/add")
    public String add(@Valid @ModelAttribute("item") User user, Errors errors, Model model)
    {
        if (errors.hasErrors())
        {
            StringBuilder errorMsg = new StringBuilder();
            for (ObjectError error : errors.getAllErrors())
            {
                errorMsg.append(error.getDefaultMessage()).append(" ");
            }
            if (errorMsg.length() > 0)
            {
                log.info("errors message={}", errorMsg);
            }
            model.addAttribute("items", userService.list());
            return "/user/show";
        }
        userService.saveOrUpdate(user);
        return "redirect:/user/list";
    }
    
    /**
     * 测试删除缓存
     */
    @GetMapping("/delete/{id}")
    public String delete(@PathVariable Long id)
    {
        userService.delete(id);
        return "redirect:/user/list";
    }
    
    @GetMapping({"/", "/list"})
    public String list(Model model)
    {
        User user = new User();
        if (RandomUtils.nextInt(1, 10) > 1)
        {
            user.setUserName(RandomStringUtils.randomNumeric(5));
            user.setAge(RandomUtils.nextInt(10, 70));
            user.setDesc(RandomStringUtils.randomNumeric(5));
        }
        model.addAttribute("item", user);
        model.addAttribute("items", userService.list());
        return "/user/show";
    }
    
    /**
     * 编辑数据
     * 
     * @param id
     * @param model
     * @return
     * @see [类、类#方法、类#成员]
     */
    @GetMapping("/update/{id}")
    public String update(@PathVariable Long id, Model model)
    {
        model.addAttribute("item", userService.get(id));
        model.addAttribute("items", userService.list());
        return "/user/show";
    }
}
//goto src\main\java\com\fly\DemoBootApplication.java
package com.fly;

import java.net.InetAddress;

import org.apache.commons.lang3.SystemUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@SpringBootApplication
public class DemoBootApplication
{
    @Value("${server.port}")
    Integer port;
    
    public static void main(String[] args)
    {
        SpringApplication.run(DemoBootApplication.class, args);
    }
    
    @Bean
    @ConditionalOnWebApplication
    CommandLineRunner openBrowser()
    {
        return args -> {
            if (SystemUtils.IS_OS_WINDOWS && port > 0)
            {
                log.info("★★★★★★★★  now open Browser ★★★★★★★★ ");
                String ip = InetAddress.getLocalHost().getHostAddress();
                String url = "http://" + ip + ":" + port;
                Runtime.getRuntime().exec("cmd /c start /min " + url);
            }
        };
    }
}
//goto src\main\resources\application.yml
server:
  port: 8080
spring:
  mvc:
    view:
      prefix: /WEB-INF/views
      suffix: .jsp
//goto src\main\webapp\WEB-INF\views\index.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<table>
	<tr>
		<th colspan="${fn:length(urls)+1}">Navigate</th>
	</tr>
	<tr>
		<c:forEach var="item" items="${urls}">
			<td><a href="${pageContext.request.contextPath}${item}/">${item}</a></td>
		</c:forEach>
	</tr>
</table>
//goto src\main\webapp\WEB-INF\views\user\show.jsp
<%@ page contentType="text/html;charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<meta charset="utf-8">
<html>
<head>
<title>00fly功能演示</title>
<style>
body {
	margin: 10;
	font-size: 62.5%;
	line-height: 1.5;
}

.blue-button {
	background: #25A6E1;
	padding: 3px 20px;
	color: #fff;
	font-size: 12px;
	border-radius: 2px;
	-moz-border-radius: 2px;
	-webkit-border-radius: 4px;
	border: 1px solid #1A87B9
}

table {
	width: 70%;
}

th {
	background: SteelBlue;
	color: white;
}

td, th {
	border: 1px solid gray;
	font-size: 12px;
	text-align: left;
	padding: 5px 10px;
	overflow:hidden; 
	white-space:nowrap; 
	text-overflow:ellipsis;
	max-width: 200px;
}
</style>
</head>
<script type="text/javascript">
	function formReset() {
		location.href="/user/list";
	}
</script>
<body>
	<center>
    <table>
	  <tr>
		<th colspan="${fn:length(urls)+1}">Navigate</th>
	  </tr>
	  <tr>
		<c:forEach var="item" items="${urls}">
			<td><a href="${pageContext.request.contextPath}${item}/">${item}</a></td>
		</c:forEach>
	  </tr>
    </table>    
	<form:form method="post" modelAttribute="item" action="${pageContext.request.contextPath}/user/add">
		<table>
			<tr>
				<th colspan="3">Add or Edit Item</th>
				<form:hidden path="userId" />
			</tr>
			<tr>
				<td><form:label path="userName">userName:</form:label></td>
				<td><form:input path="userName" size="30" maxlength="30"></form:input></td>
				<td>String <form:errors path="userName" cssStyle="color:red" /></td>
			</tr>
			<tr>
				<td><form:label path="age">age:</form:label></td>
				<td><form:input path="age" size="30" maxlength="30"></form:input></td>
				<td>Integer <form:errors path="age" cssStyle="color:red" /></td>
			</tr>
			<tr>
				<td><form:label path="desc">desc:</form:label></td>
				<td><form:input path="desc" size="30" maxlength="30"></form:input></td>
				<td>String <form:errors path="desc" cssStyle="color:red" /></td>
			</tr>
			<tr>
				<td colspan="3" style="text-align: center;"><input type="submit" class="blue-button" /> <input type="reset" class="blue-button" onclick="formReset()" /></td>
			</tr>
		</table>
	</form:form>
	<h3>Data List</h3>
	<c:if test="${!empty items}">
		<table>
			<tr>
				<th width="5">序号</th>
				<th width="5">Edit</th>
				<th width="5">Delete</th>
				<th width="100">userId</th>
				<th width="150">userName</th>
				<th width="150">age</th>
				<th width="150">desc</th>
			</tr>
			<c:forEach items="${items}" var="it" varStatus="vs">
				<tr>
					<td>${vs.count}</td>
					<td><a href="<c:url value='/user/update/${it.userId}' />">Edit</a></td>
					<td><a href="<c:url value='/user/delete/${it.userId}' />">Delete</a></td>
					<td>${it.userId}</td>
					<td>${it.userName}</td>
					<td>${it.age}</td>
					<td>${it.desc}</td>
				</tr>
			</c:forEach>
		</table>
	</c:if>
	<h3>
		应用端口:<font color="red">${port}</font>
	</h3>
	<h3>
		Server IP<font color="red">${ip}</font>
	</h3>
	</center>
</body>
</html>

三,准备工作

1. pom.xml 引入组件

		<!-- JSTL 支持,按需引入 -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
		</dependency>

		<!-- JSP 编译支持,必须引入-->
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<scope>provided</scope>
		</dependency>

2. application.yml 指定jsp配置

application.yml

spring:
  mvc:
    view:
      prefix: /WEB-INF/views
      suffix: .jsp

四,war方式运行

1. 修改pom.xml文件

	<packaging>war</packaging>

2. mvn执行打包

mvn clean package

执行后会在target目录生成war包,拷贝出来后运行

java -jar docker-demo-0.0.1.war

浏览器访问: http://127.0.0.1:8080/user/ 界面如下:
在这里插入图片描述

五,jar方式运行

复制 pom.xml重命名为 pom-jsp-jar.xml

1. 修改pom-jsp-jar.xml文件

	<packaging>jar</packaging>

2. 修改 spring-boot-maven-plugin添加版本号

注意只能使用1.4.2.RELEASE,其他版本不行

			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<version>1.4.2.RELEASE</version>
			</plugin>

3. 添加资源文件配置(Jar运行必须

		<resources>
			<resource>
				<directory>src/main/java</directory>
				<excludes>
					<exclude>**/*.java</exclude>
				</excludes>
			</resource>
			<resource>
				<directory>src/main/resources</directory>
				<includes>
					<include>**/**</include>
				</includes>
			</resource>
			<resource>
				<directory>src/main/webapp</directory>
				<includes>
					<include>**/**</include>
				</includes>
				<targetPath>META-INF/resources</targetPath>
			</resource>
		</resources>

4. mvn执行打包

mvn clean package -f pom-jsp-jar.xml

执行后会在target目录生成 jar包,拷贝出来后运行

java -jar docker-demo-0.0.1.jar

六,war、jar方式运行配置文件区别

在这里插入图片描述
在这里插入图片描述


有任何问题和建议,都可以向我提问讨论,大家一起进步,谢谢!

-over-

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1166333.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入了解汽车级功率MOSFET NVMFS2D3P04M8LT1G P沟道数据表

汽车级功率MOSFET是一种专门用于汽车电子领域的功率MOSFET。它具有高电压、高电流、高温、高可靠性等特点&#xff0c;能够满足汽车电子领域对功率器件的严格要求。汽车级功率MOSFET广泛应用于汽车电机驱动、泵电机控制、车身控制等方面&#xff0c;能够提高汽车电子系统的效率…

sqlserver字符串拼接

本文主要介绍了sqlserver字符串拼接的实现&#xff0c;文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值。 1. 概 在SQL语句中经常需要进行字符串拼接&#xff0c;以sqlserver&#xff0c;oracle&#xff0c;mysql三种数据库为例&#…

Flink源码解析四之任务调度和负载均衡

源码概览 jobmanager scheduler:这部分与 Flink 的任务调度有关。 CoLocationConstraint:这是一个约束类,用于确保某些算子的不同子任务在同一个 TaskManager 上运行。这通常用于状态共享或算子链的情况。CoLocationGroup & CoLocationGroupImpl:这些与 CoLocationCon…

10月发布的5篇人工智能论文推荐

JudgeLM: Fine-tuned Large Language Models are Scalable Judges https://arxiv.org/pdf/2310.17631.pdf 由于现有基准和指标的限制&#xff0c;在开放式环境中评估大型语言模型(llm)是一项具有挑战性的任务。为了克服这一挑战&#xff0c;本文引入了微调llm作为可扩展“法官…

解决Couldn‘t find meta-data for provider with authority

今天在复用之前写的安装APK的相关代码时发生了报错&#xff0c;那是因为安卓高版本需要新增FileProvider 新增file_paths <?xml version"1.0" encoding"utf-8"?> <paths xmlns:android"http://schemas.android.com/apk/res/android"…

一文读懂以太坊坎昆升级后 Danksharding 扩容路线

以太坊 EIP-4844 是坎昆升级的核心内容&#xff0c;它引入了一种全新的交易类型&#xff08;blob 携带交易&#xff09;以减少以太坊交易费用。blob 携带交易与常规以太坊交易一样&#xff0c;但有一些额外数据被称为 blob。与当前 calldata 存储交易数据不可变和内存只读相比而…

wordpress如何存储远程附件到fss

管理员登录wordpress ,插件---安装插件--搜索"Hacklog Remote Attachment",进行安装并启用 . 设置中找到 Hacklog远程附件.点击进入选项设置. 按照下图填写fss相关参数.这些信息可以在fss详情中查看.目录路径如果没有请先在fss中创建. 4.设置完毕保存,接下来就…

佳易王桌球室台球厅计时计费电脑收费管理系统软件试用版V18.0下载

佳易王桌球室台球厅计时计费电脑收费管理系统软件试用版V18.0下载 一、佳易王桌球棋牌计时计费软件部分功能简介&#xff1a; 1、计时计费功能 &#xff1a;开台时间和所用的时长直观显示&#xff0c;每3秒即可刷新一次时间。 2、销售商品功能 &#xff1a;商品可以绑定桌子…

天天都能买买买,但双11不凑热闹我浑身难受

点击文末“阅读原文”即可参与节目互动 剪辑、音频 / 姝琦、卷圈 运营 / SandLiu 卷圈 监制 / 姝琦 封面 / 姝琦Midjourney 产品统筹 / bobo 场地支持 / 声湃轩北京录音间 有人说满足情绪需求是消费主义的一个重要特征&#xff0c;甚至堪称商家的消费升级歪招。 是吗&…

SpringSecurity+JWT+Redis实现前后端分离认证与授权

spring security的简单原理&#xff1a; SpringSecurity有很多很多的拦截器&#xff0c;在执行流程里面主要有两个核心的拦截器 登陆验证拦截器AuthenticationProcessingFilter 资源管理拦截器AbstractSecurityInterceptor 但拦截器里面的实现需要一些组件来实现&#xff0c;…

Windows系统搭建网盘神器filebrowser结合内网穿透实现公网访问

Windows系统搭建网盘神器filebrowser结合内网穿透实现公网访问 文章目录 Windows系统搭建网盘神器filebrowser结合内网穿透实现公网访问前言1.下载安装File Browser2.启动访问File Browser3.安装cpolar内网穿透3.1 注册账号3.2 下载cpolar客户端3.3 登录cpolar web ui管理界面3…

基于安卓Android的校园快药APP-药店app

项目介绍 本文介绍了校园快药APP软件开发建设的意义和国内外发展现状&#xff0c;然后详细描述了所开发手机APP的可行性分析&#xff0c;并分析了手机APP所要实现的功能。因为校园快药设施较多&#xff0c;而且人口密集&#xff0c;不能更好的管理校园快药&#xff0c;造成需要…

[C++ ]:5.类和对象中(运算符重载补充)+ 类和对象下(初始化列表)

类和对象中&#xff08;运算符重载补充&#xff09; 类和对象下&#xff08;初始化列表&#xff09; 一.运算符重载补充&#xff1a;1.流插入运算符&#xff1a;1.考虑到隐含的参数指针&#xff1a;2.进行优化&#xff01;2-1&#xff1a;解决办法&#xff1a;友元2-2&#xff…

Redis 分片集群

目录 ​编辑一、搭建分片集群 1、集群结构 ​编辑 2、准备实例和配置 3、启动 4、创建集群 二、散列插槽 三、集群伸缩 四、故障转移 1、自动故障转移 2、手动故障转移 五、RedisTemplate 访问分片集群 一、搭建分片集群 1、集群结构 主从和哨兵可以解决高可用、高…

01-SDV全域OS研发思考

背景 近年来&#xff0c;随着汽车“新四化”浪潮的兴起&#xff0c;软件定义已成为产业共识&#xff0c;将深度参与到整个汽车的定义、开发验证销售以及服务全过程。一方面确保软件可升级&#xff0c;跨车型、软件甚至跨车企软件重用。另一方面对于硬来讲&#xff0c;要做到可…

PlantSimulation安装帮助文档端口被占用的解决办法

PlantSimulation安装帮助文档端口被占用的解决办法 从PlantSimulaiton&#xff08;TPS&#xff09;2201开始帮助文档开始使用在线&#xff0c;如果使用本地则需要安装本地文档服务器。但是在安装过程中你可能会遇到&#xff0c;5000断开被占用的情况。解决办法如下&#xff1a…

UTONMOS:元宇宙顺势而上,重构数字化发展新形态

元宇宙&#xff08;Metaverse&#xff09;是一个虚拟的、且与现实世界平行的虚拟世界&#xff0c;由一系列相互关联的技术组成。在这个虚拟世界中&#xff0c;人们可以通过 VR、 AR等设备进入其中&#xff0c;与虚拟人物进行互动。 随着新一代信息技术的飞速发展&#xff0c;元…

将函数模板作为拷贝构造函数

目录 前言 一.认识pair 二.创建一个mypair对象 二.用mypair对象去初始化另一个mypair对象 三.全局的函数模版make_pair 四.map中的insert函数 五.验证 ​​​​​​​前言 当一个类的成员变量有自定义类型时&#xff0c;我们可以考虑将构造函数设为模板&#xff0c;这…

北斗卫星显身手,铁路作业人员安全防护再升级

北斗卫星显身手&#xff01;铁路作业人员安全防护再升级 在铁轨上忙碌的铁路作业人员&#xff0c;承载着运输与交通的重任&#xff0c;他们的辛勤付出为我们的生活提供了便利。然而&#xff0c;背后也隐藏着一系列的安全隐患和风险。为了确保铁路作业人员的安全&#xff0c;保障…

【实践篇】一次Paas化热部署实践分享 | 京东云技术团队

前言 本文是早些年&#xff0c;Paas化刚刚提出不久时&#xff0c;基于部门内第一次Paas化热部署落地经验所写&#xff0c;主要内容是如何构建一些热部署代码以及一些避雷经验。 一、设计-领域模型设计 1.首先&#xff0c;确定领域服务所属的领域 2.其次&#xff0c;确定垂直…