Spring 01
Springのホームページ
pom.xml (Project Object Model)
Modelがこのページにもらえます。もらったら、pom.xmlに貼り付けます。
web.xml
どちらのcontrollerで実行するのは、web.xmlで決めます。
src/main/java
プロジェクトのビジネス ロジック プログラムなどの一般的なコードを配置するために使用される所です。
src/main/resources
property、xml、profileなどのstatic resourceを配置するために使用される所です。
src/test/java
単体test codeなどのtest codeを配置するために使用される所です。
・Spring MVC
(1)DispatcherServlet
フロントコントローラーです。全てのリクエストはDispatcherServletを通して配信され、対応するhandlerに配信されます。
(2)HandlerMapping
要求リンクを解析して、要求リンクに基づいて要求を実行したクラス(HandlerMappingというハンドラー)を見つけます。
(3)HandlerAdapter
使用者からのリクエストによってメソッドを呼んで、処理します。
(4)Controller
Controllerは使用者のリクエストを処理して、Controllerが終わったら、DispatcherServletにModelとViewのオブジェクトを渡します。
他の角度で見たら、DispatcherServletはWebアプリケーション全体のコントローラーです。Controllerは単一のHttp要求処理におけるコントローラーです。
(5)ViewResolver
Viewを解析し、View内の論理名を実際のViewオブジェクトに変更します。
(6)Model
アプリケーションデータ、ビジネスルール、ロジック、関数などです。
(7)Service
ビジネスロジックの処理、処理された結果のControllerへの返却、またはDAOの呼び出しによるデータベースへの格納を担当します。
ログイン画面(DataBaseなし)
(pom.xml)
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
(web.xml)
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value> <!-- Spring Security's setting file is change to classpath(applicationContxt.xml) -->
</context-param>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
(applicationContext.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<security:http auto-config='true'>
<security:intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')"/>
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="matt" password="matt" authorities="ROLE_ADMIN"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans:beans>
プログラミング中、あった問題 14
・JSPがクラスから直接にメソッドを呼びます。
クラス名.メソッド名();
・メソッドを呼ぶ時、値をもらいます。
value=クラス名.メソッド名();
・メソッドを呼ぶ時、staticで定義します。
public static データ型 メソッド名
・メソッドがstaticで定義したら、エラーになります。
原因は同じクラスの変数を使っています。
結論:JSPがクラスからメソッドを呼べません。
・新しいメソッドを作ります。
public static データ型 メソッド名
・新しいメソッドが既存の値をもらう方法
(既存の値はDataBaseからもらった値です。)
メソッドを呼ぶ時、値を入れます。
クラス名.メソッド名(値);
・どこから入れる値をもらいます。
JSP
String 変数名 = (String) request.getAttribute("変数名");
クラス名.メソッド名(値);
Beans
クラス名.メソッド名(値);
結論:JSPで値を渡すなら、一度Beansから値をもらうことが必要です。
Beansで渡すなら、新しいメソッドは何を処理したほうがいいですか?
そして、JSPは同じBeansから値をもらいます。
新しいメソッドを作ることが必要ないと思います。
・値をもらう方法
String 変数名 = (String) request.getAttribute("変数名");
・上記の方法でメソッドをもらいます。
できないと思います。
・複数メソッドを作ります。
コードが長くなって、値も一つ一つもらいます。
結論:明確に特定の値を処理するのはいいですが、似ているメソッドが存在するのは必要ないと思います。
配列の配列
複数の配列をまとめることができます。
しかし、デバッグで検査する時、配列は長くなります。
この問題について、新しい変数を作って、
何番目の配列を指定するなら、検査することが簡単になります。
ArrayList<ArrayList<String>> 配列名 = new ArrayList<>();
配列名.add(配列1);
配列名.add(配列2);
配列名.add(配列3);
配列名.get(0);
結論:JSPで新しい変数を定義することが必要ないです。
以前はBeansとJSPが新しい変数を追加しなければなりません。
今はBeansで新しい変数を作って、JSPでその配列を指定すると、結果を出ます。
・Spring Frameworkとは
フレームワークは自身で実行することができません。開発者のコードと一緒にのは完全なアプリケーションです。フレームワークは共通のプログラムをまとめので、再利用するのは可能です。フレームとは枠です。開発者たちがこの枠の下にプログラミングします。枠に開発のスビートが早くて、開発者のコードも一致性が高いです。将来に修正することが簡単になります。しかし、フレームワークの仕様要件を超えるなら(拡充機能がない場合)、修正することが難しくなります。本来、フレームワークの自体が制限であることです。
・Frameworkの利点
変更に強い
テストが簡単
拡張性が高い
保守性が高い
再利用性が高い
プログラミング中、あった問題 13
・JSPにArraylistをもらう方法
ArrayList<String> todo_text1 = (ArrayList<String>)request.getAttribute("todo_text1");
警告があるですが、使えます。
警告:unchecked cast from object to Arraylist<String>
・ループ
問題:複数のArraylistが一つループにプリントしたい場合は、どちら方法は一番いいです?
1.愚直な方法(For)
for(int i = 0; i < list.size(); ++i){
String s = list.get(i);
System.out.println(s);
}
2.Iterator(イテレータ)(For)
for(Iterator<String>itr = list.iterator(); itr.hasNext();){
String s = itr.next();
System.out.println(s);
}
3.拡張for文
for(String s : list){
System.out.println(s);
}
4.ラムダ
list.forEach(s -> {
System.out.println(s);
});
5. ラムダだが、メソッド参照
list.forEach(System.out::println);
6.愚直な方法(while)
int j = 0;
while (list.size() > j) {
System.out.println(list.get(j));
j++;
}
7.Iterator(イテレータ)(while)
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
自分の結論:3番の方法を使うなら、一つArraylistしか使えません。イテレータなら、同じ問題だと思います。1番と6番なら、簡単ですが、ループの中にコードがわかりやすいと思います。
(3番)
int i = 0;
for(String result : list01){
System.out.println(result); <-list02と使い方は違います。。
System.out.println(list02.get(i));
i++;
}
(6番)
int i = 0;
while(list01.size() > i){
System.out.println(list01.get(i)); <-list02と使い方は同じです。
System.out.println(list02.get(i));
i++;
}
プログラミング中、あった問題 12
・print_todo機能をまとめました。
実行方法:encodeの部分がSQLの部分に遷移しました。
・edit_todo.jspにもらった値をを二回でエンコードしました。
UserBeansから戻る値の部分を修正しました。
public String getId_edit() {
return id;
}
public void setId_edit(String id) {
this.id = id;
}
public String getPassword_edit() {
return password;
}
public void setPassword_edit(String password) {
this.password = password;
}
・Encode機能を共通関数にします。
package user_todo;
public class CommonBeans {
public static String EscapeHTMLCharacter(String original) {
String newString = original;
newString = newString.replaceAll("(?i)(&)", "&");
newString = newString.replaceAll("(?i)(')", "'");
newString = newString.replaceAll("(?i)(\")", """);
newString = newString.replaceAll("(?i)(<)", "<");
newString = newString.replaceAll("(?i)(>)", ">");
return newString;
}
public static String EscapeSQLCharacter(String original) {
String newString = original;
newString = newString.replaceAll("(?i)(')", "''");
return newString;
}
}
使い方:CommonBeans.EscapeHTMLCharacter(userid);
・MVC
モデル(Model):データを保存する場所です。
ビュー(View):結果が表示されます。
コントローラ(Controller):データを処理する場所です。
・UserServletsとTodoServletを作成しました。
BeansのSQL指令をServletに遷移しました。
UserServlet
public class UserServlet {
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(timestamp);
// Add New Account
public static String add_user(String id, String password) {
id = EscapeCharacter.EscapeSQLCharacter(id);
password = EscapeCharacter.EscapeSQLCharacter(password);
String sql = "insert into user(user_id, password) values ('" + id + "','" + password + "')";
return sql;
}
// Delete Account
public static String delete_user(String id) {
id = EscapeCharacter.EscapeSQLCharacter(id);
String sql = "delete from user where user_id=('" + id + "')";
return sql;
}
// Delete user todo
public static String delete_user_todo(String id) {
id = EscapeCharacter.EscapeSQLCharacter(id);
String sql = "delete from todo where user_id=('" + id + "')";
return sql;
}
// Change Password
public static String change_password(String id, String password) {
id = EscapeCharacter.EscapeSQLCharacter(id);
password = EscapeCharacter.EscapeSQLCharacter(password);
String sql = "UPDATE user SET password ='" + password + "' WHERE user_id = '" + id + "'";
return sql;
}
// Select user
public static StringBuffer select_user(String id,String password) {
id = EscapeCharacter.EscapeSQLCharacter(id);
password = EscapeCharacter.EscapeSQLCharacter(password);
StringBuffer sql = new StringBuffer();
sql.append("select * from user where user_id = '" + id + "' and password = '" + password + "'");
return sql;
}
// Account Login Verification
public static StringBuffer verification_user(String id) {
StringBuffer sql = new StringBuffer();
sql.append("SELECT `todo_id`,`todo_text`,`finished`,`upload_date` FROM `todo` WHERE user_id = '" + id + "'");
return sql;
}
// Select user_todo
public static StringBuffer select_todo(String id) {
StringBuffer sql = new StringBuffer();
id = EscapeCharacter.EscapeSQLCharacter(id);
sql.append("SELECT `todo_id`,`todo_text`,`finished`,`upload_date` FROM `todo` WHERE user_id = '" + id + "'");
return sql;
}
// Date_type_convert
public static String date_convert(String upload_date) {
upload_date = upload_date.replaceFirst("(?i)(-)", "年");
upload_date = upload_date.replaceFirst("(?i)(-)", "月");
upload_date = upload_date.replaceFirst("(?i)( )", "日");
upload_date = upload_date.substring(0, 16);
int YEAR = Integer.parseInt(upload_date.substring(0, 4));
int MONTH = Integer.parseInt(upload_date.substring(5, 7));
int DATE = Integer.parseInt(upload_date.substring(8, 10));
MONTH = MONTH - 1;
DATE = DATE - 1;
String week = new String[7];
week[0] = "日";
week[1] = "月";
week[2] = "火";
week[3] = "水";
week[4] = "木";
week[5] = "金";
week[6] = "土";
Calendar YEAR_MONTH_DATE = Calendar.getInstance();
YEAR_MONTH_DATE.set(Calendar.YEAR, YEAR);
YEAR_MONTH_DATE.set(Calendar.MONTH, MONTH);
YEAR_MONTH_DATE.set(Calendar.DAY_OF_MONTH, DATE);
int DAY_OF_WEEK = YEAR_MONTH_DATE.get(Calendar.DAY_OF_WEEK);
upload_date = upload_date.substring(5, 11) + "(" + week[DAY_OF_WEEK] + ")" + upload_date.substring(11, 16);
return upload_date;
}
TodoServlet
public class TodoServlet {
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(timestamp);
// Add Todo
public static String add_todo(String id, String data, String time) {
id = EscapeCharacter.EscapeSQLCharacter(id);
data = EscapeCharacter.EscapeSQLCharacter(data);
String sql = "INSERT INTO `company_db`.`todo` (`user_id`, `todo_text`, `finished`, `created_date`, `upload_date`) VALUES ('"
+ id + "', '" + data + "', '0', '" + time + "', '" + time + "')";
return sql;
}
// Delete Todo
public static String delete_todo(String todo_array) {
String todo_str = EscapeCharacter.EscapeSQLCharacter(todo_array);
String sql = "DELETE FROM `company_db`.`todo` WHERE `todo_id`='" + todo_str + "'";
return sql;
}
// UPDATE Todo
public static String edit_todo(String todoid, String data, String time) {
todoid = EscapeCharacter.EscapeSQLCharacter(todoid);
data = EscapeCharacter.EscapeSQLCharacter(data);
String sql = "UPDATE `todo` SET `todo_text` ='" + data + "',`upload_date` ='" + time + "' WHERE `todo_id` = '"
+ todoid + "'";
return sql;
}
// Select user_todo
public static StringBuffer select_todo(String id) {
StringBuffer sql = new StringBuffer();
id = EscapeCharacter.EscapeSQLCharacter(id);
sql.append("SELECT `todo_id`,`todo_text`,`finished`,`upload_date` FROM `todo` WHERE user_id = '" + id + "'");
return sql;
}
// Date_type_convert
public static String date_convert(String upload_date) {
upload_date = upload_date.replaceFirst("(?i)(-)", "年");
upload_date = upload_date.replaceFirst("(?i)(-)", "月");
upload_date = upload_date.replaceFirst("(?i)( )", "日");
upload_date = upload_date.substring(0, 16);
int YEAR = Integer.parseInt(upload_date.substring(0, 4));
int MONTH = Integer.parseInt(upload_date.substring(5, 7));
int DATE = Integer.parseInt(upload_date.substring(8, 10));
MONTH = MONTH - 1;
DATE = DATE - 1;
String week = new String[7];
week[0] = "日";
week[1] = "月";
week[2] = "火";
week[3] = "水";
week[4] = "木";
week[5] = "金";
week[6] = "土";
Calendar YEAR_MONTH_DATE = Calendar.getInstance();
YEAR_MONTH_DATE.set(Calendar.YEAR, YEAR);
YEAR_MONTH_DATE.set(Calendar.MONTH, MONTH);
YEAR_MONTH_DATE.set(Calendar.DAY_OF_MONTH, DATE);
int DAY_OF_WEEK = YEAR_MONTH_DATE.get(Calendar.DAY_OF_WEEK);
upload_date = upload_date.substring(5, 11) + "(" + week[DAY_OF_WEEK] + ")" + upload_date.substring(11, 16);
return upload_date;
}
プログラミング中、あった問題 11
・変数名error_statusがerror_message01に変更しました。
以前
String error_status = (String) request.getAttribute("error_status");
String error_message = (String) request.getAttribute("error_message");
現在
String error_message01 = (String) request.getAttribute("error_message01");
String error_message02 = (String) request.getAttribute("error_message02");
・バグ:記号アカウントのTodo一覧画面のディスプレイ機能は失効しました。
問題点:値を渡す方法は問題があります。
推測原因:Encodeの機能は不完全です。
原因:SQLの値が変わりました。。
解決方法:不要なコードを削除しました。
id = id.replaceAll("(?i)(')", "''");
・バグ:編集機能と削除機能が失効しまいました。
問題点:Encodeは不完全です。
解決方法:デバッグで一つ一つを修正しました。
悪い点:コードは読みづらいです。
以前のEncodeメソッドを削除しました。
public Boolean Encode(){
id = id.replaceAll("(?i)(&)", "&");
id = id.replaceAll("(?i)(')", "'");
id = id.replaceAll("(?i)(\")", """);
id = id.replaceAll("(?i)(<)", "<");
id = id.replaceAll("(?i)(>)", ">");
password = password.replaceAll("(?i)(&)", "&");
password = password.replaceAll("(?i)(')", "'");
password = password.replaceAll("(?i)(\")", """);
password = password.replaceAll("(?i)(<)", "<");
password = password.replaceAll("(?i)(>)", ">");
return true;
}
ModeServletにModeによって指定のメソッドを実行します。
if (result == true && mode.equals("user_verification")
||result == true && mode.equals("add_Todo_database")
||result == true && mode.equals("delete_Todo_database")){
userid = userid.replaceAll("(?i)(&)", "&");
userid = userid.replaceAll("(?i)(')", "'");
userid = userid.replaceAll("(?i)(\")", """);
userid = userid.replaceAll("(?i)(<)", "<");
userid = userid.replaceAll("(?i)(>)", ">");
userpassword = userpassword.replaceAll("(?i)(&)", "&");
userpassword = userpassword.replaceAll("(?i)(')", "'");
userpassword = userpassword.replaceAll("(?i)(\")", """);
userpassword = userpassword.replaceAll("(?i)(<)", "<");
userpassword = userpassword.replaceAll("(?i)(>)", ">");
if(mode.equals("user_verification")) {
request.setAttribute("id", userid);
request.setAttribute("password", userpassword);
user.print_todo(request, response);
}
if(mode.equals("add_Todo_database")) {
request.setAttribute("id", userid);
request.setAttribute("password", userpassword);
todo.print_todo(request, response);
}
if(mode.equals("delete_Todo_database")) {
request.setAttribute("id", userid);
request.setAttribute("password", userpassword);
todo.todo_delete_back(request, response);
}
}
else if(result == true && mode.equals("edit_Todo_database")){
request.setAttribute("id", userid);
request.setAttribute("password", userpassword);
todo.todo_edit_back(request, response);
}
・バグに対応して、コードを修正しました。
public Boolean print_todo(HttpServletRequest request, HttpServletResponse response) {
try {
ResultSet rset = null;
conn = ds.getConnection();
StringBuffer sql = new StringBuffer();
//赤いところは各機能のバグによって修正した部分です。
id = id.replaceAll("(?i)(&)", "&");
id = id.replaceAll("(?i)(')", "'");
id = id.replaceAll("(?i)(")", "\"");
id = id.replaceAll("(?i)(<)", "<");
id = id.replaceAll("(?i)(>)", ">");
password = password.replaceAll("(?i)(&)", "&");
password = password.replaceAll("(?i)(')", "'");
password = password.replaceAll("(?i)(")", "\"");
password = password.replaceAll("(?i)(<)", "<");
password = password.replaceAll("(?i)(>)", ">");
id = id.replaceAll("(?i)(')", "''");
sql.append("SELECT `todo_id`,`todo_text`,`finished`,`upload_date` FROM `todo` WHERE user_id = '" + id + "'");
System.out.println(sql);
pstmt = conn.prepareStatement(new String(sql));
pstmt.execute();
rset = pstmt.executeQuery();
request.setAttribute("print", rset);
request.getRequestDispatcher("/member.jsp").forward(request, response);
rset.close();
pstmt.close();
conn.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
conn.close();
} catch (Exception e) {
}
}
}
・Todo.jspにキャンセルボタンが失効しました。
問題点:値を二回でエンコードしました。
解決方法:もう一度文字列を置換して、正常な値を戻します。
<%
userid = userid.replaceAll("(?i)(&)", "&");
userpassword = userpassword.replaceAll("(?i)(&)", "&");
%>
・日時機能をServletに遷移する方法がわかりません。
member.jspにResultSetで定義した値をもらって、JSPに値をStringで変換して、結果が表示されます。
私ができると思う方法はResultSetで定義した値を変わります。しかし、この方法で実行すると、DataBaseの値も変わります。
・ArrayでResultSetの型から値を変換します。
実行方法:日時機能がBeansに遷移しました。そして、arrayで値をもらって、member.jspに渡します。
問題点:arrayの長さは定義しなければなりません。しかし、whileでDataBaseからもらって、いくつの資料がわかりません。ループが終わった前に、長さがわかることができません。もし、arrayの中にnullがあるなら、ページが真白になってしまいました。
//赤いところは問題点
String array_todo_text = new String[2];
String array_upload_date = new String[2];
String array_todo_id = new String[2];
int counter = 0;
while (rset.next()) {
String todo_text = rset.getString("todo_text");
todo_text = todo_text.replaceAll("(?i)(&)", "&");
todo_text = todo_text.replaceAll("(?i)(')", "'");
todo_text = todo_text.replaceAll("(?i)(\")", """);
todo_text = todo_text.replaceAll("(?i)(<)", "<");
todo_text = todo_text.replaceAll("(?i)(>)", ">");
array_todo_text[counter]=todo_text;
String upload_date = rset.getString("upload_date");
upload_date = upload_date.replaceFirst("(?i)(-)", "年");
upload_date = upload_date.replaceFirst("(?i)(-)", "月");
upload_date = upload_date.replaceFirst("(?i)( )", "日");
upload_date = upload_date.substring(0,16);
int YEAR = Integer.parseInt(upload_date.substring(0,4));
int MONTH = Integer.parseInt(upload_date.substring(5,7));
int DATE = Integer.parseInt(upload_date.substring(8,10));
MONTH = MONTH-1;
DATE = DATE-1;
String week = new String[7];
week[0] = "日";
week[1] = "月";
week[2] = "火";
week[3] = "水";
week[4] = "木";
week[5] = "金";
week[6] = "土";
Calendar YEAR_MONTH_DATE = Calendar.getInstance();
YEAR_MONTH_DATE.set( Calendar.YEAR,YEAR );
YEAR_MONTH_DATE.set( Calendar.MONTH,MONTH );
YEAR_MONTH_DATE.set( Calendar.DAY_OF_MONTH,DATE );
int DAY_OF_WEEK = YEAR_MONTH_DATE.get( Calendar.DAY_OF_WEEK );
upload_date = upload_date.substring(5,11) + "(" + week[DAY_OF_WEEK]+ ")" + upload_date.substring(11,16);
array_upload_date[counter]=upload_date;
array_todo_id[counter]=rset.getString("todo_id");
counter++;
}
・Arraylistの使用
上記問題の解決方法:Arraylistで値をもらって、最後にarrayに渡します。
List<String>list_todo_text = new ArrayList<>();
List<String>list_upload_date = new ArrayList<>();
List<String>list_todo_id = new ArrayList<>();
while (rset.next()) {
String todo_text = rset.getString("todo_text");
todo_text = todo_text.replaceAll("(?i)(&)", "&");
todo_text = todo_text.replaceAll("(?i)(')", "'");
todo_text = todo_text.replaceAll("(?i)(\")", """);
todo_text = todo_text.replaceAll("(?i)(<)", "<");
todo_text = todo_text.replaceAll("(?i)(>)", ">");
list_todo_text.add(todo_text);
String upload_date = rset.getString("upload_date");
upload_date = upload_date.replaceFirst("(?i)(-)", "年");
upload_date = upload_date.replaceFirst("(?i)(-)", "月");
upload_date = upload_date.replaceFirst("(?i)( )", "日");
upload_date = upload_date.substring(0,16);
int YEAR = Integer.parseInt(upload_date.substring(0,4));
int MONTH = Integer.parseInt(upload_date.substring(5,7));
int DATE = Integer.parseInt(upload_date.substring(8,10));
MONTH = MONTH-1;
DATE = DATE-1;
String week = new String[7];
week[0] = "日";
week[1] = "月";
week[2] = "火";
week[3] = "水";
week[4] = "木";
week[5] = "金";
week[6] = "土";
Calendar YEAR_MONTH_DATE = Calendar.getInstance();
YEAR_MONTH_DATE.set( Calendar.YEAR,YEAR );
YEAR_MONTH_DATE.set( Calendar.MONTH,MONTH );
YEAR_MONTH_DATE.set( Calendar.DAY_OF_MONTH,DATE );
int DAY_OF_WEEK = YEAR_MONTH_DATE.get( Calendar.DAY_OF_WEEK );
upload_date = upload_date.substring(5,11) + "(" + week[DAY_OF_WEEK]+ ")" + upload_date.substring(11,16);
list_upload_date.add(upload_date);
list_todo_id.add(rset.getString("todo_id"));
}
String todo_text=(String)list_todo_text.toArray(new String[0]);
String upload_date=(String)list_upload_date.toArray(new String[0]);
String todo_id=(String)list_todo_id.toArray(new String[0]);
最後のArrayListがArrayに変換する理由はJSPに定義した型がわからないので、Arrayに変換しました。
String todo_text = (String) request.getAttribute("todo_text");
String upload_date = (String) request.getAttribute("upload_date");
String todo_id = (String[]) request.getAttribute("todo_id");
プログラミング中、あった問題 10
・変数statusの使用
変数statusがerror_statusに変わりました。
変数messageがerror_messageに変わりました。
新しい変数resultを追加しました。
if (result == true && mode.equals("user_verification")
|| result == true && mode.equals("delete_Todo_database")
|| result == true && mode.equals("add_Todo_database")
|| result == true && mode.equals("edit_Todo_database"))
・if...else if...else...確実にelseで終了
以前:全部のelse ifをifに変わりました。
現在:elseで終了しました。
if (userid.equals("") && userpassword.equals("")) {
error_status = "ログイン失敗しました。";
error_message = "USERNAMEとPASSWORDを入力してください。";
}
else if (userid.equals("")) {
error_status = "ログイン失敗しました。";
error_message = "USERNAMEを入力してください。";
}
else if (userpassword.equals("")) {
error_status = "ログイン失敗しました。";
error_message = "PASSWORDを入力してください。";
}else {
String value = shain.verificationData();
if (value.equals("false")) {
error_status = "ログイン失敗しました。";
error_message = "USERNAMEもしくはPASSWORDは正しくありません。";
}
else if (value.equals("disconnect")) {
error_status = "DataBase接続できません。";
error_message = "管理者に連絡してください。";
}
else {
result = true;
}
}
・Encodeの部分UserBeansに移動します。
public String getPassword() {
password = password.replaceAll("(?i)(&)", "&");
password = password.replaceAll("(?i)(')", "'");
password = password.replaceAll("(?i)(\")", """);
password = password.replaceAll("(?i)(<)", "<");
password = password.replaceAll("(?i)(>)", ">");
return password;
}
public String getId() {
id = id.replaceAll("(?i)(&)", "&");
id = id.replaceAll("(?i)(')", "'");
id = id.replaceAll("(?i)(\")", """);
id = id.replaceAll("(?i)(<)", "<");
id = id.replaceAll("(?i)(>)", ">");
return id;
}
・userとtodoのServletが分別しました。
実行方法:Todoの機能をTodoBeansに遷移しました。ModeServletにTodoと関連した変数を変わりました。
・一覧画面のディスプレイ機能がDataBaseのServletに移動します。
実行方法:UserBeansにprint_todoメソッドを追加しました。
public Boolean print_todo(HttpServletRequest request, HttpServletResponse response) {
try {
ResultSet rset = null;
conn = ds.getConnection();
StringBuffer sql = new StringBuffer();
id = id.replaceAll("(?i)(')", "''");
sql.append("SELECT `todo_id`,`todo_text`,`finished`,`upload_date` FROM `todo` WHERE user_id = '" + id + "'");
System.out.println(sql);
pstmt = conn.prepareStatement(new String(sql));
pstmt.execute();
rset = pstmt.executeQuery();
request.setAttribute("print", rset);
request.getRequestDispatcher("/member.jsp").forward(request, response);
rset.close();
pstmt.close();
conn.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
conn.close();
} catch (Exception e) {
}
}
}
バグ:追加や削除や編集をしたら、真白のページに遷移してしまいました。
問題点:JSPからModeServletに値を渡します。そして、ModeServletからBeansに値を渡します。UserBeansを実行したことがないので、値がありません。ですから、TodoBeansもprint_todoメソッドを追加しなければなりません。
解決方法:UserBeansとTodoBeansがprint_todoメソッドを追加しました。
if (result == true && mode.equals("user_verification"))
{
request.setAttribute("id", userid);
request.setAttribute("password", userpassword);
user.print_todo(request, response);
}
else if(result == true && mode.equals("delete_Todo_database")
|| result == true && mode.equals("add_Todo_database")
|| result == true && mode.equals("edit_Todo_database")) {
request.setAttribute("id", userid);
request.setAttribute("password", userpassword);
todo.print_todo(request, response);
}
・for(string todo:todo_array)メソッドを使用しました。
for (String todo_array : todo) {
String todo_str = todo_array.replaceAll("(?i)(')", "''");
String sql = "DELETE FROM `company_db`.`todo` WHERE `todo_id`='" + todo_str + "'";
doDataBase(sql);
}
・トランザクションの勉強、DataBaseで複数指令が確実に実行するためです。
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/company_db?serverTimezone=UTC&useSSL=false",
"suser", "spass");
conn.setAutoCommit(false);
Statement statement=conn.createStatement();
//Encode
id = id.replaceAll("(?i)(')", "''");
String sql1 = "delete from user where user_id=('" + id + "')";
String sql2 = "delete from todo where user_id=('" + id + "')";
statement.executeUpdate(sql1);
statement.executeUpdate(sql2);
conn.commit();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
問題:どうやって確認しますか?
以前の方法は一つ一つを実行するので、デバッグで止めて、一つ一つを実行しながら、DataBaseにデータを確認します。観察した結果は最初の指令を実行したら、DataBaseのデータが削除されました。現在の方法なら、全部の指令を終わる前に、DataBaseのデータが削除されません。
・member.jspのEncode
BeansにEncodeメソッドを追加しました。
public Boolean Encode(){
id = id.replaceAll("(?i)(&)", "&");
id = id.replaceAll("(?i)(')", "'");
id = id.replaceAll("(?i)(\")", """);
id = id.replaceAll("(?i)(<)", "<");
id = id.replaceAll("(?i)(>)", ">");
password = password.replaceAll("(?i)(&)", "&");
password = password.replaceAll("(?i)(')", "'");
password = password.replaceAll("(?i)(\")", """);
password = password.replaceAll("(?i)(<)", "<");
password = password.replaceAll("(?i)(>)", ">");
return true;
}
プログラミング中、あった問題 09
現在の型:2019-05-09 00:00:00
想定の型:2019年05月09日(木)00:00
String todo_text = rset.getString("todo_text");
todo_text = todo_text.replaceAll("(?i)(&)", "&");
todo_text = todo_text.replaceAll("(?i)(')", "'");
todo_text = todo_text.replaceAll("(?i)(\")", """);
todo_text = todo_text.replaceAll("(?i)(<)", "<");
todo_text = todo_text.replaceAll("(?i)(>)", ">");
String upload_date = rset.getString("upload_date");
upload_date = upload_date.replaceFirst("(?i)(-)", "年");
upload_date = upload_date.replaceFirst("(?i)(-)", "月");
upload_date = upload_date.replaceFirst("(?i)( )", "日");
upload_date = upload_date.substring(0,16);
int YEAR = Integer.parseInt(upload_date.substring(0,4));
int MONTH = Integer.parseInt(upload_date.substring(5,7));
int DATE = Integer.parseInt(upload_date.substring(8,10));
MONTH = MONTH-1;
DATE = DATE-1;
String[] week = new String[7];
week[0] = "日";
week[1] = "月";
week[2] = "火";
week[3] = "水";
week[4] = "木";
week[5] = "金";
week[6] = "土";
Calendar YEAR_MONTH_DATE = Calendar.getInstance();
YEAR_MONTH_DATE.set( Calendar.YEAR,YEAR );
YEAR_MONTH_DATE.set( Calendar.MONTH,MONTH );
YEAR_MONTH_DATE.set( Calendar.DAY_OF_MONTH,DATE );
int DAY_OF_WEEK = YEAR_MONTH_DATE.get( Calendar.DAY_OF_WEEK );
upload_date = upload_date.substring(5,11) + "(" + week[DAY_OF_WEEK]+ ")" + upload_date.substring(11,16);
今までのコードの改善方向
1.Encodeの部分がServletに移動します。
2.トランザクションの勉強、DataBaseで複数指令が確実に実行するためです。
3.caseの変数名をわかりやすくします。(Refactor)
4.DataBaseの接続確認機能を削除します。
5.無駄なサービスを削除します。(default value)
6.if...else if...else...確実にelseで終了します。
7.statusがbooleanで定義します。もしくは変数名をかわります。
8.一覧画面のディスプレイ機能がDataBaseのServletに移動します。
9.dogetとdopostの役割を理解します。
10.userとtodoのServletが分別します。
11.Encodeの機能がまとめてします。
12.for(string todo:todo_array)メソッドを使用します。
・Servlet名を変更しました。
info.searchman.lesson.java_mysql.EditServlet -> user_todo.ModeServlet
info.searchman.lesson.java_mysql.EditServlet -> user_todo.UserBeans
(web.xml)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>ModeServlet</servlet-name>
<servlet-class>user_todo.ModeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ModeServlet</servlet-name>
<url-pattern>/Mode</url-pattern>
</servlet-mapping>
</web-app>
・JSPのurl-pattern修正
<form action="Edit" method="POST"> -> <form action="Mode" method="POST">
・JSP名を変更しました。
add_list.jsp -> add_Todo.jsp
delete_ID.jsp -> delete_User.jsp
delete_list.jsp -> delete_Todo.jsp
edit_list.jsp -> edit_Todo.jsp
・caseの変数名を変わりました。
case "add_User"
case "delete_User"
case "delete_User_confirm"
case "change_password"
ase "change_password_save"
case "user_verification"
case "add_Todo"
case "add_Todo_database"
case "delete_Todo"
case "delete_Todo_database"
case "edit_Todo"
case "edit_Todo_database"
case "logout"
・DataBaseの接続確認機能を削除しました。
・新しいエラーメッセージを作成しました。(DataBase接続できません。)
(ModeServlet)
if (value.equals("disconnect")) {
status = "DataBase接続できません。";
message = "管理者に連絡してください。";
}
(UserBeans)
catch (SQLException sQLException) {
sQLException.printStackTrace();
var = "disconnect";
return var;
}
・アカウントを作成すると、default valueを追加する機能を削除しました。
String sql2 = "INSERT INTO `company_db`.`todo` (`user_id`, `todo_text`, `finished`, `created_date`, `upload_date`) VALUES ('"
+ id + "', '買い物する', '1', '" + time + "', '" + time + "')";
・全ての変数pwをpasswordに変更しました。
・dogetとdopost
GETの場合、URL内部にパラメータが組み込まれるので、ブラウザの履歴やキャッシュが残ります。
POSTは残らないので、機密性が高いと言えなくもありませんが、結局、パケットは平文で流れるので、機密性について考える場合は、どちらにしても別途、暗号化の仕組みを取り入れる必要があります。
URLを使ったので、dogetの部分は必要です。
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
・if...else if...else...確実にelseで終了します。
elseを使う必要性がないので、全部のelse ifをifに変わりました。
・変数statusの使用
if (status.equals("成功しました") && mode.equals("user_verification")
|| status.equals("成功しました") && mode.equals("delete_Todo_database")
|| status.equals("成功しました") && mode.equals("add_Todo_database")
|| status.equals("成功しました") && mode.equals("edit_Todo_database"))
使用しない問題:認証機能が失効します。
booleanで定義する問題:全てのcaseが修正しなければなりません。そして、詳しいエラーメッセージがなくなります。
新しい変数を追加する問題:四つcaseの中に、全てのifがこの変数を使用しなければなりません。