@Controller
public class HomeController {
@Autowired
private JdbcTemplate jdbcTemplate;
@RequestMapping("/article/")
public String show(Model model) {
final String selectQuery = "select * from Article";
Map<?, ?> map = jdbcTemplate.queryForMap(selectQuery);
model.addAttribute("data", map.toString());
return "article";
}
}
実際にはControllerに全てを記述せずにモデル等を定義することが多いかと思います。
ここでは、Articleのオブジェクトを表すクラスを以下のように定義します。
package hayashier.mywebsite.model;
public class Article {
private Integer id;
private String title;
private String body;
private String path;
public Article() {
}
public Article(Integer id, String title, String body, String path) {
this.id = id;
this.title = title;
this.body = body;
this.path = path;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}
Mapperを定義します。
package hayashier.mywebsite.mapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import hayashier.mywebsite.model.Article;
public class ArticleMapper implements RowMapper<Article> {
public static final String BASE_SQL =
"SELECT a.id, a.title, a.body, a.path"
+ " FROM Article a";
@Override
public Article mapRow(ResultSet rs, int nowNum) throws SQLException {
Integer id = rs.getInt("id");
String title = rs.getString("title");
String body = rs.getString("body");
String path = rs.getString("path");
return new Article(id, title, body, path);
}
}
DAOを定義します。
package hayashier.mywebsite.dao;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import hayashier.mywebsite.mapper.ArticleMapper;
import hayashier.mywebsite.model.Article;
@Repository
@Transactional
public class ArticleDAO extends JdbcDaoSupport {
public ArticleDAO(DataSource dataSource) {
this.setDataSource(dataSource);
}
public List<Article> getArticles() {
String sql = ArticleMapper.BASE_SQL;
Object[] params = new Object[] {};
ArticleMapper mapper = new ArticleMapper();
List<Article> articles = this.getJdbcTemplate().query(sql, params, mapper);
return articles;
}
public Article getArticleFromPath(String path) {
String sql = ArticleMapper.BASE_SQL
+ " WHERE a.path = ?";
Object[] params = new Object[] { path };
ArticleMapper mapper = new ArticleMapper();
List<Article> articles = this.getJdbcTemplate().query(sql, params, mapper);
if (articles.size() > 0) {
return articles.get(0);
}
return new Article();
}
}
Controllerから以下のように使用することができる
@Controller
public class ListController {
@Autowired
private ArticleDAO articleDAO;
@RequestMapping("/list/{page_id}")
public ModelAndView list(@PathVariable int page_id) {
ArrayList<Article> articles = (ArrayList<Article>) articleDAO.getArticles();
MySQL上で以下のようにDDLを定義して、サンプルデータを挿入しておきます。
CREATE DATABASE IF NOT EXISTS `mywebsite` DEFAULT CHARACTER SET utf8mb4;
USE `mywebsite`;
DROP TABLE IF EXISTS Article;
CREATE TABLE Article (
id integer NOT NULL AUTO_INCREMENT,
title VARCHAR(255),
body LONGTEXT,
path VARCHAR(255),
PRIMARY KEY (id),
UNIQUE (path)
);
INSERT INTO Article (title, body, path) VALUES (
'test title',
'Test Body',
'test-path'
);
参考
設定ファイルを外部ファイル化
MySQLのホスト情報やユーザー名やパスワードを外部ファイル化しておきます。ファイルの場所は相対ディレクトリ指名やclasspath:,file:/// or file: が使用できます。
@Repository
@Transactional
public class ArticleCacheDAO {
// The purpose of this threshold is to prevent from not being able to get data
// caused by data loss event, for example, cache node failure or reboot
public final static int CACHE_FOR_THREAHOLD = 0;
@Autowired
RedisTemplate<String,Object> cacheTemplate;
@Resource(name="redisTemplate")
HashOperations<String,String,Article> hashOps;
private static final String KEY = "mywebsite:articles";
TimeUnit ARTICLE_EXPIRED_TIME_UNIT = TimeUnit.DAYS;
int ARTICLE_TIME_OUT = 24;
public Article getArticle(String path) {
return hashOps.get(KEY, path);
}
public List<Article> getAllArticles() {
return new ArrayList<Article>(hashOps.entries(KEY).values());
}
public void addArticle(Article article) {
hashOps.putIfAbsent(KEY, article.getPath(), article);
cacheTemplate.expire(KEY, ARTICLE_TIME_OUT, ARTICLE_EXPIRED_TIME_UNIT);
}
public void addArticles(List<Article> articles) {
for (Article article : articles) {
addArticle(article);
}
}
public long getNumberOfArticles() {
return hashOps.size(KEY);
}
}
Tomcatで稼働するWebサーバのルートディレクトリの場所の確認をおこないます。brew installからインストールした場合、/usr/local/Cellar/tomcat/9.0.34/libexec/webapps/のディレクトリ(9.0.34の部分は、tomcatで使用しているバージョン)となり、こちらに移動しておきます。上記ディレクトリはbrew ls tomcatコマンドで確認でき、webappsディレクトリ以下が実際にWebサーバーとして稼働させるデフォルトのルートディレクトリとなります。
Request processing failed; nested exception is org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [hayashier.mywebsite.model.Article]
4月 27, 2020 7:03:55 午後 org.apache.catalina.core.StandardWrapperValve invoke
重大: パス[]を持つコンテキスト内のサーブレット[mywebsite]のServlet.service() が例外[Handler processing failed; nested exception is java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/Config]が根本的要因と共に投げられました。
java.lang.ClassNotFoundException: javax.servlet.jsp.jstl.core.Config
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1365)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1188)
at org.springframework.web.servlet.support.JstlUtils.exposeLocalizationContext(JstlUtils.java:103)
at org.springframework.web.servlet.view.JstlView.exposeHelpers(JstlView.java:137)
at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:145)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:316)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1373)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1118)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:834)