如何使用嵌入式 Jetty 打包和部署 Web 应用程序
How to package and deploy web app with embedded Jetty
我正在开发的 Web 应用程序必须 运行 在 嵌入式 Jetty 上运行(没有外部 Web 应用程序容器)。所有的逻辑和内容都准备好了。我只想了解如何使用 Maven 打包和部署带有嵌入式 Jetty 的 Web 应用程序。以下是详细问题:
目前我 运行 我的网络应用程序在 Jetty 9.x 上 Intellij IDEA 但我想无论如何它都是外部码头。那么什么是jetty嵌入式服务器。考虑到我的网络应用程序的结构(见下文),我怎样才能做到这一点?
我认为包文件一定不是 war 文件,因为它在嵌入式码头服务器上必须是 运行ning。我想一定是可执行jar。但是如何使用 Maven 获取它?
如何将它部署到目标机器上(它只是本地 PC,而不是服务器)?
这是我的项目结构,供您了解情况并参考您的回答:
我真的需要你们的帮助。
2016 年 7 月 4 日更新
我创建了 spring 引导演示应用程序,我已经完成了@techtabu 给我的 spring 引导文档中写的所有内容,但我得到的只是下一个错误:
我还没有打包和部署我的演示应用程序。刚刚按下 "run 'MySpringBootDemoApp'" 按钮。
不仅如此,我的 spring 启动应用程序无法像通常的外部码头那样自行打开浏览器。
这是什么原因。请帮助我!
2016 年 7 月 6 日更新
package com.dvdexchange.controller;
import com.dvdexchange.model.Disk;
import com.dvdexchange.model.MyDisk;
import com.dvdexchange.model.Takenitem;
import com.dvdexchange.service.impl.DiskServiceImpl;
import com.dvdexchange.service.impl.TakenItemServiceImpl;
import com.dvdexchange.service.impl.UserServiceImpl;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
/**Главный контроллер, отвечающий за обработку запросов пользователя по доступу
**на разные адреса веб-сервиса**/
@Controller
public class MainController {
private UserServiceImpl userService = new UserServiceImpl();
private DiskServiceImpl diskService = new DiskServiceImpl();
private TakenItemServiceImpl takenItemService = new TakenItemServiceImpl();
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home() {
return "login"; /*Первая страница, которую должен видеть пользователь - это страница авторизации и она же страница приветствия*/
}
@RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView login(@RequestParam(value = "error", required = false) String error, /*данные о предыдущей неудачной авторизации из предыдущей попытки*/
@RequestParam(value = "logout", required = false) String logout, HttpServletRequest request) { /*или об успешном выходе из аккаунта с данными о запросе на сервер*/
ModelAndView model = new ModelAndView();
if (error != null) {
model.addObject("error", getErrorMessage(request, "SPRING_SECURITY_LAST_EXCEPTION")); /*Получение сообщения об ошибке и запись в модель для отображения пользователю*/
}
if (logout != null) {
model.addObject("msg", "Вы успешно вышли из учетной записи."); /*Запись данных об успешном выходе из аккаунта в модель для отображения пользователю*/
}
model.setViewName("login");
return model;
}
@RequestMapping(value = "/diskLib")
public ModelAndView diskLib() {
String loggedUserEmail = SecurityContextHolder.getContext().getAuthentication().getName();
List<MyDisk> diskList = new ArrayList<MyDisk>();
List<MyDisk> testDiskList; /*Для предварительной проверки множества на валидность*/
int givenDisksCount = 0; /*Количество взятых у пользователя дисков нужно для того, чтобы корректно блокировать кнопку "удалить диск",
**если все диски пользователя отданы*/
testDiskList = userService.getUserDisksWithStatus(loggedUserEmail);
if (testDiskList != null) { //Множество может быть пустым и нужно позаботиться о валидности результата при таком исходе,
diskList = testDiskList; //поэтому используется testDiskList. Валидное пустое множество это не null, а множество( или список), в котором 0 элементов
//Сортировка дисков по id по возрастанию
Collections.sort(diskList, new Comparator<MyDisk>() {
public int compare(MyDisk o1, MyDisk o2) {
return o1.getId() - o2.getId();
}
});
}
for (MyDisk disk : diskList) {
if (disk.isGiven()) {
givenDisksCount++;
}
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("CurrentUserEmail", loggedUserEmail);
modelAndView.addObject("AllDisksOfTheUser", diskList);
modelAndView.addObject("GivenDisksCount", givenDisksCount);
modelAndView.setViewName("diskLib"); /*Указываем для какой страницы предназначены данные (модель). Аналогично в остальных методах*/
return modelAndView;
}
@RequestMapping(value = "/borrowDisk")
public ModelAndView borrowDisk() {
String loggedUserEmail = SecurityContextHolder.getContext().getAuthentication().getName();
List<Disk> allFreeDisks = new ArrayList<Disk>();
List<Disk> testDisks;
testDisks = diskService.getAllFreeDisksForCurrentUser(loggedUserEmail);
if (testDisks != null) { //Множество может быть пустым и нужно позаботиться о валидности результата при таком исходе,
allFreeDisks = testDisks; //поэтому используется testDisks. Валидное пустое множество это не null, а множество( или список), в котором 0 элементов
//Сортировка дисков по id по возрастанию
Collections.sort(allFreeDisks, new Comparator<Disk>() {
public int compare(Disk o1, Disk o2) {
return o1.getId() - o2.getId();
}
});
}
int borrowCount = 0; /*Количество взятых пользователем дисков*/
testDisks = diskService.getAllDisksTakenByLoggedUser(loggedUserEmail);
if (testDisks != null) {
borrowCount = testDisks.size();
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("CurrentUserEmail", loggedUserEmail);
modelAndView.addObject("AllFreeDisks", allFreeDisks); /*Множество всех свободных для аренды дисков для текущего пользователя*/
modelAndView.addObject("BorrowCount", borrowCount);
modelAndView.addObject("BorrowLimit", TakenItemServiceImpl.maxBorrowedDiskCount); /*Существует лимит на количество дисков, которые может взять каждый пользователь в аренду*/
modelAndView.setViewName("borrowDisk");
return modelAndView;
}
@RequestMapping(value = "/takenDisks")
public ModelAndView takenDisks() {
String loggedUserEmail = SecurityContextHolder.getContext().getAuthentication().getName();
List<Disk> takenDisks = new ArrayList<Disk>();
List<Disk> testTakenDisks;
testTakenDisks = diskService.getAllDisksTakenByLoggedUser(loggedUserEmail);
if (testTakenDisks != null) { //Множество может быть пустым и нужно позаботиться о валидности результата при таком исходе,
takenDisks = testTakenDisks; //поэтому используется testFreeDisks. Валидное пустое множество это не null, а множество( или список), в котором 0 элементов
//Сортировка дисков по id по возрастанию
Collections.sort(takenDisks, new Comparator<Disk>() {
public int compare(Disk o1, Disk o2) {
return o1.getId() - o2.getId();
}
});
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("CurrentUserEmail", loggedUserEmail);
modelAndView.addObject("TakenDisks", takenDisks); /*Кол-во дисков, отданных пользователем в аренду*/
modelAndView.addObject("BorrowCount", takenDisks.size());
modelAndView.addObject("BorrowLimit", TakenItemServiceImpl.maxBorrowedDiskCount); /*Существует лимит на количество дисков, которые может взять каждый пользователь в аренду*/
modelAndView.setViewName("takenDisks");
return modelAndView;
}
@RequestMapping(value = "/givenDisks")
public ModelAndView givenDisks() {
String loggedUserEmail = SecurityContextHolder.getContext().getAuthentication().getName();
List<Takenitem> givenDisks = new ArrayList<Takenitem>();
List<Takenitem> testGivenDisks;
testGivenDisks = takenItemService.getAllDisksGivenByLoggedUser(loggedUserEmail);
if (testGivenDisks != null) { //Множество может быть пустым и нужно позаботиться о валидности результата при таком исходе,
givenDisks = testGivenDisks; //поэтому используется testFreeDisks. Валидное пустое множество это не null, а множество( или список), в котором 0 элементов
//Сортировка дисков по id по возрастанию
Collections.sort(givenDisks, new Comparator<Takenitem>() {
public int compare(Takenitem o1, Takenitem o2) {
return o1.getIddisk() - o2.getIddisk();
}
});
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("CurrentUserEmail", loggedUserEmail);
modelAndView.addObject("GivenDisks", givenDisks); /*Множество отданных дисков*/
modelAndView.addObject("GivenCount", givenDisks.size()); /*Кол-во отданных дисков*/
modelAndView.addObject("TotalCount", userService.getUserDisksWithStatus(loggedUserEmail).size()); /*Общее кол-во дисков собственных пользователя*/
modelAndView.setViewName("givenDisks");
return modelAndView;
}
/*Получаем исключение с необходимым текстом*/
private String getErrorMessage(HttpServletRequest request, String key) {
Exception exception = (Exception) request.getSession().getAttribute(key);
String error = "";
/*Получение понятного для пользователя текста ошибки в зависимостит от причин отказа в доступе*/
if (exception instanceof BadCredentialsException) { /*Если неверно введен пароль, а логин верный и аккаунт исправен и не заблокирован*/
error = "Неверные \"Логин\" и/или \"Пароль\"!"; /*Но для безопасности все-равно нельзя указывать, что именно введено неправильно*/
} else if (exception instanceof LockedException) { /*Если аккаунт заблокирован*/
error = exception.getMessage();
} else {
error = "Неверные \"Логин\" и/или \"Пароль\"!"; /*если неверны логин и пароль или только логин*/
}
return error;
}
}
不要注意评论 - 它们是俄语的。
我同意 deffymo 的评论。使用 Spring-引导。使用嵌入式服务器要容易得多。如果您使用的是 IntelliJ,请在 create New Project window、select Spring Initializr 上创建一个 Spring 启动项目。另请参考spring-boot documentation.
但是,请记住 spring-boot 使用 Tomcat 作为默认的嵌入式服务器。您应该排除 Tomcat 并在依赖项中添加码头。查看 docs 如何操作。
But how can I get it using Maven?
在您的 pom 文件中将包装定义为 jar。
<groupId>your-group</groupId>
<artifactId>your-project-name</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
How can I deploy it on target machine (it's going to be just local PC - not server)?
运行 jar 文件作为 java jar.
java -jar your-project-name.jar
您可能还想看看 maven shade plugin
来自描述
"this plugin provides the capability to package the artifact in an uber-jar,"
您可以使用 java -jar yourapp.jar
启动您的应用程序
我正在开发的 Web 应用程序必须 运行 在 嵌入式 Jetty 上运行(没有外部 Web 应用程序容器)。所有的逻辑和内容都准备好了。我只想了解如何使用 Maven 打包和部署带有嵌入式 Jetty 的 Web 应用程序。以下是详细问题:
目前我 运行 我的网络应用程序在 Jetty 9.x 上 Intellij IDEA 但我想无论如何它都是外部码头。那么什么是jetty嵌入式服务器。考虑到我的网络应用程序的结构(见下文),我怎样才能做到这一点?
我认为包文件一定不是 war 文件,因为它在嵌入式码头服务器上必须是 运行ning。我想一定是可执行jar。但是如何使用 Maven 获取它?
如何将它部署到目标机器上(它只是本地 PC,而不是服务器)?
这是我的项目结构,供您了解情况并参考您的回答:
我真的需要你们的帮助。
2016 年 7 月 4 日更新
我创建了 spring 引导演示应用程序,我已经完成了@techtabu 给我的 spring 引导文档中写的所有内容,但我得到的只是下一个错误:
我还没有打包和部署我的演示应用程序。刚刚按下 "run 'MySpringBootDemoApp'" 按钮。
不仅如此,我的 spring 启动应用程序无法像通常的外部码头那样自行打开浏览器。
这是什么原因。请帮助我!
2016 年 7 月 6 日更新
package com.dvdexchange.controller;
import com.dvdexchange.model.Disk;
import com.dvdexchange.model.MyDisk;
import com.dvdexchange.model.Takenitem;
import com.dvdexchange.service.impl.DiskServiceImpl;
import com.dvdexchange.service.impl.TakenItemServiceImpl;
import com.dvdexchange.service.impl.UserServiceImpl;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
/**Главный контроллер, отвечающий за обработку запросов пользователя по доступу
**на разные адреса веб-сервиса**/
@Controller
public class MainController {
private UserServiceImpl userService = new UserServiceImpl();
private DiskServiceImpl diskService = new DiskServiceImpl();
private TakenItemServiceImpl takenItemService = new TakenItemServiceImpl();
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home() {
return "login"; /*Первая страница, которую должен видеть пользователь - это страница авторизации и она же страница приветствия*/
}
@RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView login(@RequestParam(value = "error", required = false) String error, /*данные о предыдущей неудачной авторизации из предыдущей попытки*/
@RequestParam(value = "logout", required = false) String logout, HttpServletRequest request) { /*или об успешном выходе из аккаунта с данными о запросе на сервер*/
ModelAndView model = new ModelAndView();
if (error != null) {
model.addObject("error", getErrorMessage(request, "SPRING_SECURITY_LAST_EXCEPTION")); /*Получение сообщения об ошибке и запись в модель для отображения пользователю*/
}
if (logout != null) {
model.addObject("msg", "Вы успешно вышли из учетной записи."); /*Запись данных об успешном выходе из аккаунта в модель для отображения пользователю*/
}
model.setViewName("login");
return model;
}
@RequestMapping(value = "/diskLib")
public ModelAndView diskLib() {
String loggedUserEmail = SecurityContextHolder.getContext().getAuthentication().getName();
List<MyDisk> diskList = new ArrayList<MyDisk>();
List<MyDisk> testDiskList; /*Для предварительной проверки множества на валидность*/
int givenDisksCount = 0; /*Количество взятых у пользователя дисков нужно для того, чтобы корректно блокировать кнопку "удалить диск",
**если все диски пользователя отданы*/
testDiskList = userService.getUserDisksWithStatus(loggedUserEmail);
if (testDiskList != null) { //Множество может быть пустым и нужно позаботиться о валидности результата при таком исходе,
diskList = testDiskList; //поэтому используется testDiskList. Валидное пустое множество это не null, а множество( или список), в котором 0 элементов
//Сортировка дисков по id по возрастанию
Collections.sort(diskList, new Comparator<MyDisk>() {
public int compare(MyDisk o1, MyDisk o2) {
return o1.getId() - o2.getId();
}
});
}
for (MyDisk disk : diskList) {
if (disk.isGiven()) {
givenDisksCount++;
}
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("CurrentUserEmail", loggedUserEmail);
modelAndView.addObject("AllDisksOfTheUser", diskList);
modelAndView.addObject("GivenDisksCount", givenDisksCount);
modelAndView.setViewName("diskLib"); /*Указываем для какой страницы предназначены данные (модель). Аналогично в остальных методах*/
return modelAndView;
}
@RequestMapping(value = "/borrowDisk")
public ModelAndView borrowDisk() {
String loggedUserEmail = SecurityContextHolder.getContext().getAuthentication().getName();
List<Disk> allFreeDisks = new ArrayList<Disk>();
List<Disk> testDisks;
testDisks = diskService.getAllFreeDisksForCurrentUser(loggedUserEmail);
if (testDisks != null) { //Множество может быть пустым и нужно позаботиться о валидности результата при таком исходе,
allFreeDisks = testDisks; //поэтому используется testDisks. Валидное пустое множество это не null, а множество( или список), в котором 0 элементов
//Сортировка дисков по id по возрастанию
Collections.sort(allFreeDisks, new Comparator<Disk>() {
public int compare(Disk o1, Disk o2) {
return o1.getId() - o2.getId();
}
});
}
int borrowCount = 0; /*Количество взятых пользователем дисков*/
testDisks = diskService.getAllDisksTakenByLoggedUser(loggedUserEmail);
if (testDisks != null) {
borrowCount = testDisks.size();
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("CurrentUserEmail", loggedUserEmail);
modelAndView.addObject("AllFreeDisks", allFreeDisks); /*Множество всех свободных для аренды дисков для текущего пользователя*/
modelAndView.addObject("BorrowCount", borrowCount);
modelAndView.addObject("BorrowLimit", TakenItemServiceImpl.maxBorrowedDiskCount); /*Существует лимит на количество дисков, которые может взять каждый пользователь в аренду*/
modelAndView.setViewName("borrowDisk");
return modelAndView;
}
@RequestMapping(value = "/takenDisks")
public ModelAndView takenDisks() {
String loggedUserEmail = SecurityContextHolder.getContext().getAuthentication().getName();
List<Disk> takenDisks = new ArrayList<Disk>();
List<Disk> testTakenDisks;
testTakenDisks = diskService.getAllDisksTakenByLoggedUser(loggedUserEmail);
if (testTakenDisks != null) { //Множество может быть пустым и нужно позаботиться о валидности результата при таком исходе,
takenDisks = testTakenDisks; //поэтому используется testFreeDisks. Валидное пустое множество это не null, а множество( или список), в котором 0 элементов
//Сортировка дисков по id по возрастанию
Collections.sort(takenDisks, new Comparator<Disk>() {
public int compare(Disk o1, Disk o2) {
return o1.getId() - o2.getId();
}
});
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("CurrentUserEmail", loggedUserEmail);
modelAndView.addObject("TakenDisks", takenDisks); /*Кол-во дисков, отданных пользователем в аренду*/
modelAndView.addObject("BorrowCount", takenDisks.size());
modelAndView.addObject("BorrowLimit", TakenItemServiceImpl.maxBorrowedDiskCount); /*Существует лимит на количество дисков, которые может взять каждый пользователь в аренду*/
modelAndView.setViewName("takenDisks");
return modelAndView;
}
@RequestMapping(value = "/givenDisks")
public ModelAndView givenDisks() {
String loggedUserEmail = SecurityContextHolder.getContext().getAuthentication().getName();
List<Takenitem> givenDisks = new ArrayList<Takenitem>();
List<Takenitem> testGivenDisks;
testGivenDisks = takenItemService.getAllDisksGivenByLoggedUser(loggedUserEmail);
if (testGivenDisks != null) { //Множество может быть пустым и нужно позаботиться о валидности результата при таком исходе,
givenDisks = testGivenDisks; //поэтому используется testFreeDisks. Валидное пустое множество это не null, а множество( или список), в котором 0 элементов
//Сортировка дисков по id по возрастанию
Collections.sort(givenDisks, new Comparator<Takenitem>() {
public int compare(Takenitem o1, Takenitem o2) {
return o1.getIddisk() - o2.getIddisk();
}
});
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("CurrentUserEmail", loggedUserEmail);
modelAndView.addObject("GivenDisks", givenDisks); /*Множество отданных дисков*/
modelAndView.addObject("GivenCount", givenDisks.size()); /*Кол-во отданных дисков*/
modelAndView.addObject("TotalCount", userService.getUserDisksWithStatus(loggedUserEmail).size()); /*Общее кол-во дисков собственных пользователя*/
modelAndView.setViewName("givenDisks");
return modelAndView;
}
/*Получаем исключение с необходимым текстом*/
private String getErrorMessage(HttpServletRequest request, String key) {
Exception exception = (Exception) request.getSession().getAttribute(key);
String error = "";
/*Получение понятного для пользователя текста ошибки в зависимостит от причин отказа в доступе*/
if (exception instanceof BadCredentialsException) { /*Если неверно введен пароль, а логин верный и аккаунт исправен и не заблокирован*/
error = "Неверные \"Логин\" и/или \"Пароль\"!"; /*Но для безопасности все-равно нельзя указывать, что именно введено неправильно*/
} else if (exception instanceof LockedException) { /*Если аккаунт заблокирован*/
error = exception.getMessage();
} else {
error = "Неверные \"Логин\" и/или \"Пароль\"!"; /*если неверны логин и пароль или только логин*/
}
return error;
}
}
不要注意评论 - 它们是俄语的。
我同意 deffymo 的评论。使用 Spring-引导。使用嵌入式服务器要容易得多。如果您使用的是 IntelliJ,请在 create New Project window、select Spring Initializr 上创建一个 Spring 启动项目。另请参考spring-boot documentation.
但是,请记住 spring-boot 使用 Tomcat 作为默认的嵌入式服务器。您应该排除 Tomcat 并在依赖项中添加码头。查看 docs 如何操作。
But how can I get it using Maven?
在您的 pom 文件中将包装定义为 jar。
<groupId>your-group</groupId>
<artifactId>your-project-name</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
How can I deploy it on target machine (it's going to be just local PC - not server)?
运行 jar 文件作为 java jar.
java -jar your-project-name.jar
您可能还想看看 maven shade plugin
来自描述
"this plugin provides the capability to package the artifact in an uber-jar,"
您可以使用 java -jar yourapp.jar
启动您的应用程序