Upload
fedor-lavrentyev
View
54
Download
0
Embed Size (px)
Citation preview
Промышленное программирование
Сборка проекта
Использование готового кода
Утилитыpublic String join(String sep, Object… tokens) { StringBuilder sb = new StringBuilder(); for (Object token : tokens) { if (!sb.isEmpty()) { sb.append(sep); } sb.append(token); } return sb.toString();}
Утилитыimport com.google.guava....Joiner;
Joiner.on(“,”).join(anything);
Сборка и деплойcd myProjectjavac $(find src/ -name “*.java”)# Noo, what about classpath?export CLASSPATH=lib/...javac $(find src/ -name “*.java”)# Noo, what about cleaning?rm -rf target/javac $(find src/ -name “*.java”)# Noo, what about download some libraries?wget http://repo1.maven.org/maven2/log4j/log4j/1.2.17/log4j-1.2.17.jarjavac $(find src/ -name “*.java”)# Oh, sorry, no compiler for Java 8 =(# FFFFFFFFFFFUUUUUUUUUUUUU!!!!!1111
Сборка и деплойmvn clean install
ИнициализацияService service = new ServiceImpl();FooHandler handler = new FastFooHandler(HANDLE_SPEED);service.setHandler(handler);int importantParameter = Integer.parseInt(args[1])service.setImportantParameter(importantParameter);Listener l1 = new LazyListener();Listener l2 = new DilligentListener();service.setListeners(Arrays.asList(l1, l2));service.init();
Инициализацияclass ServiceImpl implements Service { @Autowired Handler handler;
@Autowired List<Listener> listeners;
@Value(“#{args[1]}”) int importantParameter;
@PostConstruct void init() { … }}
У Java очень большое сообществоВсе ваши задачи кто-то уже решилК любому сервису кто-то уже написал APIК каждому багу кто-то уже настругал
костыль workaround
Общие библиотекиПодробно документированыОбильно обсуждены на форумахПочти стабильно работаютДоступны для скачивания в репозиториях
Google GuavaОбертки над объектами и исключениямиНовые коллекции, Immutable-коллекцииФункциональщинаМногопоточностьКешированиеРабота со строкамиХеш-функцииРабота с потоками и файловой системойВолшебные Reflection
Apache CommonsРасширения для java.langНовые коллекцииПотоки и файловая системаАлгоритмы кодирования и хешированияСжатие и распаковкаConnection Pooling…
Логгингjava.util.logging (JUL)Apache commons-loggingLog4jSLF4jLogback
ТестированиеJUnitTestNGUnitilsMockitoJMockSpring Test *…
Как подключить библиотеку?
Apache MavenMaven - “фреймворк для автоматизации
сборки проектов...” (с) WikipediaКонфигурируется декларативно на XML-
языке POM (Project Object Model)Проект Maven ~= java-модуль“Соглашение превыше конфигурации”
Maven репозиторийМногие java-библиотеки публично
опубликованы как проекты MavenMaven Project ~= java-библиотека + POM-
файл + ресурсыПроекты доступны в центральном
репозитории Maven http://search.maven.org/
Maven проектыКаждый опубликованный maven-проект
имеет уникальный идентификаторИдентификатор состоит из имени группы,
имени артефакта, версии.Внутри проекта смежные артефакты
различаются т.н. классификатором
Пример проектаcom.google.guava:guava-gwt:17.0
Группа - com.google.guavaАртефакт - guava-gwtВерсия - 17.0Неявный классификатор - jar
Структура проекта/lection01 |-- src/ | |-- main/ | | |-- java/ | | | \-- ru/fizteh/java/fediq/ # Структура пэкейджа | | | \-- LectionMain.java | | \-- resources/ | | \-- config.properties | \-- test/ | \-- java/ | \-- ru/fizteh/java/fediq/ | \-- LectionTest.java \-- pom.xml # конфигурация проекта
Пример конфигурации Maven<project> <modelVersion>4.0.0</modelVersion> # Волшебство <groupId>ru.fizteh.java2.fediq</groupId> # Аналог package <artifactId>lection-maven</artifactId> # Имя проекта <version>1.0</version> # Версия <dependencies> <dependency> # Используемая библиотека <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>2.5.6</version> </dependency> </dependencies></project>
Конфигурация Maven
Жизненные циклы проекта MavenСборка состоит из этапов - жизненных циклов
(lifecycles)Циклы выполняются последовательно, с
первого до целевогоКраткий список жизненных циклов - verify,
compile, test, install, deployСборочная задача может быть присвоена
какому-то этапу или выполняться отдельно
Работа с Maven$ mvn dependency:tree # Показать дерево зависимостей$ mvn dependency:copy-dependencies # Скачать все зависимости
$ mvn compile # Скомпилировать код$ mvn test # Запустить юнит-тесты$ mvn package # Собрать (сжать и т.д.) артефакты$ mvn install # Загрузить артефакт в локальный репозиторий$ mvn deploy # Загрузить артефакт в удаленный репозиторий$ mvn clean # Убрать за собой всякое
$ mvn clean install # Пересобрать проект
$ mvn install # = mvn validate compile test package install ...
ЗависимостиЗависимости проекта перечисляются в
блоке <dependencies>Maven умеет отслеживать транзитивные
зависимостиВо время сборки maven автоматически
скачает все необходимые файлыЗадача dependencies:copy-dependencies
сложит зависимости в директорию target/
ScopesScope - ситуация или этап, в котором
потребуется зависимостьprovided - только для компиляцииruntime - только в рантаймеtest - только в тестеcompile (default) - на стадии компиляции и в
рантаймеsystem - предоставляется окружением
Пример указания зависимостей<dependencies> <dependency> <groupId>com.jolbox</groupId> <artifactId>bonecp</artifactId> <version>0.8.0.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency></dependencies>
ПлагиныЗадачи в maven поставляются плагинамиПлагин содержит в себе несколько целейПлагины содержатся в тех же
репозиториях, что и другие проектыПлагины также “достаются” автоматическиПлагин конфигурируется в pom-файлеРяд плагинов подключен по умолчанию -
clean, compile, install, surefire и др.
Пример конфигурации плагина<build> ... <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins></build>
Пример конфигурации плагина<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skip>true</skip> <skip>false</skip> <testFailureIgnore>true</testFailureIgnore> </configuration></plugin>
Пример конфигурации плагина<plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>someone-execution-id</id> <phase>package</phase> <goals> <goal>attached</goal> </goals> </execution> </executions></plugin>
JAR-файлыПо окончании сборки проект будет
упакован в jar-файлjar - это обычный zip-архив, содежащий
скомпилированные классы и метаданныеПри желании, в аналогичные jar-файлы
можно сохранить исходники, ресурсы и прНа последней стадии (деплое) jar-файлы
заливаются в репозиторий
Наследование проектовДля поддержки принципа DRY maven
поддерживает наследование проектовОсновная конфигурация производится в
“родительском” проектеДочерние проекты подключают его с
помощью тега <parent>Часто родительский проект является
корнем “многомодульного” проекта
Многомодульные проектыГруппа близких проектов может быть
объединена в многмодульный проектВсе модули перечисляются в корневом
проекте в теге <modules/>Также в корневом проекте указывается
<packaging>pom</packaging>
Пример - корневой проект<project> <modelVersion>4.0.0</modelVersion> <groupId>ru.fizteh.java2</groupId> <artifactId>parent-pom</artifactId> <packaging>pom</packaging> <version>1.0</version> <modules> <module>example-jdbc</module> <module>example-spring</module> </modules> <build/> ... <dependencies/> ...</project>
Пример - дочерний проект<project> <parent> <groupId>ru.fizteh.java2</groupId> <artifactId>parent-pom</artifactId> <version>1.0</version> </parent> <groupId/> <version/> … # Унаследованные параметры можно перезаписывать <artifactId>example-jdbc</artifactId> <packaging>jar</packaging>
<dependencies/> ...</project>
Рекомендуемая литература
Компоновка приложенияПромышленное программирование
Связанность кода
http://infomgmt.wordpress.com/
Больше кода - сложнее работатьСо временем число сущностей растетЧисло связей растет на порядок быстрееЕсли не предпринять мер, быстро
наступает коллапс разработки
И это очень частая проблема
Финансовые аспектыСложность рефакторингаСложность изменения APIВремя вхождения (нового разработчика)Коэффициент автобуса
Логическая компонентаКомпонента - автономная логическая
единица кодаВнутри компоненты происходит
контролируемое тесное взаимодействиеНаружу предоставляется API (контракт)Компонента взаимодействует с соседями
через их API
Слабая связанность
http://infomgmt.wordpress.com/
Сильная связанность
http://infomgmt.wordpress.com/
Закон ДеметрыЕсли у A есть доступ к Би у Б есть доступ к В,то А не нужен доступ к В
Уровни связанностиСодержимоеОбщее состояниеВнешний контрактСтруктура данныхСообщенияНет связности
Связность (сцепление) компонентыКомпонента должна быть осмысленнаЕе части должны иметь что-то общееСвязность - мера взаимосвязи между
составными частями одной компонентыПринцип наименьшего удивления
опирается на связность
Типы связности (сцепления)ФункциональнаяПоследовательнаяВременная/процедурнаяЛогическая/тематическаяСлучайная
Фрактальная природа компонентыКомпонента создана на основе маленьких
составных частейИх разработчик рассматривал каждую
такую часть как отдельную компонентуВаша сложная система - на самом деле,
одна из компонент в бизнес-процессе
Фрактальная природа компоненты
Основная идея проектированияМеньше связанность - больше сцепление
МодульностьМодульность - принцип разработки ПО,
согласно которому код разделяется на отдельные функционально законченные сущности - модули
Это позволяет переиспользовать кодЭто упрощает проектированиеЭто упрощает дистрибуцию (см. Maven)
SPI - набор интерфейсов, предлагаемый к реализации пользователями
API - набор моделей, интерфейсов и т.п., реализованный модулем
Контракт - формальное соглашение об использовании модуля
Contract-first Development - парадигма разработки “от контракта”
SPI, API, контракт
Интерфейс и реализацияКак правило, API модуля не содержит
сложных конструкций и зависимостейВнешние интерфейсы (API) модуля можно
выделить в отдельный легкий модульРеализация остается в отдельном тяжелом
модуле, о котором пользователи могут не знать
Зависимости между модулямиПереизбыток зависимостей в системе
вызывает непредсказуемые проблемыРазделение реализации и интерфейса
сильно сокращает объем знаний и зависимостей, необходимый для использования модуля
Внедрение зависимостей
Пример прямого управленияvoid main() { Brain brain = new MonkeyBrain(); Tail tail = new FishTail(); TeethHolder teeth = new SharkJaws(); //Animal animal = new FourLimbedMonster(); FourLimbedMonster animal = new FourLimbedMonster(); animal.setTail(tail); animal.setTeethHolder(teeth); animal.doHunt(); // NoSuchBrainException}
Пример прямого управленияvoid main() { Brain brain = new MonkeyBrain(); Tail tail = new FishTail(); TeethHolder teeth = new SharkJaws(); Animal animal = new FourLimbedMonster(brain, tail, teeth); animal.doHunt();}
Встроим зависимостиinterface DependencyInjector { void put(Object o); <T> T get(Class<T> clazz);}
Встроим зависимостиclass FourLimbedMonster implements Animal { Brain brain; TeethHolder teeth; Tail tail;
public FourLimbedMonster(DependencyInjector di) { brain = di.get(Brain.class); teeth = di.get(TeethHolder.class); tail = di.get(Tail.class); }}
Встроим зависимостиvoid main() { DependencyInjector di = new DependencyInjectorImpl(); di.put(new MonkeyBrain()); di.put(new FishTail()); di.put(new SharkJaws()); Animal animal = new FourLimbedMonster(di); animal.doHunt();}
Выделим зависимости в модулиclass ModuleWithBodyParts { public static void fillBodyParts(DependencyInjector di) { di.put(new MonkeyBrain()); di.put(new FishTail()); di.put(new SharkJaws()); }}class ModuleWithAnimal { public static Animal buildAnimal(DependencyInjector di) { return new FourLimbedMonster(di); }}
Выделим зависимости в модулиvoid main() { DependencyInjector di = new DependencyInjectorImpl(); ModuleWithBodyParts.fillBodyParts(di); Animal animal = ModuleWithAnimal.buildAnimal(di); animal.doHunt();}
Обобщим еще немногоinterface DependenciesSource { void fill(DependencyInjector di);}
void main(List<DependenciesSource> sources) { DependencyInjector di = new DependencyInjectorImpl(); for (DependenciesSource source : sources) { source.fill(di); } di.get(Animal.class).doHunt();}
Spring FrameworkПромышленное программирование
Хочется Dependency Injection?
Spring FrameworkМощная инфраструктурная платформа для
создания сложного JVM-based ПОИнтеграция со множеством популярных
фреймворков, внешних сервисов и JSRСквозная концепция программированияОгромное сообществоДе-факто стандарт Java-платформы
Из коробки:Application Context - DI и каталог ресурсовИнтеграция с БД (JDBC, ORM, транзакции)Web - Servlets, MVC, JSP, REST, ...XML и JSON биндингиSpEL - язык для управления ресурсамиAOP, Instrumentation и прочий сатанизмТестирование с JUnit и TestNG...
Пример из жизниpublic interface Brain { String getIdea();}
public interface Animal { String doHunt();}
Пример из жизниpublic class MonkeyBrain implements Brain { public String getIdea() { return "Banana"; }}
Пример из жизниpublic class Kitten implements Animal { private Brain brain; public void setBrain(Brain brain) { this.brain = brain; } public String doHunt() { return String.format("Meow, %s!", brain.getIdea()); }}
Пример из жизниimport org.springframework.context.ApplicationContext;
void main() { ApplicationContext ctx = ...; // Magic
Animal animal = ctx.getBean(Animal.class);
animal.doHunt(); // Meow, Banana!}
XML-based заклинания
Spring XML config<beans ... > <bean name="someoneBrain" class="MonkeyBrain"/>
<bean name="kitten" class="Kitten"> <property name="brain" ref="someoneBrain"/> </bean></beans>
Шапка выглядит так<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd ">
Autowiring<beans ... > <bean name="someoneBrain" class="MonkeyBrain"/>
<bean name="kitten" class="Kitten" autowire=”byType”/>
<bean name="kitten" class="Kitten"> <property name="brain" ref="someoneBrain"/> </bean></beans>
Autowiring by default<beans ... default-autowire="byType"> <bean name="someoneBrain" class="MonkeyBrain"/>
<bean name="kitten" class="Kitten"/></beans>
Запуск контекстаvoid main() { ApplicationContext ctx = new ClassPathXmlApplicationContext("ctx.xml");
Animal animal = ctx.getBean(Animal.class);
animal.doHunt(); // Meow, Banana!}
Annotation-based заклинания
@Component annotation@Componentpublic class MonkeyBrain implements Brain { public String getIdea() { return "Banana"; }}
@Autowired annotation@Componentpublic class Kitten implements Animal { @Autowired private Brain brain;
public String doHunt() { return String.format("Meow, %s!", brain.getIdea()); }}
Запуск контекстаvoid main() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.scan(“package.name”); ctx.refresh(); Animal animal = ctx.getBean(Animal.class); System.out.println(animal.doHunt());}
Animal animal = ctx.getBean(Animal.class);
animal.doHunt(); // Meow, Banana!}
@Configuration и @ComponentScan@Configuration@ComponentScan("package.name")public class AnimalsConfig { @Bean public Brain fishBrain() { return new Brain() { public String getIdea() {return "Bobble";} }; }}
Запуск контекстаvoid main() { ApplicationContext ctx = new AnnotationConfigApplicationContext(AnimalsConfig.class);
Animal animal = ctx.getBean(Animal.class);
animal.doHunt(); // Meow, Bobble!}
Жизненный цикл контекста
Bean Lifecycle1.Расчитывается граф (DAG) зависимостей2.Инициализируются зависимости бина3.Выставляются ссылки на зависимости4.Запускаются инициализаторы5.Бин живет, контекст запущен6.Запускаются деструкторы7.Граф зависимостей уничтожается в
обратном порядке
InitializingBean и DisposableBeaninterface InitializingBean { void afterPropertiesSet() throws Exception;}
interface DisposableBean { void destroy() throws Exception;}
Пример DisposableBeanclass ClosableOne impelements Closable, DisposableBean { @Overwrite public void close() throws IOException { … }
@Overwrite public void destroy() throws Exception { close(); }}
@PostConstruct и @PreDestroyclass NamedOne implements Closable { @Autowired private String name; private String formattedName;
@PostConstruct public void init() {formattedName = format(name);}
@PreDestroy @Overwrite public void close() { … }}
Awaresinterface BeanNameAware { void setBeanName(String name) …;}
interface ResourceLoaderAware { void setResourceLoader(ResourceLoader loader) …;}
interface ApplicationContextAware { void setApplicationContext(ApplicationContext ctx) …;}
@Lazy@Lazy@Serviceclass ReallyHardService {
@PostConstruct void veryLongInitializing() { … };
void almostUselessMethod() { … };}
Рекомендуемая литература
Maven dependencies<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.0.6.RELEASE</version></dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.0.6.RELEASE</version> <scope>test</scope></dependency>
Окружение и запускПромышленное программирование
Ресурсы приложения
Как передать коэффициент в бин?class CalibratingOne { @Autowired // Any double?! double coefficient; @Autowired // Other any double?! double scale;}
@Valueclass CalibratingOne { @Value(“${property.name}”) double coefficient; @Value(“${prop.scale:1.0}”) double scale; // здесь 1.0 - дефолтное значение}
PropertiesPlaceholderConfigurer@Configuration@PropertySource(“classpath:application.properties”)class ApplicationConfiguration { @Bean public PropertiesPlaceholderConfigurer props() { return new PropertiesPlaceholderConfigurer(); }}
.properties-файлыru.fizteh.java2.example3.coefficient=5.0ru.fizteh.java2.example3.scale=0.8
# comments allowedru.fizteh.java2.mysql.port=3306ru.fizteh.java2.mysql.user=fediqru.fizteh.java2.mysql.password=Very$tr0ngPa66w*rd
System propertiesjava … \ -Dru.fizteh.app.mode=yarr \ -Dru.fizteh.app.count=133 \ … \ ru.fizteh.app.MainClass \ command line args
@Resource@Serviceclass CheapCalculator implements BillCalculator { Bill calcCost(Order order) { return new Bill(order.getCosts()); }}@Serviceclass CostyCalculator implements BillCalculator { Bill calcCost(Order order) { return new Bill(order.getCosts() * 2); }}
@Resourceclass OrderProcessor { @Autowired // which one? BillCalculator billCalculator;
public BigDecimal processOrder(Order order) { return billCalculator.calcCost(order).getPrice(); }}
@Resourceclass OrderProcessor { @Resource(name = “cheapCalculator”) BillCalculator billCalculator;
public BigDecimal processOrder(Order order) { return billCalculator.calcCost(order).getPrice(); }}
@Resource@Service // = @Service(“cheapCalculator”) // Default nameclass CheapCalculator implements BillCalculator { Bill calcCost(Order order) { return new Bill(order.getCosts()); }}@Service(“ohohoCalculator”) // Custom nameclass CostyCalculator implements BillCalculator { Bill calcCost(Order order) { return new Bill(order.getCosts() * 2); }}
class OrderProcessor { @Autowired BillCalculator billCalculator; public BigDecimal processOrder(Order order) { return billCalculator.calcCost(order).getPrice(); }}
Взятие бинов из контекстаclass Cook { @Autowired // like ApplicationContextAware ApplicationContext ctx;
public void cook() { Pan pan = ctx.getBean(Pan.class) Map<String, Food> namedFood = ctx.getBeansOfType(Food.class); Food fish = ctx.getBean(“fish”, Food.class); }}
Взятие параметров из контекстаclass Accountant{ @Autowired // like ApplicationContextAware ApplicationContext ctx;
public void report() { Environment env = ctx.getEnvironment(); String cardHolder = env.getProperty(“cardHolder”); double tax = env.getPropertyAsClass(“tax”, Double.class) }}
Взятие файлов из контекстаclass Reader { @Autowired // like ResourceLoaderAware ResourceLoader loader; // вообще-то, это тот же контекст
public void read() { Resource resource = loader.getResource(“file.txt”); URI uri = resource.getURI(); String body = IOUtils.toString( // apache commons-io resource.getInputStream()); }}
Non-required wiringclass Logger { @Autowired(required = false) Printer printer;
public void log(String s) { if (printer != null) { printer.print(s); } … }}
SLF4J + Log4J
Использование логгераimport org.slf4j.Logger;import org.slf4j.LoggerFactory;
class SomeoneActor { private static final Logger log = LoggerFactory.getLogger(SomeoneActor.class);
void doSomething(Object event) { log.warn(“Oh, god, {} happens!”, event); }}
Использование логгераvoid doSomethingWrong(String arg) { try { doSomethingBad(arg); } catch (AnyException e) { log.error(“Bad with {} happens”, arg, e) // Если последний аргумент - исключение, // то в лог будет выведен stack trace }}
Уровни логгингаtrace - “шаг левой… шаг правой…”debug - “идем прямо… все еще идем...”info - “надо идти прямо 32 км”warn - “пришлось обойти лужу”error - “потерял карту, упал в яму, промок”fatal - (в SLF4J нет) “сломал обе ноги,
прощай, жестокий мир”
Maven Dependencies<!-- SLF4J core API --!><dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.7</version></dependency>
<!-- SLF4J to Log4J bridge --!><dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.7</version></dependency>
<!-- Log4J implementation --!><dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version></dependency>
log4j.xml<log4j:configuration> <appender .../> <category .../> <root .../></log4j:configuration>
log4j.xml header<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"><log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
log4j.xml category<category name="ru.fizteh"> <priority value="ALL"/> <!-- Most important --!></category>
<category name="wire"> <priority value="NONE"/> <!-- NO U!!! --!></category>
<category name="org.springframework"> <priority value="WARN"/> <!-- Don’t worry --!></category>
log4j.xml appender<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value= "%-d{ISO8601} [%15.15t] %-5p %30.30c - %m%n"/> </layout>
</appender>
Conversion Pattern explained%d{ISO8601} - дата в формате ISO-8601%p - приоритет (уровень логгинга)%t - thread, имя потока%c - имя логгера (имя класса)%с{1} - последнее слово в имени логгера%m - логируемое сообщение%n - перевод строки
Conversion Pattern explainedprintf-like formattingДо точки - минимальное число знаковПосле точки - максимальное число знаковС минусом - слева направоБез минуса - справа налево%-10.20c = поле от 10 до 20 символов,
заполнять слева направо, имя класса
log4j.xml root<root> <!-- Прочие категории интересуют нас от INFO и выше --> <priority value="INFO"/> <!-- Льем все в console --> <appender-ref ref="console"/></root>
%-d{ISO8601} [%t] %-5p %20.20c %m%n2014-09-14 00:47:42,912 [main] INFO .java2.ServerStarter Starting web server2014-09-14 00:47:42,913 [main] DEBUG eh.java2.util.Reader Reading config.xml2014-09-14 00:47:42,913 [main] DEBUG eh.java2.util.Reader Reading pages.xml2014-09-14 00:47:42,913 [main] WARN eh.java2.util.Reader Cannot read trololo.xml2014-09-14 00:47:42,914 [main] ERROR .java2.ServerStarter Failed to open socketjava.net.BindException: Permission denied
at java.net.PlainSocketImpl.socketBind(Native Method)at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:382)at java.net.ServerSocket.bind(ServerSocket.java:375)at java.net.ServerSocket.<init>(ServerSocket.java:237)at java.net.ServerSocket.<init>(ServerSocket.java:128)at ru.fizteh.java2.ServerStarter.openSocket(ServerStarter.java:30)at ru.fizteh.java2.ServerStarter.main(ServerStarter.java:23)
Боевой запуск приложения
Что нужно сделать для запуска?Допустим, компиляция уже завершена
Собрать библиотеки зависимостей, собственные классы и файлы ресурсов
Построить из них classpathЗапустить JVM* с нужными аргументамиИногда вместо отдельной JVM можно
запустить приложение в общем контейнере
Запуск через Shell-скрипт#!/bin/sh
mvn clean packagemvn dependency:copy-dependencies
CLASSPATH=$(find target/ -name "*.jar" -printf "%f:")
java -cp $CLASSPATH \ -Dhard.coded.args=fixed.values \ -ru.fizteh.java2.MainClass "$@"
Упаковка в Web App Archive (.war)# Нужны правки в pom.xml, смотрите их в следующих серияхmvn clean compile war:war
# Копируем war-файл в Application Servercopy target/myapp.war $TOMCAT_HOME/webapps/# При должной настройке приложение запустится само# Подробнее о веб-приложениях в следующих сериях
chrome http://localhost:8080/myapp
Spring BootНабор библиотек, бесстыдно облегчающий
запуск Spring-based приложенийАвтоматически конфигурирует Spring,
manifest.mf, Application Server, etc…Тесно интегрирован с Maven и Gradle
Spring Boot Maven Plugin<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>1.1.6.RELEASE</version> <executions> <execution> <goals><goal>repackage</goal></goals> </execution> </executions></plugin>
Spring Boot в коде@Configuration@EnableAutoConfiguration // Опциональноclass AppConfig { ... public static void main(String[] args) { SpringApplication.run(AppConfig.class); }}
Запуск с помощью Spring Bootmvn clean package # если в конфиге указан goal repackagemvn clean package spring-boot:repackage # если не указан
# запуск прямо из mavenmvn spring-boot:run
# В repackaged jar упакованы зависимости и настроен main class# Его можно распространять отдельно и запускать напрямуюjava -jar target/app.jar