在〈DataSource 設置〉中曾經看過,Spring Boot 可以自動注入 JdbcTemplate
,這也可以用來簡化 gossip 中的 AccountDAOJdbcImpl
以及 MessageDAOJdbcImpl
,後者其實就是〈DataSource 設置〉看過的程式碼,至於前者,可以如下修改:
package cc.openhome.model;
...略
@Repository
public class AccountDAOJdbcImpl implements AccountDAO {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void createAccount(Account acct) {
jdbcTemplate.update("INSERT INTO t_account(name, email, password, enabled) VALUES(?, ?, ?, 0)",
acct.getName(), acct.getEmail(), acct.getPassword());
jdbcTemplate.update("INSERT INTO t_account_role(name, role) VALUES(?, 'ROLE_MEMBER')",
acct.getName());
}
@Override
public Optional<Account> accountByUsername(String name) {
return jdbcTemplate.queryForList("SELECT * FROM t_account WHERE name = ?", name)
.stream()
.findFirst()
.map(row -> {
return new Account(
row.get("NAME").toString(),
row.get("EMAIL").toString(),
row.get("PASSWORD").toString()
);
});
}
@Override
public Optional<Account> accountByEmail(String email) {
return jdbcTemplate.queryForList("SELECT * FROM t_account WHERE email = ?", email)
.stream()
.findFirst()
.map(row -> {
return new Account(
row.get("NAME").toString(),
row.get("EMAIL").toString(),
row.get("PASSWORD").toString()
);
});
}
public void activateAccount(Account acct) {
jdbcTemplate.update("UPDATE t_account SET enabled = ? WHERE name = ?", 1, acct.getName());
}
@Override
public void updatePassword(String name, String password) {
jdbcTemplate.update("UPDATE t_account SET password = ? WHERE name = ?", password, name);
}
}
在舊版文件中看過 Spring 對 Mail 的簡化,提供了 MailSender
等 API,這也可以用來簡化 GmailService
,你只要在 application.properties 中刪掉原本自行設置的 Mail 等屬性並設置 spring.mail
等資訊:
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=yourname@gmail.com
spring.mail.password=yourpassword
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
就可以把 GmailService
簡化如下:
package cc.openhome.model;
...略
@Service
public class GmailService implements EmailService {
@Autowired
private JavaMailSender mailSender;
@Override
public void validationLink(Account acct) {
String link = String.format(
"http://localhost:8080/verify?email=%s&token=%s",
uriEncode(acct.getEmail()), uriEncode(acct.getPassword())
);
String anchor = String.format("<a href='%s'>驗證郵件</a>", link);
String html = String.format("請按 %s 啟用帳戶或複製鏈結至網址列:<br><br> %s", anchor, link);
sendMessage(acct.getEmail(), "Gossip 註冊結果", html);
}
@Override
public void failedRegistration(String acctName, String acctEmail) {
sendMessage(
acctEmail,
"Gossip 註冊結果",
String.format("帳戶申請失敗,使用者名稱 %s 或郵件 %s 已存在!", acctName, acctEmail)
);
}
@Override
public void passwordResetLink(Account acct) {
String link = String.format(
"http://localhost:8080/reset_password?name=%s&email=%s&token=%s",
uriEncode(acct.getName()),
uriEncode(acct.getEmail()),
uriEncode(acct.getPassword())
);
String anchor = String.format("<a href='%s'>重設密碼</a>", link);
String html = String.format("請按 %s 或複製鏈結至網址列:<br><br> %s", anchor, link);
sendMessage(
acct.getEmail(),
"Gossip 重設密碼",
html
);
}
private void sendMessage(String to, String subject, String text) {
MimeMessage message = mailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(message, false);
message.setContent(text, "text/html; charset=UTF-8");
helper.setTo(to);
helper.setSubject(subject);
helper.setSentDate(new Date());
mailSender.send(message);
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
private String uriEncode(String text) {
try {
return URLEncoder.encode(text, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
你可以在 gossip 中找到以上的範例專案。