[Программирование, Java] Отправка электронных писем с помощью Spring (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
В рамках обучающей серии по Spring Boot в этой статье мы рассмотрим способ отправки электронных писем с помощью Spring.ВведениеОтправка электронных писем — одна из базовых функций, которая может понадобиться в любом приложении. Из этой статьи вы узнаете, как отправлять электронные письма с помощью Spring. Для отправки электронных писем вам потребуются данные SMTP-сервера. В качестве примера вы можете использовать SMTP для Gmail (имейте в виду, что у Gmail есть определенные ограничения по отправке электронной почты). Интерфейс JavaMailSender в Spring Framework предлагает простую абстракцию для отправки электронной почты, а Spring Boot производит автоматическую настройку этого интерфейса и стартового модуля.1. Зависимости MavenЧтобы добавить функцию автоконфигурации Spring Boot в приложение, нам нужно внести spring-boot-starter-mail в файл pom.xml. Ниже представлен фрагмент нашего файла pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
2. Конфигурация электронной почтыПосле того как мы определили зависимости, следующим шагом будет добавление конфигурации почты для автоматической настройки с помощью Spring Boot:
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username= gmail user name
spring.mail.password= your password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
Приведенные выше значения конфигурации относятся к SMTP-серверу Gmail. При необходимости замените их своими3. Служба электронной почтыДалее мы создадим простой класс службы электронной почты, который позволит нашему приложению отправлять электронные письма. В нашем примере почтовой службы мы реализуем два метода:
- отправка простых электронных писем;
- отправка электронных писем с вложением.
Наш код будет выглядеть так:
@Service
public class DefaultEmailService implements EmailService {
@Autowired
public JavaMailSender emailSender;
@Override
public void sendSimpleEmail(String toAddress, String subject, String message) {
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setTo(toAddress);
simpleMailMessage.setSubject(subject);
simpleMailMessage.setText(message);
emailSender.send(simpleMailMessage);
}
@Override
public void sendEmailWithAttachment(String toAddress, String subject, String message, String attachment) throws MessagingException, FileNotFoundException {
MimeMessage mimeMessage = emailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
messageHelper.setTo(toAddress);
messageHelper.setSubject(subject);
messageHelper.setText(message);
FileSystemResource file = new FileSystemResource(ResourceUtils.getFile(attachment));
messageHelper.addAttachment("Purchase Order", file);
emailSender.send(mimeMessage);
}
}
4. Тестовый контроллерСоздадим простой контроллер REST, чтобы проверить, как работает код. У нашего контроллера REST будет два метода. Сам контроллер будет выглядеть так:
package com.javadevjournal.controller;
import com.javadevjournal.email.service.EmailService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.mail.MailException;
import org.springframework.web.bind.annotation.*;
import javax.mail.MessagingException;
import java.io.FileNotFoundException;
@RestController
@RequestMapping("/email")
public class EmailController {
private static final Logger LOG = LoggerFactory.getLogger(EmailController.class);
@Autowired
EmailService emailService;
@GetMapping(value = "/simple-email/{user-email}")
public @ResponseBody ResponseEntity sendSimpleEmail(@PathVariable("user-email") String email) {
try {
emailService.sendSimpleEmail(email, "Welcome", "This is a welcome email for your!!");
} catch (MailException mailException) {
LOG.error("Error while sending out email..{}", mailException.getStackTrace());
return new ResponseEntity<>("Unable to send email", HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<>("Please check your inbox", HttpStatus.OK);
}
@GetMapping(value = "/simple-order-email/{user-email}")
public @ResponseBody ResponseEntity sendEmailAttachment(@PathVariable("user-email") String email) {
try {
emailService.sendEmailWithAttachment(email, "Order Confirmation", "Thanks for your recent order",
"classpath:purchase_order.pdf");
} catch (MessagingException | FileNotFoundException mailException) {
LOG.error("Error while sending out email..{}", mailException.getStackTrace());
return new ResponseEntity<>("Unable to send email", HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<>("Please check your inbox for order confirmation", HttpStatus.OK);
}
}
5. Основной класс Spring Boot
@SpringBootApplication
public class SendEmailUsingSpringApplication {
public static void main(String[] args) {
SpringApplication.run(SendEmailUsingSpringApplication.class, args);
}
}
Запустите приложение и перейдите по следующим ссылкам:
http://localhost:8080/email/order-email/umeshawasthi@www.javadevjournal.com
http://localhost:8080/email/simple-email/umeshawasthi@www.javadevjournal.com
6. Конфигурация SMTP-сервера GmailПрежде чем использовать SMTP-сервер Gmail, ознакомьтесь со следующей статьей. Из-за дополнительных мер безопасности в Gmail ваш обычный пароль от электронной почты работать не будет. Отправка электронных писем с помощью Spring Boot и ThymeleafВ предыдущем разделе мы рассмотрели, как отправлять электронные письма с помощью Spring. Однако для рабочего приложения понадобится более продвинутый способ. В этом разделе мы рассмотрим, как отправлять электронные письма с помощью Spring Boot и Thymeleaf.Thyleleaf — это шаблонизатор. Thymeleaf поможет нам отправлять электронные письма в формате HTML с широкими функциональными возможностями. Предположим, мы хотим отправить клиенту электронное письмо для подтверждения его учетной записи.7. Класс EmailContextДля большей универсальности создадим класс EmailContext, содержащий всю основную информацию, которая нам нужна для электронной почты. Наш класс будет выглядеть так:
public abstract class AbstractEmailContext {
private String from;
private String to;
private String subject;
private String email;
private String attachment;
private String fromDisplayName;
private String emailLanguage;
private String displayName;
private String templateLocation;
private Map <String, Object> context;
//getter and seter methods
}
Рассмотрим несколько полей этого класса:
- templateLocation — указывает расположение HTML-шаблона. Это поле понадобится нам для генерации окончательного вывода.
- context — содержит все динамические значения, передаваемые в электронном письме. Thymeleaf будет использовать эту карту для замены выражений фактическими значениями (например, ваше имя и т. д.).
Далее мы настроим нашу службу электронной почты на обработку HTML-шаблонов Thymeleaf для наполнения электронных писем.8. Реализация EmailService
package com.javadevjournal.core.email.service;
import com.javadevjournal.core.email.context.AbstractEmailContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.nio.charset.StandardCharsets;
@Service
public class DefaultEmailService implements EmailService {
@Autowired
private JavaMailSender emailSender;
@Autowired
private SpringTemplateEngine templateEngine;
@Override
public void sendMail(AbstractEmailContext email) throws MessagingException {
MimeMessage message = emailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message,
MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED,
StandardCharsets.UTF_8.name());
Context context = new Context();
context.setVariables(email.getContext());
String emailContent = templateEngine.process(email.getTemplateLocation(), context);
mimeMessageHelper.setTo(email.getTo());
mimeMessageHelper.setSubject(email.getSubject());
mimeMessageHelper.setFrom(email.getFrom());
mimeMessageHelper.setText(emailContent, true);
emailSender.send(message);
}
}
В приведенном выше коде есть несколько важных моментов.
- Мы создаем и настраиваем карту как набор переменных. Thymeleaf будет использовать этот контекст для замены заполнителей или выражений значениями, переданными через него.
- SpringTemplateEngine представляет собой абстракцию различных шаблонизаторов, эта функция осуществляет выбор настроенного шаблонизатора. В нашем случае это Thymeleaf.
- Функция templateEngine.process() отвечает за обработку и возврат результата в виде строки. Она выбирает шаблон HTML, обработает его и заменяет выражения фактическими значениями.
- Наконец, мы встраиваем получившийся результат в MimeMessage и заставляем почтовый сервер обрабатывать его как HTML (mimeMessageHelper.setText(emailContent, true))
9. Шаблон электронного письмаВот наш HTML-шаблон для электронного письма (для экономии места я немного сократил HTML-код).
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<meta charset="utf-8"> <!-- utf-8 works for most cases -->
<meta name="viewport" content="width=device-width"> <!-- Forcing initial-scale shouldn't be necessary -->
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- Use the latest (edge) version of IE rendering engine -->
<meta name="x-apple-disable-message-reformatting"> <!-- Disable auto-scale in iOS 10 Mail entirely -->
<title></title> <!-- The title tag shows in email notifications, like Android 4.4. -->
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
<!-- CSS Reset : BEGIN -->
</head>
<body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;">
<center style="width: 100%; background-color: #f1f1f1;">
<div style="display: none; font-size: 1px;max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden; mso-hide: all; font-family: sans-serif;">
</div>
<div style="max-width: 600px; margin: 0 auto;" class="email-container">
<!-- BEGIN BODY -->
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="margin: auto;">
<tr>
<td valign="top" class="bg_white" style="padding: 1em 2.5em 0 2.5em;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="logo" style="text-align: center;">
<h1>Welcome</h1>
</td>
</tr>
</table>
</td>
</tr><!-- end tr -->
<tr>
<td valign="middle" class="hero bg_white" style="padding: 2em 0 4em 0;">
<table>
<tr>
<td>
<div class="text" style="padding: 0 2.5em; text-align: center;">
<h2>Finish creating your account.</h2>
<h3>Hi<p th:text="${firstName}"></h3>
<h3>We're excited to have you get started. First, you need to confirm your account. Just press the button below.</h3>
<p><a th:href="${verificationURL}" class="btn btn-primary">Validate Account</a></p>
</div>
</td>
</tr>
<tr>
<td>
<div class="text" style="padding: 0 2.5em; text-align: center;">
<h3>if you experience any issues with the button above, copy and paste the URL below into your web browser.</h3>
<p th:text="${verificationURL}"></p>
</div>
</td>
</tr>
</table>
</td>
</tr><!-- end tr -->
<!-- 1 Column Text + Button : END -->
</table>
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="margin: auto;">
<tr>
<td valign="middle" class="bg_light footer email-section">
<table>
<tr>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-right: 10px;">
<h3 class="heading">About</h3>
<p>Welcome to Java Development Journal Blog. We publish articles on
Spring, Spring Boot and Spring Security.
</p>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 5px; padding-right: 5px;">
<h3 class="heading">Contact Info</h3>
<ul>
<li><span class="text">Java Development Journal</span></li>
</ul>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 10px;">
<h3 class="heading">Useful Links</h3>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
</ul>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr><!-- end: tr -->
</table>
</div>
</center>
</body>
</html>
Имейте в виду, что необходимо внести в контекст значения для ${firstName} и ${verifyURL}, чтобы Thymeleaf мог подставить фактические значения для этих переменных во время обработки.РезюмеВ этой статье мы узнали, как отправлять электронные письма с помощью Spring. Мы узнали, каким образом можно реализовать функции электронной почты с применением автоконфигурации Spring Boot. Исходный код, приведенный в этом посте, доступен на GitHub.
Перевод материала подготовили в преддверии старта курса онлайн-курса «Разработчик на Spring Framework».Приглашаем также всех желающих на открытый вебинар «Spring в Docker. Практические советы». На занятии мы рассмотрим всем известную тему по запуску Spring-приложений в Docker-контейнере и не всем известные решения возникающих задач.
===========
Источник:
habr.com
===========
===========
Автор оригинала: javadevjournal.com
===========Похожие новости:
- [Тестирование игр] 7 методов тестирования игр (перевод)
- [Программирование, Разработка робототехники, Бизнес-модели, Робототехника] Кружок робототехники VS технический центр
- [JavaScript, Google Chrome, HTML] Швейцарский нож отладки JavaScript
- [Программирование, Совершенный код, Управление разработкой] Почему в мире так много отстойного ПО (перевод)
- [Oracle, Программирование, SQL, DevOps] Настройка CI/CD скриптов миграции БД с нуля с использованием GitLab и Liquibase
- [Разработка веб-сайтов, JavaScript, TypeScript] TypeScript: Раскладываем tsconfig по полочкам. Часть 2
- [Программирование микроконтроллеров, Производство и разработка электроники, Компьютерное железо] Новые цены на микроконтроллеры STM32 из свежих поставок
- [Perl, Ruby, Python, Программирование, Node.JS] Сервер в одну строку на 17 языках (перевод)
- [Программирование, Учебный процесс в IT, Карьера в IT-индустрии] Личный опыт: подготовка к магистратуре JetBrains в Университете ИТМО и первые впечатления
- [Разработка веб-сайтов, JavaScript, ReactJS, TypeScript] Кэш или стэйт, пробуем React-query
Теги для поиска: #_programmirovanie (Программирование), #_java, #_java, #_spring, #_maven, #_email_service, #_docker, #_blog_kompanii_otus (
Блог компании OTUS
), #_programmirovanie (
Программирование
), #_java
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 16:12
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
В рамках обучающей серии по Spring Boot в этой статье мы рассмотрим способ отправки электронных писем с помощью Spring.ВведениеОтправка электронных писем — одна из базовых функций, которая может понадобиться в любом приложении. Из этой статьи вы узнаете, как отправлять электронные письма с помощью Spring. Для отправки электронных писем вам потребуются данные SMTP-сервера. В качестве примера вы можете использовать SMTP для Gmail (имейте в виду, что у Gmail есть определенные ограничения по отправке электронной почты). Интерфейс JavaMailSender в Spring Framework предлагает простую абстракцию для отправки электронной почты, а Spring Boot производит автоматическую настройку этого интерфейса и стартового модуля.1. Зависимости MavenЧтобы добавить функцию автоконфигурации Spring Boot в приложение, нам нужно внести spring-boot-starter-mail в файл pom.xml. Ниже представлен фрагмент нашего файла pom.xml: <dependency>
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> spring.mail.host=smtp.gmail.com
spring.mail.port=587 spring.mail.username= gmail user name spring.mail.password= your password spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true
@Service
public class DefaultEmailService implements EmailService { @Autowired public JavaMailSender emailSender; @Override public void sendSimpleEmail(String toAddress, String subject, String message) { SimpleMailMessage simpleMailMessage = new SimpleMailMessage(); simpleMailMessage.setTo(toAddress); simpleMailMessage.setSubject(subject); simpleMailMessage.setText(message); emailSender.send(simpleMailMessage); } @Override public void sendEmailWithAttachment(String toAddress, String subject, String message, String attachment) throws MessagingException, FileNotFoundException { MimeMessage mimeMessage = emailSender.createMimeMessage(); MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true); messageHelper.setTo(toAddress); messageHelper.setSubject(subject); messageHelper.setText(message); FileSystemResource file = new FileSystemResource(ResourceUtils.getFile(attachment)); messageHelper.addAttachment("Purchase Order", file); emailSender.send(mimeMessage); } } package com.javadevjournal.controller;
import com.javadevjournal.email.service.EmailService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.mail.MailException; import org.springframework.web.bind.annotation.*; import javax.mail.MessagingException; import java.io.FileNotFoundException; @RestController @RequestMapping("/email") public class EmailController { private static final Logger LOG = LoggerFactory.getLogger(EmailController.class); @Autowired EmailService emailService; @GetMapping(value = "/simple-email/{user-email}") public @ResponseBody ResponseEntity sendSimpleEmail(@PathVariable("user-email") String email) { try { emailService.sendSimpleEmail(email, "Welcome", "This is a welcome email for your!!"); } catch (MailException mailException) { LOG.error("Error while sending out email..{}", mailException.getStackTrace()); return new ResponseEntity<>("Unable to send email", HttpStatus.INTERNAL_SERVER_ERROR); } return new ResponseEntity<>("Please check your inbox", HttpStatus.OK); } @GetMapping(value = "/simple-order-email/{user-email}") public @ResponseBody ResponseEntity sendEmailAttachment(@PathVariable("user-email") String email) { try { emailService.sendEmailWithAttachment(email, "Order Confirmation", "Thanks for your recent order", "classpath:purchase_order.pdf"); } catch (MessagingException | FileNotFoundException mailException) { LOG.error("Error while sending out email..{}", mailException.getStackTrace()); return new ResponseEntity<>("Unable to send email", HttpStatus.INTERNAL_SERVER_ERROR); } return new ResponseEntity<>("Please check your inbox for order confirmation", HttpStatus.OK); } } @SpringBootApplication
public class SendEmailUsingSpringApplication { public static void main(String[] args) { SpringApplication.run(SendEmailUsingSpringApplication.class, args); } } http://localhost:8080/email/order-email/umeshawasthi@www.javadevjournal.com
http://localhost:8080/email/simple-email/umeshawasthi@www.javadevjournal.com public abstract class AbstractEmailContext {
private String from; private String to; private String subject; private String email; private String attachment; private String fromDisplayName; private String emailLanguage; private String displayName; private String templateLocation; private Map <String, Object> context; //getter and seter methods }
package com.javadevjournal.core.email.service;
import com.javadevjournal.core.email.context.AbstractEmailContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Service; import org.thymeleaf.context.Context; import org.thymeleaf.spring5.SpringTemplateEngine; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import java.nio.charset.StandardCharsets; @Service public class DefaultEmailService implements EmailService { @Autowired private JavaMailSender emailSender; @Autowired private SpringTemplateEngine templateEngine; @Override public void sendMail(AbstractEmailContext email) throws MessagingException { MimeMessage message = emailSender.createMimeMessage(); MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED, StandardCharsets.UTF_8.name()); Context context = new Context(); context.setVariables(email.getContext()); String emailContent = templateEngine.process(email.getTemplateLocation(), context); mimeMessageHelper.setTo(email.getTo()); mimeMessageHelper.setSubject(email.getSubject()); mimeMessageHelper.setFrom(email.getFrom()); mimeMessageHelper.setText(emailContent, true); emailSender.send(message); } }
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"> <head> <meta charset="utf-8"> <!-- utf-8 works for most cases --> <meta name="viewport" content="width=device-width"> <!-- Forcing initial-scale shouldn't be necessary --> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- Use the latest (edge) version of IE rendering engine --> <meta name="x-apple-disable-message-reformatting"> <!-- Disable auto-scale in iOS 10 Mail entirely --> <title></title> <!-- The title tag shows in email notifications, like Android 4.4. --> <link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet"> <!-- CSS Reset : BEGIN --> </head> <body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;"> <center style="width: 100%; background-color: #f1f1f1;"> <div style="display: none; font-size: 1px;max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden; mso-hide: all; font-family: sans-serif;"> </div> <div style="max-width: 600px; margin: 0 auto;" class="email-container"> <!-- BEGIN BODY --> <table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="margin: auto;"> <tr> <td valign="top" class="bg_white" style="padding: 1em 2.5em 0 2.5em;"> <table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%"> <tr> <td class="logo" style="text-align: center;"> <h1>Welcome</h1> </td> </tr> </table> </td> </tr><!-- end tr --> <tr> <td valign="middle" class="hero bg_white" style="padding: 2em 0 4em 0;"> <table> <tr> <td> <div class="text" style="padding: 0 2.5em; text-align: center;"> <h2>Finish creating your account.</h2> <h3>Hi<p th:text="${firstName}"></h3> <h3>We're excited to have you get started. First, you need to confirm your account. Just press the button below.</h3> <p><a th:href="${verificationURL}" class="btn btn-primary">Validate Account</a></p> </div> </td> </tr> <tr> <td> <div class="text" style="padding: 0 2.5em; text-align: center;"> <h3>if you experience any issues with the button above, copy and paste the URL below into your web browser.</h3> <p th:text="${verificationURL}"></p> </div> </td> </tr> </table> </td> </tr><!-- end tr --> <!-- 1 Column Text + Button : END --> </table> <table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="margin: auto;"> <tr> <td valign="middle" class="bg_light footer email-section"> <table> <tr> <td valign="top" width="33.333%" style="padding-top: 20px;"> <table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"> <tr> <td style="text-align: left; padding-right: 10px;"> <h3 class="heading">About</h3> <p>Welcome to Java Development Journal Blog. We publish articles on Spring, Spring Boot and Spring Security. </p> </td> </tr> </table> </td> <td valign="top" width="33.333%" style="padding-top: 20px;"> <table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"> <tr> <td style="text-align: left; padding-left: 5px; padding-right: 5px;"> <h3 class="heading">Contact Info</h3> <ul> <li><span class="text">Java Development Journal</span></li> </ul> </td> </tr> </table> </td> <td valign="top" width="33.333%" style="padding-top: 20px;"> <table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"> <tr> <td style="text-align: left; padding-left: 10px;"> <h3 class="heading">Useful Links</h3> <ul> <li><a href="#">Home</a></li> <li><a href="#">About</a></li> </ul> </td> </tr> </table> </td> </tr> </table> </td> </tr><!-- end: tr --> </table> </div> </center> </body> </html> Перевод материала подготовили в преддверии старта курса онлайн-курса «Разработчик на Spring Framework».Приглашаем также всех желающих на открытый вебинар «Spring в Docker. Практические советы». На занятии мы рассмотрим всем известную тему по запуску Spring-приложений в Docker-контейнере и не всем известные решения возникающих задач.
=========== Источник: habr.com =========== =========== Автор оригинала: javadevjournal.com ===========Похожие новости:
Блог компании OTUS ), #_programmirovanie ( Программирование ), #_java |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 16:12
Часовой пояс: UTC + 5