文章目录
- 一,序
- 二,样例代码
- 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-