2018.12.16 Supplement: In this article, it is created using "Tomcat project", but considering later, it is better to create it by "specifying maven-archetype-webapp
in Maven project ". (Or in a "dynamic web project")
reference
-Export project and war file when creating server-side Java in Eclipse -[Eclipse / Tomcat] Servlet + JSP in Maven webapp project
I don't know what number to brew, but I gnawed a little at the in-house introductory Java study session, so for review and preparation. (Also, I wonder if there is something to do when running a web application + DB application after building a little environment)
--Development environment is Pleiades Java Full Edition --MySQL is built separately-> Install MySQL 8.0 on Windows 10 with zip --Qiita --Java-MySQL connection uses Maven to install JDBC
Each version
Nowadays, it is developed using various frameworks, but I want to see what kind of implementation and processing is done in the primitive place, so here I am doing it with plain JSP + Servlet.
Create a Java | Tomcat project
The project name is memoapp
The context name is (default) / memoapp
This will create the project
Create a JSP file for the UI part. Select the JSP file from the Eclipse new menu.
Select WEB-INF / jsp
as the creation folder (otherwise it will be created by manually entering it)
The file name is easy to understand.
Select "New JSP file (html)" as the template
This will create a JSP file
Edit <title>
and add page title with <h1>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Memo App</title>
</head>
<body>
<h1>memo app</h1>
</body>
</html>
Create a Servlet class that processes data exchange with the created JSP.
The source at the time of automatic generation is only the class definition and there is no constructor, but doGet ()
is defined as follows. (Create a method that will be called when there is a GET request)
MemoAppMain.java
package jp.example.org;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/")
public class MemoAppMain extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String view = "/WEB-INF/jsp/index.jsp";
RequestDispatcher dispatcher = req.getRequestDispatcher(view);
dispatcher.forward(req, resp);
}
}
With doGet ()
, the JSP file in /WEB-INF/jsp/index.jsp
is read and the contents of the JSP are displayed on the browser using forward processing.
In addition, it seems that there are forward and redirect in the screen transition of Servlet: [Know the difference between redirect and forward: JavaTips ~ JSP / Servlet edition-@IT](http://www.atmarkit.co.jp/ait/ articles / 0407/06 / news077.html)
Now when you start Tomcat and "update the context definition", you should see the contents of the JSP when accessed from your browser.
This is usually an html form tag. Roughly like this.
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Memo App</title>
</head>
<body>
<h1>memo app</h1>
<form method="post">
<input type="text" name="title" size="50"/>
<br/>
<textarea rows="5" cols="80" name="memo"></textarea>
<br/>
<input type="submit"/>
</form>
</body>
</html>
Normally, the form tag uses the ʻaction` attribute to describe the destination of the input data, but this time it is omitted because it is made to post to itself.
When displayed (because there is no decoration), it looks like this. (I want to do something with Bootstrap ...)
Since I didn't write the action in the form described in JSP, the post destination is myself.
In other words, you can create a POST receiving process in the already created MemoAppMain
class.
MemoAppMain
hasdoGet ()
to process the created GET request, but createdoPost ()
to process the POST request in the same way.
For the time being, it looks like this
MemoAppMain.java
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
System.out.println("title: " + req.getParameter("title"));
System.out.println("memo: " + req.getParameter("memo"));
// --Save to DB here--
resp.sendRedirect(".");
}
This method is called when there is a POST request.
As the name suggests, the parameters (HTTP request) at POST are set in the req
object and can be accessed withgetParameter (String)
.
The "title" and "memo" of the character string specified by this getParameter (String)
are the character strings of the form name of the html form.
Right now, I'm only accessing the POSTed text data, so I'll create a process to save this in the DB.
setCharacterEncoding ("UTF-8");
is a measure against garbled characters.
Reference: Correspondence of Japanese parameters (setCharacterEncoding) --Getting request information --Introduction to Servlet
When the save process is finished, I call sendRedirect (". ");
To redirect the screen to myself and reload it.
Todo: Does not explain how to start / stop Tomcat and how the app works at this point.
Use MySQL.
Create a process to save the data entered in the form in DB. Before that, first set up JDBC to perform DB operations from a Java application.
JDBC settings (embedding the JDBC driver in the application) can be done manually, but here we will use Maven to install it.
Maven ... Gugu ♡
Select [Configuration]-> [Convert to Maven Project] from the right-click menu of the project.
The dialog for creating a new POM is displayed. Leave the default contents and click [Finish] OK
This will generate a pom.xml file (and a target
directory for output).
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>memoapp</groupId>
<artifactId>memoapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>WEB-INF/src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source/>
<target/>
</configuration>
</plugin>
</plugins>
</build>
</project>
Also, if you convert to Maven project, some settings such as JRE version and build destination will be rewritten, so fix it
In the [Source] tab of [Java Build Path] of the project properties, the "Default output folder" is [
After changing the default value, select the output folder of
Set the output folder setting to "project default output folder"
When you update the settings, you will be asked to confirm the deletion of the file before the change, so click [Yes] to delete it.
If an unfamiliar file is generated under work
, you can delete it as well.
Access the Maven repository with a browser and find the file you need.
Maven Repository: Search/Browse/Explore
This time, search with mysql jdbc
.
Then, [MySQL Connector / J] will be hit, so Open Link
https://mvnrepository.com/artifact/mysql/mysql-connector-java
When you open the link, the version list will be displayed, so basically select the same version as MySQL. This time, I am using MySQL 8.0.13, so select the same version.
A description example of the source is described at the link destination. Post the contents displayed on this [Maven] tab into <dependencies> ~ </ dependencies>
in the pom.xml
file of the project.
However, since the <dependencies>
tag does not exist in the initial state, such as immediately after conversion to a Maven project, enter it in the UI from the dependencies tab (either manually).
Enter the value displayed on the Maven site as shown below in the dependency selection dialog and press [OK].
And mysql-connector-java will be added, so save the file.
At the same time as saving, the necessary files are downloaded and the build is started, and when the build is completed, the project configuration also adds files such as "Maven dependency".
At this point, the contents of pom.xml look like this
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>memoapp</groupId>
<artifactId>memoapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>WEB-INF/src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source/>
<target/>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
</dependencies>
</project>
Create DB and user to be used in application. This is done on MySQL, regardless of Tomcat or Java.
C:\Users\zaki>mysql -u root -p
Enter password: ********
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.13 MySQL Community Server - GPL
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
mysql> create database memoapp_db;
Query OK, 1 row affected (0.06 sec)
mysql> create user memoapp identified by "memoapp";
Query OK, 0 rows affected (0.13 sec)
mysql> grant all on memoapp_db.* to memoapp;
Query OK, 0 rows affected (0.03 sec)
mysql>
// --Save to DB here--
Connection con = null;
Statement smt = null;
String url = "jdbc:mysql://localhost:3306/memoapp_db";
String user = "memoapp";
String pass = "memoapp";
try {
con = DriverManager.getConnection(url, user, pass);
smt = con.createStatement();
System.out.println("smt: " + smt);
} catch (SQLException e) {
e.printStackTrace();
}
finally {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
// --DB processing up to here--
Now when I try to register data from form, an exception occurs
java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/memoapp_db
at java.sql.DriverManager.getConnection(DriverManager.java:689)
at java.sql.DriverManager.getConnection(DriverManager.java:247)
at jp.example.org.MemoAppMain.doPost(MemoAppMain.java:44)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
:
:
This is not a problem because the JDBC jar file introduced by Maven can be referenced at the build timing on Eclipse, but the path of the JDBC jar file is not set when executing with Tomcat.
If you check [Use SMART! Maven classpath] on the "Development class loader classpath" screen of Tomcat settings in the project properties, Maven libraries will also be referenced when Tomcat is executed ...?
I thought, but tomcat got an error and memoapp doesn't work
Serious: Begin event threw exception [Sat 12 01 13:38:19 JST 2018]
Serious: Parse error in context.xml for /memoapp [Sat 12 01 13:38:19 JST 2018]
Serious:Occurred in row 126, column 2[Sat 12 01 13:38:19 JST 2018]
Serious:Mark this application as unavailable due to a previous error[Sat 12 01 13:38:19 JST 2018]
Serious: One or more components marked the context as not correctly configured [Sat 12 01 13:38:19 JST 2018]
Serious:Context launch failed due to previous error[/memoapp] [Sat 12 01 13:38:19 JST 2018]
By the way, if you make this setting and update the context definition, memoapp.xml looks like this
memoapp.xml
<Context path="/memoapp" reloadable="true" docBase="C:\Users\zaki\src\2018b-java-study\memoapp" workDir="C:\Users\zaki\src\java-study\memoapp\work" >
<Loader className="org.apache.catalina.loader.DevLoader" reloadable="true" debug="1" useSystemClassLoaderAsParent="false" />
</Context>
When I looked it up, I found some information that "Rename and copy the DevLoader.zip
file included in the Tomcat plugin to jar to TOMCAT_HOME / server / lib ".
-[eclipse] DevLoader Trap: Hinapo's Technical Memo -Debugging the Maven project-Pika breeding diary -Tomcat doesn't work in Eclipse !! --QA @ IT
In Eclipse Tomcat Plugin 9.13 as of December 2018, the DevLoader.zip file is not included directly, but in the net.sf.eclipse.tomcat_9.1.3.jar
file (hard to understand!)
Since the jar file is actually a zip file, rename the extension, expand it, and open the DevloaderTomcat7.jar
inside ... that? Is there only Tomcat7?
When I actually used this file, it didn't work on Tomcat 8.
Serious: Begin event threw error [Sat 12 01 14:48:25 JST 2018]
Serious: ContainerBase.addChild: start: [Sat 12 01 14:48:25 JST 2018]
Serious:Configuration descriptor C:\pleiades\pleiades\tomcat\8\conf\Catalina\localhost\memoapp.Error deploying xml[Sat 12 01 14:48:25 JST 2018]
There seems to be no necessary file in the Tomcat plug-in of Eclipse, so download it from the net.
https://sourceforge.net/projects/tomcatplugin/files/additional/ ↑ It doesn't happen ... So from here. https://github.com/his-eg/tomcatplugin/blob/master/net.sf.eclipse.tomcat/DevLoaderTomcat8.jar
Copy this file to Tomcat's lib directory. (For Pleiades, around pleiades \ tomcat \ 8 \ lib \ DevloaderTomcat7.jar
)
Now if I restart tomcat it should work ... but I still get the same error
java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/memoapp_db
(Imagine) This error fails DriverManager.getConnection ()
which cannot be executed without the jdbc jar because DevLoader has not determined which class to load at the time of execution.
So just before that, you can load the jdbc jar.
Then do Class.forName ("com.mysql.cj.jdbc.Driver ");
// --Save to DB here--
Connection con = null;
Statement smt = null;
//String url = "jdbc:mysql://localhost:3306/memoapp_db?useSSL=false&useUnicode=true&serverTimezone=UTC";
String url = "jdbc:mysql://localhost:3306/memoapp_db";
String user = "memoapp";
String pass = "memoapp";
try {
Class.forName("com.mysql.cj.jdbc.Driver");
con = DriverManager.getConnection(url, user, pass);
smt = con.createStatement();
System.out.println("smt: " + smt);
} catch (SQLException | ClassNotFoundException e) {
e.printStackTrace();
}
finally {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
// --DB processing up to here--
So the code of the DB connection part looks like this.
Note that the class name of the argument of forName ()
that often appears in the sample code is "com.mysql.cj.jdbc.Driver" because FQCN has been changed in the current version (cj has been added). Teru)
I also had to add the development classloader classpath, ʻorg.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER`.
As an aside, it took a week to reach the completion of the DB connection where ...
mysql-connector-java-8.0.13.jar
and protobuf-java-3.6.1.jar
directly under the lib
directory for the Tomcat library, the settings on the Eclipse side will be changed. It works without anything.Click here for a brief summary of MySQL operations. [(Loose and updated) MySQL / SQL memo](Qiita https://qiita.com/zaki-lknr/items/4d330b64e1d8cdd9ce59)
Simple because it is a sample
field | type | size | not null | comment | etc |
---|---|---|---|---|---|
memo_id | int | 11 | ✓ | ID | auto_increment |
category | int | 11 | category | ||
title | varchar | 64 | title | ||
memo | text | Note | |||
create_date | datetime | Created date | |||
modified_date | datetime | Update date |
Create SQL to create table
create table if not exists memo_data (
memo_id INT(11) auto_increment not null comment 'ID',
category INT(11) comment 'category',
title VARCHAR(64) comment 'title',
memo TEXT comment 'Note',
create_date DATETIME comment 'Created date',
modified_date DATETIME comment 'Update date',
primary key (memo_id)
)
Java code to create the table (although a bit appropriate)
con = DriverManager.getConnection(url, user, pass);
smt = con.createStatement();
System.out.println("smt: " + smt);
String create_table = "create table if not exists memo_data (" +
"memo_id INT(11) auto_increment not null comment 'ID'," +
"category INT(11) comment 'category'," +
"title VARCHAR(64) comment 'title'," +
"memo TEXT comment 'Note'," +
"create_date DATETIME comment 'Created date'," +
"modified_date DATETIME comment 'Update date'," +
"primary key (memo_id)" + ")";
// create table
smt.executeUpdate(create_table);
Now run it and the table will be created
mysql> show tables;
+----------------------+
| Tables_in_memoapp_db |
+----------------------+
| memo_data |
+----------------------+
1 row in set (0.01 sec)
mysql> describe memo_data;
+---------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+-------------+------+-----+---------+----------------+
| memo_id | int(11) | NO | PRI | NULL | auto_increment |
| category | int(11) | YES | | NULL | |
| title | varchar(64) | YES | | NULL | |
| memo | text | YES | | NULL | |
| create_date | datetime | YES | | NULL | |
| modified_date | datetime | YES | | NULL | |
+---------------+-------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
mysql>
Create a process to save the form input data that can be referenced by req.getParameter ("title ")
and req.getParameter ("memo ")
in the method of doPost ()
in the table.
String form_title = req.getParameter("title");
String form_memo = req.getParameter("memo");
And get it in a variable, and the INSERT statement looks like the following.
insert into memo_data (
category, title, memo, create_date, modified_date
) values (
0,
form_title,
form_memo,
cast(now() as datetime),
cast(now() as datetime)
);
Java code to save records
con = DriverManager.getConnection(url, user, pass);
smt = con.createStatement();
String form_title = req.getParameter("title");
String form_memo = req.getParameter("memo");
System.out.println("title: " + form_title);
System.out.println("text: " + form_memo);
String insert_memo = "insert into memo_data (" +
"category, title, memo, create_date, modified_date" +
") values (" +
"0," +
"'" + form_title + "'," +
"'" + form_memo + "'," +
"cast(now() as datetime)," +
"cast(now() as datetime) " +
");";
//Record save
smt.executeUpdate(insert_memo);
Now when you enter text from the browser and submit, the contents will be saved in the DB.
(It's hard to see because of line breaks) Like this
mysql> select * from memo_data;
+---------+----------+--------+----------------------------+---------------------+---------------------+
| memo_id | category | title | memo | create_date | modified_date |
+---------+----------+--------+----------------------------+---------------------+---------------------+
| 1 | 0 |shopping| -curry
-Easy
-Niku| 2018-12-02 09:52:07 | 2018-12-02 09:52:07 |
+---------+----------+--------+----------------------------+---------------------+---------------------+
1 row in set (0.00 sec)
mysql>
Create a process to display the last saved memo data on the screen.
Since it is displayed, the location is executed with doGet ()
.
The column to be displayed for the time being
--Title --Memo --Updated
With three.
First, the SELECT statement
select title, memo, modified_date from memo_data;
Unlike create and insert, Java source also creates a process to receive the execution result.
con = DriverManager.getConnection(url, user, pass);
smt = con.createStatement();
String select_memo = "select title, memo, modified_date from memo_data;";
ResultSet result = smt.executeQuery(select_memo);
while (result.next()) {
System.out.println("title: " + result.getString("title"));
System.out.println("memo: " + result.getString("memo"));
System.out.println("modify: " + result.getString("modified_date"));
}
Record information can now be obtained. Next, pass the memo data retrieved from the DB to the screen (JSP).
This time, create a process to pass data from Servlet to JSP (refer to the value received from Servlet in JSP).
First, the result of ʻexecuteQuery ()` cannot be used after the Connection is closed, so create a variable for passing and copy the record information into it.
ArrayList<HashMap<String, String>> record_list = new ArrayList<>();
//Omission
ResultSet result = smt.executeQuery(select_memo);
while (result.next()) {
HashMap<String, String> record = new HashMap<>();
record.put("title", result.getString("title"));
record.put("memo", result.getString("memo"));
record.put("modified_date", result.getString("modified_date"));
record_list.add(record);
}
Then, in order to pass this record_list
to JSP, set the value in the request variable of Servlet withsetAtribute ()
(like HashMap, you can pass the data structure in key-value format).
req.setAttribute("record_list", record_list);
String view = "/WEB-INF/jsp/index.jsp";
RequestDispatcher dispatcher = req.getRequestDispatcher(view);
dispatcher.forward(req, resp);
Now you can refer to it in JSP with the key name record_list
The value set by setAttribute (KEY)
in Servlet can be retrieved by request.getAttribute (KEY)
.
ArrayList<HashMap<String, String>> list = (ArrayList<HashMap<String, String>>) request.getAttribute("record_list");
After taking it out, it is output in html format in the same way as normal Java coding.
Iterator<HashMap<String, String>> i = list.iterator();
while (i.hasNext()) {
HashMap map = i.next();
out.println("<hr/>");
out.println("<div>" + map.get("title") + "</div>");
out.println("<div>" + map.get("modified_date") + "</div>");
out.println("<div>" + ((String) map.get("memo")).replace("\n", "<br/>") + "</div>");
}
I need an import statement first
<%@page import="java.util.Iterator"%>
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.HashMap"%>
The whole source looks like this
<%@page import="java.util.Iterator"%>
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.HashMap"%>
<%@page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Memo App</title>
</head>
<body>
<h1>Memo app</h1>
<form method="post">
<input type="text" name="title" size="50" /> <br />
<textarea rows="5" cols="80" name="memo"></textarea>
<br /> <input type="submit" />
</form>
<%
ArrayList<HashMap<String, String>> list = (ArrayList<HashMap<String, String>>) request
.getAttribute("record_list");
Iterator<HashMap<String, String>> i = list.iterator();
while (i.hasNext()) {
HashMap map = i.next();
out.println("<hr/>");
out.println("<div>" + map.get("title") + "</div>");
out.println("<div>" + map.get("modified_date") + "</div>");
out.println("<div>" + ((String) map.get("memo")).replace("\n", "<br/>") + "</div>");
}
%>
</body>
</html>
Screen display
I managed to view and save it.
--Because the DB server address specification is hard-coded, rebuilding is required every time the environment changes.
-XML file definition of database connection setting using JNDI
--SQL injection measures
--Using placeholders
--Creating a war file to run in a non-local environment
--Maybe the world of Eclipse operation
--Related information: Export project and war file when creating server-side Java in Eclipse
--Eclipse
--CLI build
--If you have a directory structure created as a Maven project, for example, in Debian Linux, if you put maven
with apt, you can create a war file by executing mvn package
in the directory with pom.xml
.
-Reference because the source has been uploaded to GitHub
――Is it IDEA after all?
--DB initialization process
--JPA (Java Persistence API)
--Classify DB processing properly
--The idea of DAO
――To put it plainly, by implementing data input / output operations separately in separate classes, for example, even if the DB changes to Postgres, the change on the caller side is minimized, which is often done with commercial code.
-DAO side source example (GitHub)
-Caller Source Changes (GitHub)
--Servlet-> Write JSP data transfer a little more beautifully
--Use JavaBeans: Simplify writing JSP / Servlet with JavaBeans and JSTL
――Can you write the display part of the loop a little more beautifully?
--In JSTL core tag library for Each: Simplify writing JSP / Servlet with JavaBeans and JSTL
--Framework support
--Spring
--Login or session
--The appearance of the screen
--Bootstrap ...
Recommended Posts