Перейти к содержимому

Configure java что это

  • автор:

Конфигурация контейнеров Java-кодом

Центральными артефактами в новых средствах поддержки Java-конфигурации в Spring являются классы, помеченные аннотацией @Configuration , и методы, помеченные аннотацией @Bean .

Аннотация @Bean используется для указания того, что метод создает экземпляр, конфигурирует и инициализирует новый объект, которым будет управлять IoC-контейнер Spring. Для тех, кто знаком с XML-конфигурацией из Spring, аннотация @Bean играет ту же роль, что и элемент . Вы можете использовать методы, аннотированные @Bean , с любой аннотацией @Component из Spring. Однако чаще всего они используются с бинами, аннотированными @Configuration .

Аннотирование класса с помощью @Configuration указывает на то, что его основное назначение — быть источником определений бина. Более того, классы, аннотированные @Configuration , позволяют определять межбиновые зависимости путем вызова других методов @Bean в том же классе. Простейший возможный класс, аннотированный @Configuration , выглядит следующим образом:

@Configuration public class AppConfig < @Bean public MyService myService() < return new MyServiceImpl(); >>
@Configuration class AppConfig < @Bean fun myService(): MyService < return MyServiceImpl() >>

Предшествующий класс AppConfig эквивалентен следующему XML-классу из Spring:

Полная @Configuration против «облегченного» режима @Bean?

Когда методы @Bean объявляются в классах, не аннотированных @Configuration , их называют обрабатываемыми в «облегченном» режиме. Методы бинов, объявленные в аннотации @Component или даже в обычном классе, считаются «облегченными», с другой основной целью объемлющего класса, а метод, помеченный аннотацией @Bean , является там своего рода бонусом. Например, служебные компоненты могут предоставлять контейнеру представления управления через дополнительный метод, аннотированный @Bean , для каждого класса соответствующего компонента. В таких сценариях методы, аннотированные @Bean , являются механизмом фабричных методов общего назначения.

В отличие от полной @Configuration , облеченные методы @Bean не могут объявлять межбиновые зависимости. Вместо этого они работают с внутренним состоянием содержащего их компонента и, по необходимости, с аргументами, которые они могут объявить. Поэтому такой метод, помеченный аннотацией @Bean , не должен вызывать другие методы, помеченные аннотацией @Bean . Каждый такой метод в буквальном смысле является лишь фабричным методом для конкретной ссылки на бин, без какой-либо специальной семантики во время выполнения. Положительным побочным эффектом здесь является то, что отсутствует необходимость применять подклассификацию CGLIB во время выполнения, поэтому нет никаких ограничений в плане проектирования классов (таким образом, объемлющий класс может быть final и так далее).

В обычных сценариях методы, помеченные аннотацией @Bean , должны быть объявлены в классах, помеченных аннотацией @Configuration , что обеспечит постоянное использование «полного» режима и перенаправление перекрестных ссылок на управление жизненным циклом контейнера. Это предотвращает случайный вызов одного и того же метода, помеченного аннотацией @Bean , через обычный вызов Java, что помогает уменьшить количество трудно находимых ошибок, которые трудно отследить при работе в «облегченном» режиме.

Аннотации @Bean и @Configuration подробно рассмотрены в следующих разделах. Однако для начала мы рассмотрим различные способы создания контейнера Spring с помощью конфигурации на основе Java.

Создание экземпляра контейнера Spring с помощью AnnotationConfigApplicationContext

Следующие разделы описывают AnnotationConfigApplicationContext , представленный в Spring 3.0. Эта универсальная реализация интерфейса ApplicationContext способна принимать на ввод не только классы, помеченные аннотацией @Configuration , но и обычные классы, аннотированные @Component , а также классы, аннотированные метаданными из JSR-330.

Если классы, помеченные аннотацией @Configuration , указаны в качестве входных данных, сам класс, аннотированный @Configuration , регистрируется как определение бина, а все объявленные в классе методы, помеченные аннотацией @Bean , также регистрируются как определения бина.

Если указаны классы, помеченные аннотацией @Component , или из JSR-330, они регистрируются как определения бинов, и предполагается, что метаданные внедрения зависимостей, такие как @Autowired или @Inject , используются в этих классах, где это необходимо.

Простая конструкция

Точно так же, как XML-файлы Spring используются в качестве входных данных при создании ClassPathXmlApplicationContext , вы можете использовать классы, аннотированные @Configuration , в качестве входных данных при создании AnnotationConfigApplicationContext . Это позволяет использовать контейнер Spring всецело без XML, как показано в следующем примере:

public static void main(String[] args)
import org.springframework.beans.factory.getBean fun main() < val ctx = AnnotationConfigApplicationContext(AppConfig::class.java) val myService = ctx.getBean() myService.doStuff() >

Как упоминалось ранее, AnnotationConfigApplicationContext не ограничивается работой только с классами, аннотированными @Configuration . Любой аннотированный @Component или JSR-330 класс может быть предоставлен в качестве входа в конструктор, как показано в следующем примере:

public static void main(String[] args)
import org.springframework.beans.factory.getBean fun main() < val ctx = AnnotationConfigApplicationContext(MyServiceImpl::class.java, Dependency1::class.java, Dependency2::class.java) val myService = ctx.getBean() myService.doStuff() >

В предыдущем примере предполагается, что MyServiceImpl , Dependency1 и Dependency2 используют аннотации внедрения зависимостей Spring, такие как аннотация @Autowired .

Построение контейнера программно с помощью register(Class…​)

Вы можете создать AnnotationConfigApplicationContext с помощью конструктора без аргументов, а затем сконфигурировать его с помощью метода register() . Данный подход особенно полезен при программном построении AnnotationConfigApplicationContext . В следующем примере показано, как это сделать:

public static void main(String[] args)
import org.springframework.beans.factory.getBean fun main() < val ctx = AnnotationConfigApplicationContext() ctx.register(AppConfig::class.java, OtherConfig::class.java) ctx.register(AdditionalConfig::class.java) ctx.refresh() val myService = ctx.getBean() myService.doStuff() >

Включение сканирования компонентов с помощью scan(String…)

Чтобы включить сканирование компонентов, вы можете аннотировать свой класс с помощью @Configuration следующим образом:

@Configuration @ComponentScan(basePackages = "com.acme") public class AppConfig < // . >
  1. Эта аннотация позволяет сканировать компоненты.
@Configuration @ComponentScan(basePackages = ["com.acme"]) class AppConfig < // . >
  1. Эта аннотация позволяет сканировать компоненты.

Опытные пользователи Spring могут быть знакомы с эквивалентом XML-объявления из пространства имен context: в Spring, показанным в следующем примере:

В предыдущем примере пакет com.acme сканируется на поиск любых классов, аннотированных @Component , а эти классы регистрируются как определения бина Spring в контейнере. AnnotationConfigApplicationContext открывает метод scan(String…​) для предоставления такой же функциональности сканирования компонентов, как показано в следующем примере:

public static void main(String[] args)
fun main() < val ctx = AnnotationConfigApplicationContext() ctx.scan("com.acme") ctx.refresh() val myService = ctx.getBean() >

Помните, что классы @Configuration мета-аннотированы с помощью @Component , поэтому являются кандидатами на сканирование компонентов. В предыдущем примере, если предположить, что AppConfig объявлен в пакете com.acme (или в любом другом пакете под ним), он перехватывается во время вызова scan() . После refresh() все его методы, аннотрованные @Bean , обрабатываются и регистрируются как определения бинов в контейнере.

Поддержка веб-приложений с помощью AnnotationConfigWebApplicationContext

К варианту WebApplicationContext класса AnnotationConfigApplicationContext можно получить доступ при помощи AnnotationConfigWebApplicationContext . Вы можете использовать эту реализацию при настройке слушателя сервлета ContextLoaderListener из Spring, DispatcherServlet из Spring MVC и так далее. Следующий фрагмент web.xml конфигурирует типичное веб-приложение в Spring MVC (обратите внимание на использование context-параметров contextClass и init-параметров):

   contextClass org.springframework.web.context.support.AnnotationConfigWebApplicationContext   contextConfigLocation com.acme.AppConfig   org.springframework.web.context.ContextLoaderListener   dispatcher org.springframework.web.servlet.DispatcherServlet  contextClass org.springframework.web.context.support.AnnotationConfigWebApplicationContext   contextConfigLocation com.acme.web.MvcConfig    dispatcher /app/*  

Для программных случаев использования GenericWebApplicationContext может использоваться в качестве альтернативы AnnotationConfigWebApplicationContext . Подробности см. в javadoc по GenericWebApplicationContext .

@Configuration

@Configuration – это аннотация на уровне класса, указывающая на то, что объект является источником определений бина. Классы, аннотированные @Configuration , объявляют бины через методы, аннотированные @Bean . Вызовы методов @Bean для классов @Configuration также могут быть использованы для определения межбиновых зависимостей.

Внедрение зависимостей между бинами

Если бины зависят друг от друга, выразить эту зависимость так же просто, как сделать так, чтобы один метод бина вызывал другой, как это показано в следующем примере:

@Configuration public class AppConfig < @Bean public BeanOne beanOne() < return new BeanOne(beanTwo()); >@Bean public BeanTwo beanTwo() < return new BeanTwo(); >>
@Configuration class AppConfig

В предыдущем примере beanOne получает ссылку на beanTwo через внедрение на основе конструктора.

Этот способ объявления межбиновых зависимостей работает только в том случае, если метод, помеченный аннотацией @Bean , объявлен внутри класса, аннотированного @Configuration . Нельзя объявлять межбиновые зависимости, используя обычные классы с аннотацией @Component .

Внедрение зависимости через метод поиска

Как отмечалось ранее, внедрение зависимости через метод – это продвинутая функция, которую не следует слишком часто использовать. Она полезна в случаях, если бин, находящийся в области видимости на уровне экземпляра-одиночки, имеет зависимость от бина, находящегося в области видимости на уровне прототипа. Использование Java для такого типа конфигурации обеспечивает естественные средства для реализации такого паттерна. В следующем примере показано, как использовать внедрение зависимости через метод поиска:

public abstract class CommandManager < public Object process(Object commandState) < // создаем новый экземпляр соответствующего интерфейса Command Command command = createCommand(); // устанавливаем состояние для (как ожидается, совершенно нового) экземпляра Command command.setState(commandState); return command.execute(); >// хорошо. но где реализация этого метода? protected abstract Command createCommand(); >
abstract class CommandManager < fun process(commandState: Any): Any < // создаем новый экземпляр соответствующего интерфейса Command val command = createCommand() // устанавливаем состояние для (как ожидается, совершенно нового) экземпляра Command command.setState(commandState) return command.execute() >// хорошо. но где реализация этого метода? protected abstract fun createCommand(): Command >

Используя конфигурацию Java, вы можете создать подкласс CommandManager , в котором абстрактный метод createCommand() переопределяется таким образом, что он ищет новый (прототип) объект команды. В следующем примере показано, как это сделать:

@Bean @Scope("prototype") public AsyncCommand asyncCommand() < AsyncCommand command = new AsyncCommand(); // вводим зависимости здесь по мере необходимости return command; >@Bean public CommandManager commandManager() < // возвращаем новую анонимную реализацию CommandManager с помощью createCommand() // переопределяется для возврата нового прототипа объекта Command return new CommandManager() < protected Command createCommand() < return asyncCommand(); >> >
@Bean @Scope("prototype") fun asyncCommand(): AsyncCommand < val command = AsyncCommand() // вводим зависимости здесь по мере необходимости return command >@Bean fun commandManager(): CommandManager < // возвращаем новую анонимную реализацию CommandManager с помощью createCommand() // переопределяется для возврата нового прототипа объекта Command return object : CommandManager() < override fun createCommand(): Command < return asyncCommand() >> >

Дополнительная информация о внутренней работе конфигурации на основе Java

Рассмотрим следующий пример, в котором метод, помеченный аннотацией @Bean , вызывается дважды:

@Configuration public class AppConfig < @Bean public ClientService clientService1() < ClientServiceImpl clientService = new ClientServiceImpl(); clientService.setClientDao(clientDao()); return clientService; >@Bean public ClientService clientService2() < ClientServiceImpl clientService = new ClientServiceImpl(); clientService.setClientDao(clientDao()); return clientService; >@Bean public ClientDao clientDao() < return new ClientDaoImpl(); >>
@Configuration class AppConfig < @Bean fun clientService1(): ClientService < return ClientServiceImpl().apply < clientDao = clientDao() >> @Bean fun clientService2(): ClientService < return ClientServiceImpl().apply < clientDao = clientDao() >> @Bean fun clientDao(): ClientDao < return ClientDaoImpl() >>

clientDao() был вызван один раз в clientService1() и один раз в clientService2() . Поскольку этот метод создает новый экземпляр ClientDaoImpl и возвращает его, обычно ожидается, что получится два экземпляра (по одному для каждой службы). Это определенно было создало проблемы: В Spring созданные бины по умолчанию имеют область видимости singleton. Вот здесь-то и свершается магия: Все классы, аннотированные @Configuration, подклассифицируются при запуске с помощью CGLIB. В подклассе дочерний метод сначала проверяет контейнер на наличие кэшированных (входящих в область видимости) бинов, прежде чем вызвать родительский метод и создать новый экземпляр.

Логика работы может различаться в зависимости от области видимости вашего бина. В данном случае речь идёт об объектах-одиночках.

Начиная со Spring 3.2, отпала необходимость добавлять CGLIB в ваш classpath, поскольку классы CGLIB были перепакованы в org.springframework.cglib и включены непосредственно в модуль spring-core JAR.

Существует несколько ограничений, связанных с тем, что CGLIB динамически добавляет функции во время запуска. В частности, конфигурационные классы не должны быть конечными. Однако, начиная с версии 4.3, для конфигурационных классов разрешены любые конструкторы, включая использование аннотации @Autowired или единственное объявление конструктора не по умолчанию для внедрения по умолчанию.

Если вы предпочитаете избежать каких-либо ограничений, накладываемых CGLIB, рассмотрите возможность объявления методов, помеченных аннотацией @Bean , для классов, неаннотированных @Configuration (например, для обычных классов, аннотированных @Component ). Перекрестные вызовы между методами, аннотированными @Bean , в этом случае не перехватываются, поэтому придется полагаться исключительно на внедрение зависимостей на уровне конструктора или метода.

Составление конфигураций на основе Java

Функция конфигурирования Spring на основе Java позволяет составлять аннотации, что может облегчить конфигурацию.

Использование аннотации @Import

Подобно элементу , используемому в XML-файлах Spring, аннотация @Import позволяет загружать определения, помеченные аннотацией @Bean , из другого класса конфигурации для облегчения модульной организации конфигураций, как показано в следующем примере:

@Configuration public class ConfigA < @Bean public A a() < return new A(); >> @Configuration @Import(ConfigA.class) public class ConfigB < @Bean public B b() < return new B(); >>
@Configuration class ConfigA < @Bean fun a() = A() >@Configuration @Import(ConfigA::class) class ConfigB

Теперь, вместо того чтобы указывать ConfigA.class и ConfigB.class при создании экземпляра контекста, необходимо явно указывать только ConfigB , как показано в следующем примере:

public static void main(String[] args) < ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class); // теперь оба бина A и B будут доступны. A a = ctx.getBean(A.class); B b = ctx.getBean(B.class); >
import org.springframework.beans.factory.getBean fun main() < val ctx = AnnotationConfigApplicationContext(ConfigB::class.java) // теперь оба бина A и B будут доступны. val a = ctx.getBean() val b = ctx.getBean() >

Такой подход упрощает создание экземпляра контейнера, поскольку приходится работать только с одним классом, а не запоминать потенциально большое количество классов @Configuration во время построения.

Начиная со Spring Framework 4.2, аннотация @Import также поддерживает ссылки на обычные классы компонентов, аналогично методу AnnotationConfigApplicationContext.register . Это особенно полезно, если нужно избежать сканирования компонентов, используя несколько классов конфигурации в качестве точек входа для явного определения всех ваших компонентов.

Внедрение зависимостей для импортированных определений, аннотированных @Bean

Предыдущий пример рабочий, но является упрощением. В большинстве практических сценариев бины имеют зависимости друг от друга в разных конфигурационных классах. При использовании XML это не проблема, так как не задействован компилятор, и вы можете объявлять ref=»someBean» , доверив Spring решать эту проблему во время инициализации контейнера. При использовании классов, помеченных аннотацией @Configuration , компилятор Java накладывает ограничения на конфигурационную модель, заключающиеся в том, что ссылки на другие бины должны иметь допустимый языком Java синтаксис.

К счастью, решить эту проблему просто. Метод, аннотированный @Bean , может иметь произвольное количество параметров, которые описывают зависимости бина. Рассмотрим следующий более реальный сценарий с несколькими классами, помеченными аннотацией @Configuration , каждый из которых зависит от бинов, объявленных в других:

@Configuration public class ServiceConfig < @Bean public TransferService transferService(AccountRepository accountRepository) < return new TransferServiceImpl(accountRepository); >> @Configuration public class RepositoryConfig < @Bean public AccountRepository accountRepository(DataSource dataSource) < return new JdbcAccountRepository(dataSource); >> @Configuration @Import() public class SystemTestConfig < @Bean public DataSource dataSource() < // возвращаем новый DataSource >> public static void main(String[] args) < ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class); // все связывается по конфигурационным классам. TransferService transferService = ctx.getBean(TransferService.class); transferService.transfer(100.00, "A123", "C456"); >
import org.springframework.beans.factory.getBean @Configuration class ServiceConfig < @Bean fun transferService(accountRepository: AccountRepository): TransferService < return TransferServiceImpl(accountRepository) >> @Configuration class RepositoryConfig < @Bean fun accountRepository(dataSource: DataSource): AccountRepository < return JdbcAccountRepository(dataSource) >> @Configuration @Import(ServiceConfig::class, RepositoryConfig::class) class SystemTestConfig < @Bean fun dataSource(): DataSource < // возвращаем новый DataSource >> fun main() < val ctx = AnnotationConfigApplicationContext(SystemTestConfig::class.java) // все связывается по конфигурационным классам. val transferService = ctx.getBean() transferService.transfer(100.00, "A123", "C456") >

Есть и другой способ получить тот же результат. Помните, что классы, аннотированные @Configuration , в конечном итоге являются лишь еще одним бином в контейнере: Это означает, что они могут использовать преимущества внедрения @Autowired и @Value и другие возможности так же, как и любой другой бин.

Убедитесь, что зависимости, которые вы внедряете таким способом, принадлежат исключительно к самому простому типу. Классы, аннотированные @Configuration , обрабатываются на довольно раннем этапе во время инициализации контекста, и принудительное внедрение зависимости таким способом может привести к непредвиденной ранней инициализации. По возможности используйте внедрение на основе параметров, как в предыдущем примере.

Кроме того, будьте особенно осторожны с определениями BeanPostProcessor и BeanFactoryPostProcessor через @Bean . Обычно их следует объявлять как static методы, аннотированные @Bean , не вызывающие создание экземпляра содержащего их конфигурационного класса. В противном случае аннотации @Autowired и @Value могут не сработать для самого конфигурационного класса, поскольку его можно создать как экземпляр бина раньше, чем AutowiredAnnotationBeanPostProcessor .

В следующем примере показано, как один бин может быть автоматически обнаружен и связан с другим бином:

@Configuration public class ServiceConfig < @Autowired private AccountRepository accountRepository; @Bean public TransferService transferService() < return new TransferServiceImpl(accountRepository); >> @Configuration public class RepositoryConfig < private final DataSource dataSource; public RepositoryConfig(DataSource dataSource) < this.dataSource = dataSource; >@Bean public AccountRepository accountRepository() < return new JdbcAccountRepository(dataSource); >> @Configuration @Import() public class SystemTestConfig < @Bean public DataSource dataSource() < // возвращаем новый DataSource >> public static void main(String[] args) < ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class); // все связывается по конфигурационным классам. TransferService transferService = ctx.getBean(TransferService.class); transferService.transfer(100.00, "A123", "C456"); >
import org.springframework.beans.factory.getBean @Configuration class ServiceConfig < @Autowired lateinit var accountRepository: AccountRepository @Bean fun transferService(): TransferService < return TransferServiceImpl(accountRepository) >> @Configuration class RepositoryConfig(private val dataSource: DataSource) < @Bean fun accountRepository(): AccountRepository < return JdbcAccountRepository(dataSource) >> @Configuration @Import(ServiceConfig::class, RepositoryConfig::class) class SystemTestConfig < @Bean fun dataSource(): DataSource < // возвращаем новый DataSource >> fun main() < val ctx = AnnotationConfigApplicationContext(SystemTestConfig::class.java) // все связывается по конфигурационным классам. val transferService = ctx.getBean() transferService.transfer(100.00, "A123", "C456") >

Внедрение на основе конструктора в классах, помеченных аннотацией @Configuration , поддерживается только начиная со Spring Framework 4.3. Обратите внимание, что нет необходимости указывать @Autowired , если целевой бин определяет только один конструктор.

Полностью уточненные импортированные бины для удобства навигации

В предыдущем сценарии использование аннотации @Autowired работает отлично и обеспечивает желаемую модульность, но определение того, где именно объявляются определения автоматически обнаруженных и связанных бинов, остается несколько неоднозначным. Например, если разработчик смотрит на ServiceConfig , как узнать, где именно объявлен бин @Autowired AccountRepository ? В коде это не указано явно, и это может быть вполне нормальным явлением. Помните, что Spring Tools for Eclipse предоставляет инструментарий, который может отображать графы, показывающие, каким образом все связано, и это может быть достаточно. Кроме того, ваша интегрированная среда разработки Java может легко осуществлять поиск всех объявлений и использований типа AccountRepository и быстро отобразить вам расположение методов, помеченных аннотацией @Bean , которые возвращают этот тип.

В случаях, если такая двусмысленность неприемлема и вам нужна прямая навигация из вашей IDE от одного класса, аннотированного @Configuration , к другому, рассмотрите возможность автоматического обнаружения и связывания самих классов конфигурации. В следующем примере показано, как это сделать:

@Configuration public class ServiceConfig < @Autowired private RepositoryConfig repositoryConfig; @Bean public TransferService transferService() < // выполняем навигацию "через" конфигурационный класс к методу, аннотированному @Bean! return new TransferServiceImpl(repositoryConfig.accountRepository()); >>
@Configuration class ServiceConfig < @Autowired private lateinit var repositoryConfig: RepositoryConfig @Bean fun transferService(): TransferService < // выполняем навигацию "через" конфигурационный класс к методу, аннотированному @Bean! return TransferServiceImpl(repositoryConfig.accountRepository()) >>

В предыдущей ситуации определение AccountRepository является полностью явным. Однако ServiceConfig теперь тесно связан с RepositoryConfig . Таков компромисс. Эта тесная связь может быть несколько ослаблена за счет использования классов с аннотацией @Configuration , основанных на интерфейсах или абстрактных классах. Рассмотрим следующий пример:

@Configuration public class ServiceConfig < @Autowired private RepositoryConfig repositoryConfig; @Bean public TransferService transferService() < return new TransferServiceImpl(repositoryConfig.accountRepository()); >> @Configuration public interface RepositoryConfig < @Bean AccountRepository accountRepository(); >@Configuration public class DefaultRepositoryConfig implements RepositoryConfig < @Bean public AccountRepository accountRepository() < return new JdbcAccountRepository(. ); >> @Configuration @Import() // импортируем конкретную конфигурацию! public class SystemTestConfig < @Bean public DataSource dataSource() < // возвращаем DataSource >> public static void main(String[] args)
import org.springframework.beans.factory.getBean @Configuration class ServiceConfig < @Autowired private lateinit var repositoryConfig: RepositoryConfig @Bean fun transferService(): TransferService < return TransferServiceImpl(repositoryConfig.accountRepository()) >> @Configuration interface RepositoryConfig < @Bean fun accountRepository(): AccountRepository >@Configuration class DefaultRepositoryConfig : RepositoryConfig < @Bean fun accountRepository(): AccountRepository < return JdbcAccountRepository(. ) >> @Configuration @Import(ServiceConfig::class, DefaultRepositoryConfig::class) // импортируем конкретную конфигурацию! class SystemTestConfig < @Bean fun dataSource(): DataSource < // возвращаем DataSource >> fun main() < val ctx = AnnotationConfigApplicationContext(SystemTestConfig::class.java) val transferService = ctx.getBean() transferService.transfer(100.00, "A123", "C456") >

Теперь ServiceConfig слабо связан с конкретным DefaultRepositoryConfig , а встроенные инструменты IDE по-прежнему полезны: Вы можете легко получить иерархию типов реализаций RepositoryConfig . Таким образом, навигация по классам, помеченным аннотацией @Configuration , и их зависимостям ничем не отличается от обычного процесса навигации по коду, основанному на интерфейсе.

Если вы хотите повлиять на порядок создания определенных бинов при запуске, объявите некоторые из них как @Lazy (для создания при первом доступе, а не при запуске) или как @DependsOn других определенных бинов (чтобы другие определенные бины создавались перед текущим бином, помимо тех действий, которые подразумеваются прямыми зависимостями последнего).

Условное включение классов @Configuration или методов @Bean

Часто бывает полезно условно активировать или дезактивировать весь класс, аннотированный @Configuration , или даже отдельные методы, аннотированные @Bean , основываясь на некотором произвольном состоянии системы. Одним из распространенных примеров этого подхода является использование аннотации @Profile для активации бинов только в том случае, если определенный профиль был включен в Environment Spring.

Аннотация @Profile фактически реализуема с помощью гораздо более гибкой аннотации под названием @Conditional . Аннотация @Conditional указывает на конкретные реализации org.springframework.context.annotation.Condition , с которыми следует ознакомиться до регистрации @Bean .

Реализации интерфейса Condition обеспечивают matches(….) метод, который возвращает true или false . Например, в следующем листинге приведена фактическая реализация Condition , используемая для аннотации @Profile :

@Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) < // Считываем атрибуты аннотации @Profile MultiValueMapattrs = metadata.getAllAnnotationAttributes(Profile.class.getName()); if (attrs != null) < for (Object value : attrs.get("value")) < if (context.getEnvironment().acceptsProfiles(((String[]) value))) < return true; >> return false; > return true; >
override fun matches(context: ConditionContext, metadata: AnnotatedTypeMetadata): Boolean < // Считываем атрибуты аннотации @Profile val attrs = metadata.getAllAnnotationAttributes(Profile::class.java.name) if (attrs != null) < for (value in attrs["value"]!!) < if (context.environment.acceptsProfiles(Profiles.of(*value as Array))) < return true >> return false > return true >

Более подробную информацию см. в javadoc по аннотации @Conditional .

Объединение Java и XML-конфигурации

Поддержка класса, помеченного аннотацией @Configuration в Spring, не стремится быть 100% полной заменой Spring XML. Некоторые средства, такие как пространства имен в Spring XML, остаются идеальным способом конфигурирования контейнера. В случаях, если XML является удобным или необходимым инструментом, вам дает выбор: либо создавать экземпляр контейнера «XML-ориентированным» способом, используя, например, ClassPathXmlApplicationContext , либо создать его экземпляр «Java-ориентированным» способом, используя AnnotationConfigApplicationContext и аннотацию @ImportResource для импорта XML по мере необходимости.

XML-ориентированное использование классов c аннотацией @Configuration

Более предпочтительным вариантом может быть начальная загрузка контейнера Spring из XML и включение в него классов, аннотированных @Configuration , в индивидуальном порядке. Например, в случае существующей обширной кодовой базы, использующей Spring XML, проще создавать классы с аннотацией @Configuration по мере необходимости и осуществлять их включение из существующих XML-файлов. Позже в этом разделе мы рассмотрим варианты использования классов, помеченных аннотацией @Configuration , в подобном «XML-ориентированном» случае.

Объявление классов @Configuration как обычных элементов в Spring

Помните, что классы с аннотацией @Configuration в конечном итоге являются определениями бинов в контейнере. В этой серии примеров мы создадим класс, аннотированный @Configuration , с именем AppConfig и включим его в файл system-test-config.xml в качестве определения . Поскольку был включен, контейнер распознает аннотацию @Configuration и надлежащим образом обрабатывает методы, помеченные аннотацией @Bean и объявленные в AppConfig .

В следующем примере показан обычный класс конфигурации на языке Java:

@Configuration public class AppConfig < @Autowired private DataSource dataSource; @Bean public AccountRepository accountRepository() < return new JdbcAccountRepository(dataSource); >@Bean public TransferService transferService() < return new TransferService(accountRepository()); >>
@Configuration class AppConfig < @Autowired private lateinit var dataSource: DataSource @Bean fun accountRepository(): AccountRepository < return JdbcAccountRepository(dataSource) >@Bean fun transferService() = TransferService(accountRepository()) >

В следующем примере показана часть образца файла system-test-config.xml :

В следующем примере показан возможный файл jdbc.properties :

jdbc.url=jdbc:hsqldb:hsql://localhost/xdb jdbc.username=sa jdbc.password=
public static void main(String[] args) < ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml"); TransferService transferService = ctx.getBean(TransferService.class); // . >
fun main() < val ctx = ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml") val transferService = ctx.getBean() // . >

В файле system-test-config.xml класс AppConfig не объявляет элемент id . Хотя это был бы приемлемый исход, но он излишний, учитывая, что ни один другой бин ни в какой момент не ссылается на него, и он вряд ли будет явно получен из контейнера по имени. Аналогичным образом бин DataSource автоматически обнаруживается и связывается только по типу, поэтому явный id бина не является строго обязательным.

Использование для перехвата классов, аннотированных @Configuration

Поскольку @Configuration мета-аннотируется с помощью аннотации @Component , классы, помеченные аннотацией @Configuration , автоматически становятся кандидатами на сканирование компонентов. Используя тот же сценарий, что описан в предыдущем примере, мы можем переопределить system-test-config.xml , чтобы воспользоваться преимуществами сканирования компонентов. Обратите внимание, что в этом случае нам не нужно явно объявлять , потому что обеспечивает ту же функциональность.

В следующем примере показан измененный файл system-test-config.xml :

Использование XML с аннотацией @ImportResource , ориентированное на класс, аннотированный @Configuration

В приложениях, где классы, аннотированные @Configuration , являются основным механизмом для конфигурирования контейнера, все же, вероятно, приходится использовать XML хотя бы в некоторой степени. В таких сценариях можно использовать аннотацию @ImportResource и определить только тот объем XML, который необходим. Таким образом получаем «Java-ориентированный» подход к конфигурированию контейнера, а использование XML сводится к минимуму. Следующий пример (который предусматривает конфигурационный класс, XML-файл, определяющий бин, файл свойств, а также main класс) демонстрирует, как использовать аннотацию @ImportResource для получения «Java-ориентированной» конфигурации, в которой XML используется по мере необходимости:

@Configuration @ImportResource("classpath:/com/acme/properties-config.xml") public class AppConfig < @Value("$") private String url; @Value("$") private String username; @Value("$") private String password; @Bean public DataSource dataSource() < return new DriverManagerDataSource(url, username, password); >>
@Configuration @ImportResource("classpath:/com/acme/properties-config.xml") class AppConfig < @Value("\$") private lateinit var url: String @Value("\$") private lateinit var username: String @Value("\$") private lateinit var password: String @Bean fun dataSource(): DataSource < return DriverManagerDataSource(url, username, password) >>
properties-config.xml  
jdbc.properties jdbc.url=jdbc:hsqldb:hsql://localhost/xdb jdbc.username=sa jdbc.password=
public static void main(String[] args) < ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); TransferService transferService = ctx.getBean(TransferService.class); // . >
import org.springframework.beans.factory.getBean fun main() < val ctx = AnnotationConfigApplicationContext(AppConfig::class.java) val transferService = ctx.getBean() // . >

5 Java gateway

Zabbix 2.0 добавлена нативная поддержка для мониторинга JMX приложений введением нового демона Zabbix, называемого «Zabbix Java gateway». Zabbix Java gateway — это демон написанный на языке Java. Когда Zabbix сервер хочет знать значение конкретного JMX счетчика у узла сети, он опрашивает Zabbix Java gateway, который использует API управления JMX для опроса интересующего удаленного приложения. Приложению не требуется никаких дополнительных программ, оно просто должно быть запущено с опцией командной строки -Dcom.sun.management.jmxremote .

Java gateway принимает входящие подключения от Zabbix сервера или прокси и может быть использован только как «пассивный прокси». Но в отличии от Zabbix прокси, Java gateway может использоваться с Zabbix прокси (Zabbix прокси не могут быть связаны). Доступ к каждому Java gateway настраивается непосредственно в файле конфигурации Zabbix сервера или прокси, таким образом только один Java gateway может быть настроен на каждый из Zabbix сервер или Zabbix прокси. Если у узла сети есть элементы данных типа JMX агент и элементы данных других типов, то только элементы данных JMX агент будут переданы в Java gateway.

Когда элемент данных должен быть обновлен через Java gateway, Zabbix сервер или прокси подключается к Java gateway и запрашивает значение, которое в свою очередь получает Java gateway и возвращает серверу или прокси. Таким образом, Java gateway никакие значения не кэширует.

У Zabbix сервера и прокси есть специальный тип процессов, который подключается к Java gateway, этот процесс настраивается опцией StartJavaPollers. Внутренне, Java gateway запускается несколькими потоками, настраиваемыми опцией START_POLLERS. На стороне сервера, если соединение занимает более чем Timeout секунд, оно будет завершено, но Java gateway может еще получать значение с JMX счетчика. Для решения данной проблемы, с версии Zabbix 2.0.15 есть опция TIMEOUT в Java gateway которая позволяет установить таймаут для сетевых JMX операции.

Zabbix сервер или прокси будет пытаться объединить запросы к одной цели JMX в одно целое, как можно больше (затрагивает интервалы элементов данных), и затем отправить их в Java Gateway за одно подключение для лучшей производительности.

Предлагается выставить значение StartJavaPollers меньшим или равным чем START_POLLERS, в противном случае могут возникнуть ситуации, когда для входящих запросов может нехватить доступных потоков в Java gateway.

Разделы ниже рассказывают о том как получить и запустить Zabbix Java gateway, как настроить Zabbix сервер (или Zabbix прокси) для использования Zabbix Java gateway в мониторинге JMX, и как настроить элементы данных Zabbix в Zabbix GUI, которые соответствуют конкретным JMX счетчикам.

5.1 Получение Java gateway

Имеется два способа получения Java gateway. Первый — это загрузка пакета Java gateway с веб сайта Zabbix и, второй — компиляция Java gateway из исходных кодов.

5.1.1 Загрузка с веб-сайта Zabbix

Пакеты Zabbix Java gateway (RHEL, Debian, Ubuntu) доступны для загрузки по адресу http://www.zabbix.com/download.php.

5.1.2 Сборка исходных кодов

Для того, чтобы скомпилировать Java gateway, для начала выполните скрипт ./configure с опцией —enable-java . Желательно указать опцию —prefix для запроса пути установки отличную от умолчания /usr/local, потому что при установке Java gateway будет создано целое дерево папок, а не только один исполняемый файл.

 $ ./configure --enable-java --prefix=$PREFIX

Для компиляции и сборки Java gateway в JAR файл, выполните make . Обратите внимание, что для этого шага вам понадобятся исполняемые файлы javac и jar in your path.

 $ make

Теперь у вас имеется файл zabbix-java-gateway-$VERSION.jar в src/zabbix_java/bin. Если для вас наиболее удобен запуск Java gateway из src/zabbix_java из каталога пакета, то вы можете перейти к инструкциям по настройке и запуску Java gateway. Иначе убедитесь в наличии достаточных привилгий для выполнения make install .

 $ make install
5.2 Обзор файлов из поставки Java gateway

Независимо от того как вы получили Java gateway, вы должны закончить набором скриптов, JAR файлом и файлами конфигурации из $PREFIX/sbin/zabbix_java. Задача этих файлов изложена ниже.

 bin/zabbix-java-gateway-$VERSION.jar

Содержимое JAR файла Java gateway.

 lib/logback-core-0.9.27.jar lib/logback-classic-0.9.27.jar lib/slf4j-api-1.6.1.jar lib/org-json-2010-12-28.jar

Зависимости Java gateway: Logback, SLF4J, и библиотека JSON.org.

 lib/logback.xml  lib/logback-console.xml

Файлы конфигурации для Logback.

 shutdown.sh  startup.sh

Удобные скрипты для запуска и остановки Java gateway.

 settings.sh

Файл конфигурации, который был взят из папки со скриптами запуска и остановки.

5.3 Настройка и запуск Java gateway

По умолчанию, Java gateway слушает на порту 10052. Если вы планируете запускать Java gateway на другом порту, то вы можете указать его в скрипте settings.sh. Смотрите описание файла конфигурации Java gateway для получения сведений о том как указать эту и другие опции.

Как только вы освоитесь с настройками, вы можете запустить Java gateway выполнив скрипт запуска:

 $ ./startup.sh

Точно так же, если вам более не требуется Java gateway, выполните скрипт завершения работы для остановки Java gateway:

 $ ./shutdown.sh

Обратите внимание, что в отличии от сервера и прокси, Java gateway легок и не требует наличия базы данных.

5.4 Настройка сервера для использования с Java gateway

Теперь, когда Java gateway запущен, вы должны сказать Zabbix серверу где искать Zabbix Java gateway. Это можно сделать указав параметры JavaGateway и JavaGatewayPort в файле конфигурации сервера. Если же узел сети на котором работает JMX приложение наблюдается через Zabbix прокси, то укажите параметры соединения в файле конфигурации прокси.

 JavaGateway=192.168.3.14 JavaGatewayPort=10052

По умолчанию, сервер на запускает процессов связанных с мониторингом JMX. Однако, если вы хотите использовать этот тип мониторинга, то вам нужно указать количество форков пуллеров Java. Вы можете это сделать таким же способом как и изменение количества пуллеров и трапперов.

 StartJavaPollers=5

Не забудьте перезапустить сервер или прокси после того как закончите их настройку.

5.5 Отладка Java gateway

В случае возникновения каких-либо проблем с Java gateway или при сообщении об ошибке, которое вы видите у элемента данных в веб интерфейсе не является в достаточной мере информативной, то вы, возможно, пожелаете посмотреть файл журнала Java gateway.

По умолчанию, файлы журналов Java gateway хранятся в файле /tmp/zabbix_java.log с уровнем журналирования «info». Бывает, что этой информации недостаточно и существует потребность в информации с уровнем журналирования «debug». Чтобы увеличить уровень журналирования, откройте файл lib/logback.xml и измените уровень тэга аттрибута на «debug»:

 root level="debug"> appender-ref ref="FILE" /> /root>

Обратите внимание, что в отличии от Zabbix сервера или Zabbix прокси, вам не нужно перезапускать Zabbix Java gateway после изменения файла logback.xml — изменения в logback.xml будут применены автоматически. Когда вы завершите отладку, вы можете вернуть обратно уровень журналирования в «info».

Если вы хотите записывать журнал в другой файл или в совершенно другую среду такую как база данных, настройте файл logback.xml для удволетворения ваших потребностей. Смотрите Руководство по Logback для получения более подробных сведений.

Иногда для отладки полезно запустить Java gateway как консольное приложение, а не как демона. Чтобы это сделать, закомментируйте переменную PID_FILE в settings.sh. Если PID_FILE не указан, скрипт startup.sh запускает Java gateway как консольное приложение, что дает возможность Logback использовать файл lib/logback-console.xml, который не только выводит журнал в консоль, но и имеет уровень журналирования «debug».

В заключение, отметим, поскольку Java gateway использует SLF4J для журналирования, вы можете заменить Logback выбранным вами фреймворком, поместим соответствующий JAR файл в папку lib. Смотрите Руководство по SLF4J для получения более подробных сведений.

Настройка приложения Java для Службы приложений Azure

Служба приложений Azure позволяет разработчикам быстро создавать, развертывать и масштабировать веб-приложения на основе пакетов Java SE, Tomcat и JBoss EAP в полностью управляемой службе. Возможно развертывание приложений с подключаемыми модулями Maven из командной строки или в редакторах, например Visual Studio Code, Eclipse или IntelliJ.

Это руководство содержит основные понятия и инструкции для разработчиков для Java, использующих Службу приложений Azure. Если вы раньше не использовали Службу приложений Azure, мы рекомендуем сначала ознакомиться с кратким руководством по Java. Ответы на общие вопросы об использовании службы приложений, не относящиеся к разработке для Java, можно найти в разделе вопросов и ответов о Службе приложений Azure.

Отображение версии Java

Чтобы отобразить сведения о текущей версии Java, выполните в Cloud Shell следующую команду.

az webapp config show --name --resource-group --query "[javaVersion, javaContainer, javaContainerVersion]" 

Чтобы отобразить сведения обо всех поддерживаемых версиях Java, выполните в Cloud Shell следующую команду.

az webapp list-runtimes --os windows | grep java 

Чтобы отобразить сведения о текущей версии Java, выполните в Cloud Shell следующую команду.

az webapp config show --resource-group --name --query linuxFxVersion 

Чтобы отобразить сведения обо всех поддерживаемых версиях Java, выполните в Cloud Shell следующую команду.

az webapp list-runtimes --os linux | grep "JAVA\|TOMCAT\|JBOSSEAP" 

Дополнительные сведения о поддержке версий см. в Служба приложений политике поддержки среды выполнения языка.

Развертывание приложения

Build Tools

Maven

Подключаемый модуль Maven для веб-приложений Azure позволяет легко подготовить проект Maven на Java для веб-приложения Azure с помощью одной команды в корневом каталоге проекта:

mvn com.microsoft.azure:azure-webapp-maven-plugin:2.11.0:config 

Эта команда добавляет подключаемый azure-webapp-maven-plugin модуль и связанную конфигурацию, запрашивая выбрать существующее веб-приложение Azure или создать новую. После этого вы можете развернуть приложение Java в Azure, используя приведенную ниже команду.

mvn package azure-webapp:deploy 

Ниже приведен пример конфигурации в pom.xml :

 com.microsoft.azure azure-webapp-maven-plugin 2.11.0 111111-11111-11111-1111111 spring-boot-xxxxxxxxxx-rg spring-boot-xxxxxxxxxx B2 westus Linux Java SE Java 11    jar $/target *.jar       
Gradle
  1. Настройте подключаемый модуль Gradle для Azure веб-приложения, добавив подключаемый модуль в ваш build.gradle :
plugins
azurewebapp < subscription = '' resourceGroup = '' appName = '' pricingTier = '' region = '' runtime < os = 'Linux' webContainer = 'Tomcat 9.0' // or 'Java SE' if you want to run an executable jar javaVersion = 'Java 8' >appSettings < = > auth < type = 'azure_cli' // support azure_cli, oauth2, device_code and service_principal >> 
gradle azureWebAppDeploy 

Интерфейсы IDE

Azure поддерживает удобные возможности для разработки Java-приложений в Службе приложений в популярных интегрированных средах разработки Java, включая:

  • VS Code: веб-приложения Java с Visual Studio Code
  • IntelliJ IDEA:создание веб-приложения Hello World для Службы приложений Azure с помощью IntelliJ
  • Eclipse:создание веб-приложения Hello World для Службы приложений Azure с помощью Eclipse

API Kudu

Java SE

Чтобы развернуть файлы JAR в Java SE, используйте конечную точку /api/publish/ сайта Kudu. Дополнительные сведения об этом API см. в этой документации.

Чтобы Служба приложений Azure могла идентифицировать и запускать ваше приложение JAR, ему необходимо назначить имя app.jar . Подключаемый модуль Maven (упомянутый выше) будет автоматически переименовывать приложение во время развертывания. Если вы не хотите переименовать JAR-файл в app.jar, вы можете отправить скрипт оболочки с помощью команды для запуска jar-приложения. Вставьте абсолютный путь в этот скрипт в текстовом поле Файл запуска в разделе конфигурации на портале. Скрипт запуска выполняется не в том каталоге, в который он помещен. Поэтому всегда используйте абсолютные пути для создания ссылок на файлы в скрипте запуска (например, java -jar /home/myapp/myapp.jar ).

Tomcat

Чтобы развернуть файлы WAR в Tomcat, используйте конечную точку /api/wardeploy/ для публикации файла архива. Дополнительные сведения об этом API см. в этой документации.

JBoss EAP

Чтобы развернуть файлы WAR в JBoss, используйте конечную точку /api/wardeploy/ для публикации файла архива. Дополнительные сведения об этом API см. в этой документации.

Чтобы развернуть файлы EAR, используйте протокол FTP. Приложение EAR будет развернуто в корне контекста, определенном в конфигурации приложения. Например, если корень контекста приложения — myapp , вы можете найти сайт по пути /myapp : http://my-app-name.azurewebsites.net/myapp . Если вы хотите, чтобы веб-приложение обслуживалось в корневом пути, убедитесь, что приложение устанавливает корневой каталог контекста в корневой путь: / Дополнительные сведения см. в разделе Установка корня контекста веб-приложения.

Не развертывайте файл .war или JAR с помощью FTP. Средство FTP предназначено для передачи сценариев запуска, зависимостей или других файлов среды выполнения. Это не оптимальный выбор для развертывания веб-приложений.

Ведение журнала и отладка приложений

Отчеты о производительности, визуализация трафика и проверка работоспособности доступны на портале Azure для каждого приложения. Дополнительные сведения см. в статье Обзор диагностики Службы приложений Azure.

Потоковая передача журналов диагностики

Чтобы получить доступ к журналам консоли, созданным в коде приложения в Службе приложений, включите ведение журнала диагностики, выполнив следующую команду в Cloud Shell:

az webapp log config --resource-group --name --docker-container-logging filesystem --level Verbose 

Возможные значения для —level : Error , Warning , Info и Verbose . Каждый последующий уровень включает предыдущий уровень. Например: Error включает только сообщения об ошибках, а Verbose включает все сообщения.

Включив ведение журнала диагностики, выполните следующую команду, чтобы просмотреть поток данных журнала:

az webapp log tail --resource-group --name

Если журналы консоли не отображаются, проверьте еще раз через 30 секунд.

Вы также можете проверить файлы журнала в браузере на странице https://.scm.azurewebsites.net/api/logs/docker .

Чтобы остановить потоковую передачу журналов, нажмите клавиши Ctrl + C .

Можно получить доступ к журналам консоли, которые были созданы в контейнере.

Сначала включите ведение журнала контейнера, выполнив следующую команду:

az webapp log config --name --resource-group --docker-container-logging filesystem 

Замените и именами, подходящими для вашего веб-приложения.

После включения ведения журнала контейнера, выполните следующую команду, чтобы просмотреть поток данных журнала.

az webapp log tail --name --resource-group

Если журналы консоли не отображаются, проверьте еще раз через 30 секунд.

Чтобы остановить потоковую передачу журналов, нажмите клавиши CTRL+C.

Вы также можете проверить файлы журнала в браузере на странице https://.scm.azurewebsites.net/api/logs/docker .

Доступ к консоли SSH

Чтобы открыть прямой сеанс SSH с контейнером, необходимо запустить приложение.

Вставьте следующий URL-адрес в браузер и замените именем вашего приложения:

https://.scm.azurewebsites.net/webssh/host 

Если вы не прошли аутентификацию, это потребуется сделать, подключившись с помощью подписки Azure. После выполнения проверки подлинности отобразится оболочка в браузере. Здесь можно запускать команды внутри контейнера.

SSH connection

Любые изменения, внесенные не в каталоге /home, сохраняются в самом контейнере и не применяются до перезапуска приложения.

Чтобы открыть удаленный сеанс SSH на локальном компьютере см. инструкцию в разделе Открытие сеанса SSH из удаленной оболочки.

Средства диагностики

Встроенные образы Java основаны на операционной системе Alpine Linux. Используйте диспетчер пакетов apk , чтобы установить любые средства или команды для устранения неполадок.

Профилировщик Java

Все среды выполнения Java в службе приложение Azure входят в JDK Flight Recorder для профилирования рабочих нагрузок Java. Это можно использовать для записи событий JVM, системы и приложений и устранения неполадок в приложениях.

Дополнительные сведения о профилировщике Java см. в документации по приложение Azure Аналитика.

Ведение журнала приложений

Включите ведение журнала приложений с помощью портала Azure или Azure CLI, чтобы настроить службу приложений для записи выходных данных стандартной консоли приложения и потоков ошибок стандартной консоли в локальную файловую систему или хранилище BLOB-объектов Azure. Ведение журнала в локальном экземпляре файловой системы Служба приложений отключено через 12 часов после настройки. Если необходимо более длительное хранение, настройте приложение для записи выходных данных в контейнер больших двоичных объектов. Журналы приложений Java и Tomcat можно найти в каталоге /home/LogFiles/Application/.

Включите ведение журнала приложений с помощью портала Azure или Azure CLI, чтобы настроить службу приложений для записи выходных данных стандартной консоли приложения и потоков ошибок стандартной консоли в локальную файловую систему или хранилище BLOB-объектов Azure. Если необходимо более длительное хранение, настройте приложение для записи выходных данных в контейнер больших двоичных объектов. Журналы приложений Java и Tomcat можно найти в каталоге /home/LogFiles/Application/.

Ведение журнала хранилища BLOB-объектов Azure для служб приложений на основе Linux можно настроить только с помощью Azure Monitor

Если приложение использует Logback или Log4j для трассировки, то эти данные трассировки можно передать в Azure Application Insights для просмотра, выполнив инструкции по настройке платформы ведения журнала в разделе Просмотр журналов трассировки Java в Application Insights.

Из-за известной уязвимости CVE-2021-44228 обязательно используйте Log4j версии 2.16 или более поздней.

Настройка

Служба приложений Azure поддерживает настройку с помощью портала Azure и интерфейса командной строки. Ознакомьтесь со следующими статьями о настройке конкретных веб-приложений не на платформе Java:

  • Настройка параметров приложения
  • Настройка личного домена
  • Настройка привязок TLS/SSL
  • Добавление CDN
  • Настройка сайта Kudu

Локальное копирование содержимого приложения

Задайте параметр JAVA_COPY_ALL приложения, чтобы true скопировать содержимое приложения в локальную рабочую роль из общей файловой системы. Это помогает устранить проблемы с блокировкой файлов.

Настройка параметров среды выполнения Java

Чтобы настроить выделенную память или другие параметры среды выполнения виртуальной машины Java, создайте параметр приложения с именем JAVA_OPTS с параметрами. При запуске Служба приложений Azure передает этот параметр в качестве переменной среды в среду выполнения Java.

На портале Azure в разделе Параметры приложения для веб-приложения создайте параметр приложения JAVA_OPTS для Java SE или CATALINA_OPTS для Tomcat с другими параметрами, такими как -Xms512m -Xmx1204m .

Чтобы настроить параметр приложения из подключаемого модуля Maven, добавьте теги «параметр/значение» в раздел подключаемого модуля Azure. В следующем примере задаются минимальный и максимальный размеры кучи для Java.

  JAVA_OPTS -Xms1024m -Xmx1024m   

При использовании Tomcat в Windows Служба приложений не требуется создать файл web.config.

Разработчики, запускающие отдельное приложение в одном слоте развертывания в плане службы приложений, могут использовать следующие параметры.

  • Экземпляры B1 и S1: -Xms1024m -Xmx1024m
  • Экземпляры B2 и S2: -Xms3072m -Xmx3072m
  • Экземпляры B3 и S3: -Xms6144m -Xmx6144m
  • Экземпляры P1v2: -Xms3072m -Xmx3072m
  • Экземпляры P2v2: -Xms6144m -Xmx6144m
  • Экземпляры P3v2: -Xms12800m -Xmx12800m
  • Экземпляры P1v3: -Xms6656m -Xmx6656m
  • Экземпляры P2v3: -Xms14848m -Xmx14848m
  • Экземпляры P3v3: -Xms30720m -Xmx30720m
  • Экземпляры I1: -Xms3072m -Xmx3072m
  • Экземпляры I2: -Xms6144m -Xmx6144m
  • Экземпляры I3: -Xms12800m -Xmx12800m
  • Экземпляры I1v2: -Xms6656m -Xmx6656m
  • Экземпляры I2v2: -Xms14848m -Xmx14848m
  • Экземпляры I3v2: -Xms30720m -Xmx30720m

При настройке параметров кучи приложения просмотрите сведения о плане службы приложений и примите во внимание, что наличие нескольких приложений и одного слота развертывания требует оптимального выделения памяти.

Включение веб-сокетов

Включите для приложения поддержку веб-сокетов на портале Azure в разделе Параметры приложения. Необходимо будет перезапустить приложение, чтобы этот параметр вступил в силу.

Включите поддержку веб-сокетов с помощью Azure CLI, выполнив следующую команду.

az webapp config set --name --resource-group --web-sockets-enabled true 

Затем перезапустите приложение.

az webapp stop --name --resource-group az webapp start --name --resource-group

Настройка кодировки по умолчанию

На портале Azure в разделе Параметры приложения для веб-приложения создайте параметр приложения JAVA_OPTS со значением -Dfile.encoding=UTF-8 .

Можно также настроить параметр приложения с помощью подключаемого модуля Maven для службы приложений. Добавьте теги имени и значения параметра в конфигурацию подключаемого модуля.

  JAVA_OPTS -Dfile.encoding=UTF-8   

Предварительная компиляция JSP-файлов

Чтобы повысить производительность приложений Tomcat, можно скомпилировать JSP-файлы перед развертыванием в службе приложений. Вы можете использовать подключаемый модуль Maven, предоставляемый Apache Sling, или использовать этот файла сборки Ant.

Защита приложений

Для приложений Java, работающих в Службе приложений Azure, предлагается тот же набор рекомендаций по обеспечению безопасности, что и для других приложений.

Аутентификация пользователей (Easy Auth)

Настройте аутентификацию приложения на портале Azure с помощью параметра Проверка подлинности и авторизация. Оттуда можно включить проверку подлинности с помощью идентификатора Microsoft Entra или социальных входов, таких как Facebook, Google или GitHub. На портале Azure можно настроить только один поставщик аутентификации. Дополнительные сведения см. в статье «Настройка приложения Служба приложений для использования входа в Microsoft Entra» и связанных статей для других поставщиков удостоверений. Если необходимо включить несколько поставщиков входа, следуйте инструкциям в статье о настройке входа и выхода.

Java SE

Разработчики Spring Boot могут использовать начальное средство Microsoft Entra Spring Boot для защиты приложений с помощью знакомых заметок Spring Security и API. Увеличьте максимальный размер заголовка в файле application.properties. Мы рекомендуем использовать значение 16384 .

Tomcat

Приложение Tomcat может получить доступ к утверждениям пользователя непосредственно из сервлета, приведя объект Principal к объекту Map. Объект Map будет сопоставлять каждый тип утверждения с коллекцией утверждений для этого типа. В приведенном ниже коде request является экземпляром HttpServletRequest .

Map> map = (Map>) request.getUserPrincipal(); 

Теперь можно проверить объект Map для любого конкретного утверждения. Например, следующий фрагмент кода выполняет перебор всех типов утверждений и выводит содержимое каждой коллекции.

for (Object key : map.keySet()) < Object value = map.get(key); if (value != null && value instanceof Collection < Collection claims = (Collection) value; for (Object claim : claims) < System.out.println(claims); >> > 

Для завершения сеансов пользователей используйте путь /.auth/ext/logout . Другие действия описаны в документации по настройке входа и выхода. Существует также официальная документация по интерфейсу Tomcat HttpServletRequest и его методам. В зависимости от конфигурации Службы приложений также происходит расконсервация следующих методов сервлета:

public boolean isSecure() public String getRemoteAddr() public String getRemoteHost() public String getScheme() public int getServerPort() 

Чтобы отключить эту функцию, создайте параметр приложения с именем WEBSITE_AUTH_SKIP_PRINCIPAL со значением 1 . Чтобы отключить все фильтры сервлета, добавленные службой приложений, создайте параметр с именем WEBSITE_SKIP_FILTERS со значением 1 .

Настройка TLS/SSL

Следуйте инструкциям в разделе Защита пользовательского DNS-имени с помощью привязки TLS/SSL в Службе приложений Azure, чтобы передать существующий TLS/SSL-сертификат и привязать его к доменному имени приложения. По умолчанию приложение по-прежнему будет разрешать HTTP-подключения. Выполните соответствующие инструкции в этом руководстве, чтобы принудительно включить TLS/SSL.

Использование возможностей Key Vault

Azure Key Vault обеспечивает централизованное управление секретами с помощью политик доступа и журнала аудита. Вы можете хранить секреты (например, пароли или строки подключения) в Key Vault и обращаться к этим секретам в приложении с помощью переменных среды.

Сначала следуйте инструкциям, чтобы предоставить приложению доступ к хранилищу ключей и сделать ссылку KeyVault на секрет в параметре приложения. Чтобы проверить, что ссылка разрешается в секрет, можно выполнить печать переменной среды во время удаленного доступа к терминалу Службы приложений.

Чтобы внедрить эти секреты в файл конфигурации Spring или Tomcat, используйте синтаксис внедрения переменных среды ( $ ). Дополнительные сведения о файлах конфигурации Spring см. в этой документации по внешним конфигурациям.

Использование хранилища ключей Java

По умолчанию все общедоступные или частные сертификаты, отправленные в Службу приложений Linux, будут загружены в соответствующие хранилища ключей Java при запуске контейнера. После отправки сертификата необходимо перезапустить Служба приложений, чтобы он был загружен в Хранилище ключей Java. Общедоступные сертификаты загружаются в хранилище ключей в $JRE_HOME/lib/security/cacerts , а частные сертификаты хранятся в $JRE_HOME/lib/security/client.jks .

Для шифрования подключения JDBC с сертификатами в хранилище ключей Java может потребоваться дополнительная настройка. Дополнительные сведения см. в документации по выбранному драйверу JDBC.

Инициализация хранилища ключей Java

Чтобы инициализировать объект import java.security.KeyStore , загрузите файл хранилища ключей с паролем. Пароль по умолчанию для обоих хранилищ ключей — changeit .

KeyStore keyStore = KeyStore.getInstance("jks"); keyStore.load( new FileInputStream(System.getenv("JRE_HOME")+"/lib/security/cacerts"), "changeit".toCharArray()); KeyStore keyStore = KeyStore.getInstance("pkcs12"); keyStore.load( new FileInputStream(System.getenv("JRE_HOME")+"/lib/security/client.jks"), "changeit".toCharArray()); 
Загрузка хранилища ключей вручную

Сертификаты можно загрузить в хранилище ключей вручную. Создайте параметр приложения SKIP_JAVA_KEYSTORE_LOAD со значением 1 , чтобы отключить автоматическую загрузку сертификатов в хранилище ключей Службой приложений. Все общедоступные сертификаты, отправленные в Службу приложений через портал Azure, хранятся в /var/ssl/certs/ . Закрытые сертификаты хранятся в /var/ssl/private/ .

Вы можете взаимодействовать с инструментом для работы с ключами Java или отлаживать его, открыв SSH-подключение к Службе приложений и выполнив команду keytool . Список команд см. в документации по инструменту для работы с ключами. Дополнительные сведения об API KeyStore см . в официальной документации.

Настройка платформ APM

В этом разделе показано, как подключить приложения Java, развернутые на платформах приложение Azure мониторинга производительности приложений (APM) Azure Monitor Аналитика, NewRelic и AppDynamics.

Настройка Application Insights

Приложение Azure Monitor Аналитика — это облачная служба мониторинга приложений, которая позволяет клиентам наблюдать за сбоями, узкими местами и шаблонами использования, чтобы повысить производительность приложений и сократить среднее время разрешения (MTTR). С помощью нескольких щелчков или команд CLI вы можете включить мониторинг приложений Node.js или Java, автозабор журналов, метрик и распределенных трассировок, устраняя необходимость включения пакета SDK в приложение. Дополнительные сведения о доступных параметрах приложения для настройки агента см. в документации по приложению Аналитика.

Портал Azure

Чтобы включить Application Insights на портале Azure, перейдите в раздел Application Insights в меню слева и выберите Включить Application Insights. По умолчанию будет использоваться новый ресурс Application Insights с тем же именем, что и у вашего веб-приложения. Вы можете выбрать существующий ресурс Application Insights или изменить имя нового ресурса. Выберите «Применить» внизу

Azure CLI

Чтобы включить с помощью Azure CLI, необходимо создать ресурс application Аналитика и задать несколько параметров приложения в портал Azure для подключения приложения Аналитика к веб-приложению.

    Включение расширения Application Insights

az extension add -n application-insights 
az monitor app-insights component create --app -g --location westus2 --kind web --application-type web 

Обратите внимание на значения и instrumentationKey , эти значения connectionString потребуются на следующем шаге.

Чтобы получить список других расположений, выполните az account list-locations .

  1. Задайте ключ инструментирования, строку подключения и версию агента мониторинга в качестве параметров приложения в веб-приложении. Замените и значениями из предыдущего шага.
az webapp config appsettings set -n -g --settings "APPINSIGHTS_INSTRUMENTATIONKEY=" "APPLICATIONINSIGHTS_CONNECTION_STRING=" "ApplicationInsightsAgent_EXTENSION_VERSION=~3" "XDT_MicrosoftApplicationInsights_Mode=default" "XDT_MicrosoftApplicationInsights_Java=1" 
  1. Задайте ключ инструментирования, строку подключения и версию агента мониторинга в качестве параметров приложения в веб-приложении. Замените и значениями из предыдущего шага.
az webapp config appsettings set -n -g --settings "APPINSIGHTS_INSTRUMENTATIONKEY=" "APPLICATIONINSIGHTS_CONNECTION_STRING=" "ApplicationInsightsAgent_EXTENSION_VERSION=~3" "XDT_MicrosoftApplicationInsights_Mode=default" 

Настройка New Relic

  1. Создайте учетную запись NewRelic на сайте NewRelic.com
  2. Скачайте агент Java с NewRelic. Его имя файла будет аналогично newrelic-java-x.x.x.zip.
  3. Скопируйте ключ лицензии. Он понадобиться позже для настройки агента.
  4. Подключитесь к экземпляру службы приложений по протоколу SSH и создайте каталог /home/site/wwwroot/apm.
  5. Отправьте распакованные файлы агента Java NewRelic в каталог /home/site/wwwroot/apm. Файлы агента должны располагаться в /home/site/wwwroot/apm/newrelic.
  6. Измените файл YAML в каталоге /home/site/wwwroot/apm/newrelic/newrelic.yml и замените значение лицензии в заполнителе собственным ключом лицензии.
  7. На портале Azure перейдите к приложению в службе приложений и создайте параметр приложения.
    • Для приложений Java SE создайте переменную среды JAVA_OPTS со значением -javaagent:/home/site/wwwroot/apm/newrelic/newrelic.jar .
    • Для Tomcat создайте переменную среды CATALINA_OPTS со значением -javaagent:/home/site/wwwroot/apm/newrelic/newrelic.jar .
  1. Создайте учетную запись NewRelic на сайте NewRelic.com
  2. Скачайте агент Java с NewRelic. Его имя файла будет аналогично newrelic-java-x.x.x.zip.
  3. Скопируйте ключ лицензии. Он понадобиться позже для настройки агента.
  4. Подключитесь к экземпляру службы приложений по протоколу SSH и создайте каталог /home/site/wwwroot/apm.
  5. Отправьте распакованные файлы агента Java NewRelic в каталог /home/site/wwwroot/apm. Файлы агента должны располагаться в /home/site/wwwroot/apm/newrelic.
  6. Измените файл YAML в каталоге /home/site/wwwroot/apm/newrelic/newrelic.yml и замените значение лицензии в заполнителе собственным ключом лицензии.
  7. На портале Azure перейдите к приложению в службе приложений и создайте параметр приложения.
    • Для приложений Java SE создайте переменную среды JAVA_OPTS со значением -javaagent:/home/site/wwwroot/apm/newrelic/newrelic.jar .
    • Для Tomcat создайте переменную среды CATALINA_OPTS со значением -javaagent:/home/site/wwwroot/apm/newrelic/newrelic.jar .

Если у вас уже есть переменная среды JAVA_OPTS или CATALINA_OPTS , добавьте параметр -javaagent:/. в конец текущего значения.

Настройка AppDynamics

  1. Создайте учетную запись AppDynamics на сайте AppDynamics.com
  2. Скачайте агент Java с веб-сайта AppDynamics. Имя файла будет аналогично AppServerAgent-x.x.x.xxxxx.zip.
  3. С помощью консоли Kudu создайте новый каталог /home/site/wwwroot/apm.
  4. Отправьте файлы агента Java в каталог /home/site/wwwroot/apm. Файлы агента должны располагаться в /home/site/wwwroot/apm/appdynamics.
  5. На портале Azure перейдите к приложению в службе приложений и создайте параметр приложения.
    • Для приложений Java SE создайте переменную среды JAVA_OPTS со значением -javaagent:/home/site/wwwroot/apm/appdynamics/javaagent.jar -Dappdynamics.agent.applicationName= , где — имя Службы приложений Azure.
    • Для Tomcat создайте переменную среды CATALINA_OPTS со значением -javaagent:/home/site/wwwroot/apm/appdynamics/javaagent.jar -Dappdynamics.agent.applicationName= , где — имя Службы приложений Azure.
  1. Создайте учетную запись AppDynamics на сайте AppDynamics.com
  2. Скачайте агент Java с веб-сайта AppDynamics. Имя файла будет аналогично AppServerAgent-x.x.x.xxxxx.zip.
  3. Подключитесь к экземпляру службы приложений по протоколу SSH и создайте каталог /home/site/wwwroot/apm.
  4. Отправьте файлы агента Java в каталог /home/site/wwwroot/apm. Файлы агента должны располагаться в /home/site/wwwroot/apm/appdynamics.
  5. На портале Azure перейдите к приложению в службе приложений и создайте параметр приложения.
    • Для приложений Java SE создайте переменную среды JAVA_OPTS со значением -javaagent:/home/site/wwwroot/apm/appdynamics/javaagent.jar -Dappdynamics.agent.applicationName= , где — имя Службы приложений Azure.
    • Для Tomcat создайте переменную среды CATALINA_OPTS со значением -javaagent:/home/site/wwwroot/apm/appdynamics/javaagent.jar -Dappdynamics.agent.applicationName= , где — имя Службы приложений Azure.

Если у вас уже есть переменная среды JAVA_OPTS или CATALINA_OPTS , добавьте параметр -javaagent:/. в конец текущего значения.

Настройка источников данных

Java SE

Чтобы подключиться к источникам данных в приложениях Spring Boot, мы рекомендуем создавать строки подключения и внедрять их в файл application.properties.

  1. В разделе «Конфигурация» на странице Службы приложений задайте имя строки, вставьте строку подключения JDBC в поле «Значение» и присвойте типу значение «Пользовательский». При необходимости можно задать эту строку подключения в качестве параметра слота. Эта строка подключения доступна для нашего приложения в виде переменной среды с именем CUSTOMCONNSTR_ . Например, строка подключения, созданная выше, будет называться CUSTOMCONNSTR_exampledb .
  2. В файле application.properties нужно сослаться на эту строку подключения с именем переменной среды. В нашем примере мы будем использовать следующее.

app.datasource.url=$

Tomcat

Эти инструкции применимы ко всем подключениям к базе данных. Вам потребуется заполнить заполнители именем класса драйвера выбранной базы данных и JAR-файлом. Ниже приведена таблица с именами классов и ссылками для скачивания драйверов для распространенных баз данных.

База данных Имя класса драйвера драйвер JDBC.
PostgreSQL org.postgresql.Driver Скачать
MySQL com.mysql.jdbc.Driver Скачать (выберите «Platform Independent» (Независимо от платформы))
SQL Server com.microsoft.sqlserver.jdbc.SQLServerDriver Скачать

Чтобы настроить Tomcat для использования Java Database Connectivity (JDBC) или Java Persistence API (JPA), сначала настройте переменную среды CATALINA_OPTS , считываемую Tomcat при запуске. Задайте эти значения с помощью параметра приложения в подключаемом модуле Maven для службы приложений:

  CATALINA_OPTS "$CATALINA_OPTS -Ddbuser=$ -Ddbpassword=$ -DconnURL=$"   

Переменные среды можно также задать на странице Конфигурация>Параметры приложения на портале Azure.

Затем определите, должен ли источник данных быть доступным для одного приложения или для всех приложений, работающих в сервлете Tomcat.

Источники данных уровня приложения
  1. Создайте файл context.xml в каталоге проекта META-INF/. Создайте каталог META-INF или, если он не существует.
  2. В context.xml добавьте элемент Context , чтобы связать источник данных с адресом JNDI. Замените заполнитель driverClassName именем класса драйвера из приведенной выше таблицы.
 " driverClassName="" username="$" password="$" /> 
 jdbc/dbconnection javax.sql.DataSource  
Общие ресурсы уровня сервера

Установки Tomcat в Службе приложений в Windows существуют в общем пространстве в плане службы приложений. Нельзя напрямую изменить установку Tomcat для конфигурации на уровне сервера. Чтобы внести изменения в конфигурацию установки Tomcat на уровне сервера, необходимо скопировать Tomcat в локальную папку, в которой можно изменить конфигурацию Tomcat.

Автоматизация создания пользовательской версии Tomcat при запуске приложения

Скрипт запуска можно использовать для выполнения действий перед запуском веб-приложения. Скрипт запуска для настройки Tomcat должен выполнить следующие действия.

  1. Проверка, что Tomcat уже скопирован и настроен локально. Если это так, скрипт запуска может завершить работу.
  2. Копирование Tomcat локально.
  3. Внесение необходимых изменений в конфигурацию.
  4. Указание, что конфигурация успешно завершена.

Для сайтов Windows создайте файл startup.cmd или startup.ps1 в каталоге wwwroot . Он будет выполняться автоматически перед запуском сервера Tomcat.

Ниже приведен скрипт PowerShell, который выполняет эти действия.

 # Check for marker file indicating that config has already been done if(Test-Path "$Env:LOCAL_EXPANDED\tomcat\config_done_marker") < return 0 ># Delete previous Tomcat directory if it exists # In case previous config could not be completed or a new config should be forcefully installed if(Test-Path "$Env:LOCAL_EXPANDED\tomcat") < Remove-Item "$Env:LOCAL_EXPANDED\tomcat" --recurse ># Copy Tomcat to local # Using the environment variable $AZURE_TOMCAT90_HOME uses the 'default' version of Tomcat Copy-Item -Path "$Env:AZURE_TOMCAT90_HOME\*" -Destination "$Env:LOCAL_EXPANDED\tomcat" -Recurse # Perform the required customization of Tomcat # Mark that the operation was a success New-Item -Path "$Env:LOCAL_EXPANDED\tomcat\config_done_marker" -ItemType File 
Преобразования

Распространенным вариантом использования для настройки версии Tomcat является изменение файлов конфигурации Tomcat server.xml , context.xml или web.xml . Служба приложений уже изменяет эти файлы для предоставления функций платформы. Чтобы продолжить использовать этих функций, важно сохранить содержимое этих файлов при внесении в них изменений. Для этого рекомендуется использовать преобразование XSL (XSLT). Используйте преобразование XSL для внесения изменений в XML-файлы с сохранением исходного содержимого файла.

Пример XSLT-файла

В этом примере преобразование добавляет в server.xml новый узел соединителя. Обратите внимание на преобразование удостоверения, которое сохраняет исходное содержимое файла.

                           
 >/.keystore" keystorePass="changeit" clientAuth="false" sslProtocol="TLS" />  
Функция для преобразования XSL

В PowerShell имеются встроенные средства для преобразования XML-файлов с помощью преобразований XSL. Следующий скрипт является примером функции, которую можно использовать в startup.ps1 для выполнения преобразования.

 function TransformXML < param ($xml, $xsl, $output) if (-not $xml -or -not $xsl -or -not $output) < return 0 >Try < $xslt_settings = New-Object System.Xml.Xsl.XsltSettings; $XmlUrlResolver = New-Object System.Xml.XmlUrlResolver; $xslt_settings.EnableScript = 1; $xslt = New-Object System.Xml.Xsl.XslCompiledTransform; $xslt.Load($xsl,$xslt_settings,$XmlUrlResolver); $xslt.Transform($xml, $output); >Catch < $ErrorMessage = $_.Exception.Message $FailedItem = $_.Exception.ItemName Write-Host 'Error'$ErrorMessage':'$FailedItem':' $_.Exception; return 0 >return 1 > 
Параметры приложения

Платформа также должна иметь представление о том, где установлена пользовательская версия Tomcat. Расположение установки можно задать в параметре приложения CATALINA_BASE .

Вы можете изменить этот параметр с помощью Azure CLI.

 az webapp config appsettings set -g $MyResourceGroup -n $MyUniqueApp --settings CATALINA_BASE="%LOCAL_EXPANDED%\tomcat" 

Этот параметр также можно изменить вручную на портале Azure.

  1. Перейдите в раздел Параметры>Конфигурация>Параметры приложения.
  2. Выберите Создать параметр приложения.
  3. Используйте эти значения для создания параметра:
    1. Имя: CATALINA_BASE
    2. Значение: «%LOCAL_EXPANDED%\tomcat»
    Пример startup.ps1

    В следующем примере скрипта пользовательская версия Tomcat копируется в локальную папку, выполняется преобразование XSL и указывается, что преобразование выполнено успешно.

     # Locations of xml and xsl files $target_xml="$Env:LOCAL_EXPANDED\tomcat\conf\server.xml" $target_xsl="$Env:HOME\site\server.xsl" # Define the transform function # Useful if transforming multiple files function TransformXML < param ($xml, $xsl, $output) if (-not $xml -or -not $xsl -or -not $output) < return 0 >Try < $xslt_settings = New-Object System.Xml.Xsl.XsltSettings; $XmlUrlResolver = New-Object System.Xml.XmlUrlResolver; $xslt_settings.EnableScript = 1; $xslt = New-Object System.Xml.Xsl.XslCompiledTransform; $xslt.Load($xsl,$xslt_settings,$XmlUrlResolver); $xslt.Transform($xml, $output); >Catch < $ErrorMessage = $_.Exception.Message $FailedItem = $_.Exception.ItemName echo 'Error'$ErrorMessage':'$FailedItem':' $_.Exception; return 0 >return 1 > $success = TransformXML -xml $target_xml -xsl $target_xsl -output $target_xml # Check for marker file indicating that config has already been done if(Test-Path "$Env:LOCAL_EXPANDED\tomcat\config_done_marker") < return 0 ># Delete previous Tomcat directory if it exists # In case previous config could not be completed or a new config should be forcefully installed if(Test-Path "$Env:LOCAL_EXPANDED\tomcat") < Remove-Item "$Env:LOCAL_EXPANDED\tomcat" --recurse >md -Path "$Env:LOCAL_EXPANDED\tomcat" # Copy Tomcat to local # Using the environment variable $AZURE_TOMCAT90_HOME uses the 'default' version of Tomcat Copy-Item -Path "$Env:AZURE_TOMCAT90_HOME\*" "$Env:LOCAL_EXPANDED\tomcat" -Recurse # Perform the required customization of Tomcat $success = TransformXML -xml $target_xml -xsl $target_xsl -output $target_xml # Mark that the operation was a success if successful if($success)
    Завершение конфигурации

    Наконец, вы поместите драйвер JARs в путь к классу Tomcat и перезапустите Служба приложений. Убедитесь, что файлы драйвера JDBC доступны для загрузчика классов Tomcat, разместив их в каталоге /home/tomcat/lib. (Создайте этот каталог, если он еще не существует.) Чтобы передать эти файлы в экземпляр Служба приложений, выполните следующие действия.

      В Cloud Shell установите расширение webapp:

    az extension add -–name webapp 
    az webapp remote-connection create --resource-group --name --port

    Кроме того, драйвер JDBC можно отправить с помощью FTP-клиента. Чтобы получить учетные данные FTP, следуйте этим инструкциям.

    Tomcat

    Эти инструкции применимы ко всем подключениям к базе данных. Вам потребуется заполнить заполнители именем класса драйвера выбранной базы данных и JAR-файлом. Ниже приведена таблица с именами классов и ссылками для скачивания драйверов для распространенных баз данных.

    База данных Имя класса драйвера драйвер JDBC.
    PostgreSQL org.postgresql.Driver Скачать
    MySQL com.mysql.jdbc.Driver Скачать (выберите «Platform Independent» (Независимо от платформы))
    SQL Server com.microsoft.sqlserver.jdbc.SQLServerDriver Скачать

    Чтобы настроить Tomcat для использования Java Database Connectivity (JDBC) или Java Persistence API (JPA), сначала настройте переменную среды CATALINA_OPTS , считываемую Tomcat при запуске. Задайте эти значения с помощью параметра приложения в подключаемом модуле Maven для службы приложений:

      CATALINA_OPTS "$CATALINA_OPTS -Ddbuser=$ -Ddbpassword=$ -DconnURL=$"   

    Переменные среды можно также задать на странице Конфигурация>Параметры приложения на портале Azure.

    Затем определите, должен ли источник данных быть доступным для одного приложения или для всех приложений, работающих в сервлете Tomcat.

    Источники данных уровня приложения
    1. Создайте файл context.xml в каталоге проекта META-INF/. Создайте каталог META-INF или, если он не существует.
    2. В context.xml добавьте элемент Context , чтобы связать источник данных с адресом JNDI. Замените заполнитель driverClassName именем класса драйвера из приведенной выше таблицы.
     " driverClassName="" username="$" password="$" /> 
     jdbc/dbconnection javax.sql.DataSource  
    Общие ресурсы уровня сервера

    Для добавления общего источника данных на уровне сервера потребуется изменить файл server.xml Tomcat. Сначала отправьте сценарий запуска и задайте путь к скрипту в разделе Конфигурация>Команда запуска. Сценарий запуска можно добавить с помощью FTP.

    Сценарий запуска преобразует XSL в файл server.xml и выведет полученный XML-файл в /usr/local/tomcat/conf/server.xml . Сценарий запуска должен установить libxslt через apk. XSL-файл и скрипт запуска можно отправить через FTP. Ниже приведен пример скрипта запуска.

    # Install libxslt. Also copy the transform file to /home/tomcat/conf/ apk add --update libxslt # Usage: xsltproc --output output.xml style.xsl input.xml xsltproc --output /home/tomcat/conf/server.xml /home/tomcat/conf/transform.xsl /usr/local/tomcat/conf/server.xml 

    Пример XSL-файла приведен ниже. В примере XSL-файл добавляет новый узел соединителя в server.xml Tomcat.

                            
     >/.keystore" keystorePass="changeit" clientAuth="false" sslProtocol="TLS" />  
    Завершение конфигурации

    Наконец, разместите JAR-файлы драйверов в пути к классам Tomcat и перезапустите службу приложений.

    1. Убедитесь, что файлы драйвера JDBC доступны для загрузчика классов Tomcat, разместив их в каталоге /home/tomcat/lib. (Создайте этот каталог, если он еще не существует.) Чтобы передать эти файлы в экземпляр Служба приложений, выполните следующие действия.
      1. В Cloud Shell установите расширение webapp:
      az extension add -–name webapp 
      1. Выполните следующую команду CLI, чтобы создать туннель SSH между локальной системой и службой приложений.
      az webapp remote-connection create --resource-group --name --port
      1. Подключитесь к локальному порту туннелирования с помощью клиента SFTP и передайте эти файлы в папку /home/tomcat/lib.

      Кроме того, драйвер JDBC можно отправить с помощью FTP-клиента. Чтобы получить учетные данные FTP, следуйте этим инструкциям.

      Источники данных EAP JBoss

      Для регистрации источника данных с помощью JBoss EAP необходимо выполнить три основных шага: передать драйвер JDBC, добавить драйвер JDBC в качестве модуля и зарегистрировать модуль. Служба приложений — это служба размещения без отслеживания состояния, поэтому команды конфигурации для добавления и регистрации модуля источника данных необходимо внести в скрипт и применить при запуске контейнера.

      1. Получите драйвер JDBC для базы данных.
      2. Создайте файл определения модуля XML для драйвера JDBC. Ниже приведен пример определения модуля для PostgreSQL.

      #!/usr/bin/env bash module add --name=org.postgres --resources=/home/site/deployments/tools/postgresql-42.2.12.jar --module-xml=/home/site/deployments/tools/postgres-module.xml /subsystem=datasources/jdbc-driver=postgres:add(driver-name="postgres",driver-module-name="org.postgres",driver-class-name=org.postgresql.Driver,driver-xa-datasource-class-name=org.postgresql.xa.PGXADataSource) data-source add --name=postgresDS --driver-name=postgres --jndi-name=java:jboss/datasources/postgresDS --connection-url=$ --user-name=$ --password=$ --use-ccm=true --max-pool-size=5 --blocking-timeout-wait-millis=5000 --enabled=true --driver-class=org.postgresql.Driver --exception-sorter-class-name=org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter --jta=true --use-java-context=true --valid-connection-checker-class-name=org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker 
      $JBOSS_HOME/bin/jboss-cli.sh --connect --file=/home/site/deployments/tools/jboss-cli-commands.cli 

      Чтобы убедиться в том, что источник данных добавлен на сервер JBoss, установите SSH-подключение к веб-приложению и запустите $JBOSS_HOME/bin/jboss-cli.sh —connect . После подключения к JBoss запустите /subsystem=datasources:read-resource список источников данных.

      robots933456 в журналах

      В журналах контейнера может отобразиться следующее сообщение:

      2019-04-08T14:07:56.641002476Z "-" - - [08/Apr/2019:14:07:56 +0000] "GET /robots933456.txt HTTP/1.1" 404 415 "-" "-" 

      Это сообщение можно проигнорировать. /robots933456.txt — это фиктивный URL-путь, с помощью которого Служба приложений проверяет, может ли контейнер обслуживать запросы. Ответ 404 означает, что путь не существует. При этом он информирует Службу приложений о том, что контейнер работоспособен и готов отвечать на запросы.

      Выбор версии среды выполнения Java

      Служба приложений позволяет пользователям выбрать основной номер версии виртуальной машины Java, например Java 8 или Java 11, а также номер исправления, например 1.8.0_232 или 11.0.5. Кроме того, можно выбрать автоматическое обновление номера исправления при появлении новых дополнительных версий. В большинстве случаев для рабочих сайтов следует использовать версии виртуальной машины Java с закрепленными номерами исправлений. Это позволит предотвратить непредвиденные сбои во время автоматического обновления версии исправлений. Все веб-приложения Java используют 64-разрядные виртуальные машины JVM, это не настраивается.

      Если вы используете Tomcat, можно закрепить версию исправления Tomcat. На Windows версии исправления виртуальной машины Java и Tomcat можно закрепить независимо друг от друга. В Linux можно закрепить версию исправлений Tomcat; Версия исправления JVM также будет закреплена, но не настраивается отдельно.

      Если вы решили закрепить дополнительную версию, необходимо периодически обновлять дополнительную версию JVM на сайте. Чтобы гарантировать выполнение приложения в более новой дополнительной версии, создайте промежуточный слот и увеличьте дополнительный номер версии на промежуточном сайте. Подтвердив правильность работы приложения в новой дополнительной версии, можно поменять местами промежуточный и рабочий слоты.

      JBoss EAP

      Кластеризация в JBoss EAP

      Служба приложений поддерживает кластеризацию для JBoss EAP версии 7.4.1 и выше. Чтобы включить кластеризацию, веб-приложение должно быть интегрировано с виртуальной сетью. При интеграции веб-приложения с виртуальной сетью веб-приложение перезагрузится, а JBoss EAP автоматически запускается с кластеризованной конфигурацией. Экземпляры JBoss EAP будут взаимодействовать через подсеть, указанную в интеграции виртуальной сети, используя порты, указанные в переменной WEBSITES_PRIVATE_PORTS среды во время выполнения. Кластеризацию можно отключить, создав параметр приложения с именем WEBSITE_DISABLE_CLUSTERING и с любым значением.

      Если вы включаете интеграцию виртуальной сети с шаблоном ARM, необходимо вручную задать для свойства vnetPrivatePorts значение 2 . Если включить интеграцию с виртуальной сетью с помощью интерфейса командной строки или портала, это свойство будет установлено автоматически.

      Если кластеризация включена, то экземпляры JBoss EAP используют протокол обнаружения FILE_PING JGroups для обнаружения новых экземпляров и сохранения сведений о кластере, таких как члены кластера, их идентификаторы и IP-адреса. В службе приложений эти файлы находятся в папке /home/clusterinfo/ . Первый экземпляр EAP для запуска будет получать разрешения на чтение и запись в файле членства в кластере. Другие экземпляры считывают файл, находят основной узел и координируют с ним свои действия для включения в кластер и добавления в файл.

      Типы планов службы приложений «Премиум» версии 3 и «Изолированный» версии 2 также можно распределить по зонам доступности для повышения устойчивости и надежности критически важных для бизнеса рабочих нагрузок. Эта архитектура также называется избыточностью между зонами. Функция JBoss EAP кластеризация совместима с функцией избыточности зоны.

      Правила автомасштабирования

      При настройке правил автомасштабирования для горизонтального масштабирования важно удалять экземпляры постепенно (по одному за раз), чтобы каждый удаленный экземпляр может передавать свое действие (например, обработку транзакции базы данных) другому члену кластера. При настройке правил автомасштабирования на портале для уменьшения масштаба используйте следующие параметры:

      • Операция: «Уменьшить количество на».
      • Ожидание: «5 минут» или больше.
      • Число экземпляров: 1.

      Вам не нужно добавочно добавлять экземпляры (масштабирование), одновременно добавлять несколько экземпляров в кластер.

      Планы службы приложений JBoss EAP

      JBoss EAP доступен только для типов планов службы приложений «Премиум» версии 3 и «Изолированный» версии 2. Клиенты, которые создали сайт JBoss EAP на другом уровне в общедоступной предварительной версии, должны повысить уровень оборудования до «Премиум» или «Изолированный» во избежание непредвиденного поведения.

      Следующие шаги

      Посетите центр Azure для разработчиков Java, чтобы найти краткие руководства Azure, руководства и справочную документацию по Java.

      • Служба приложений под управлением Linux: вопросы и ответы
      • Справка по переменным среды и параметрам приложений

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *