okinawa

IT勉強メモ

アルゴリズム勉強メモ

 

参考

漫画の並べ替えを例にしていてわかりやすかった。

デカルトみを感じたいなら、コンピュータ科学をやれ!【アルゴリズム3】#3 - YouTube

 

選択ソート

1000巻の漫画から1巻を探して一番左に配置。
次に2巻を探して1巻の隣に配置。
これを繰り返す。
1000回の比較
999回の比較
998
997



1
平均すると500回の比較を999回繰り返す。
なので計算量は
999 * 500 = 499500
(n-1)(n÷2)
O(n^2)


クイックソート

1000巻の漫画から真ん中500巻を取り出す。(本当は真ん中ではないがわかりやすくするため)
500巻より小さいのを左に、大きいのを右に分割する。
比較を1000回行うことになる。
左のからさらに1冊を取り出す。同様に小さいのを左、大きいのを右。
繰り返し分割していくと
1000
500
250
125
62
31
15
7
3
1
計10回で1冊に分割できる。
1回の分割ごとに1000回比較するから計算量は
1000 * log1000 = 10000
n * log1000
O(nlogn)

クイックソートは分割統治アルゴリズ。
分割統治は大きな問題を小さく分割して解決すること。
プログラマーは分割統治が重要らしい。

カプセル化とか関数の機能分割とかは確かに分割統治してる気がする。

IT用語メモ

 

Cookieとキャッシュ

CookieはどのPCからのアクセスかなどのユーザーを識別する用途で使われる。

サーバーからクライアントに送りつけられるもの。

 

キャッシュはWebページの画像などを保存して再度開くとき高速化する。

クライアントが勝手に保存する。

 

API

Application Programming Interface

システムとシステムの間を繋ぐインターフェースのこと。

 

POPとIMAP

POPはメールサーバーからメールをダウンロード。

メールはクライアント側で保存する。

 

IMAPはメールサーバーに直接メールを見に行く。

メールはメールサーバーに保存。

 

最近はGmailなどのWebメールが主流になっており、POPやIMAPを意識することが少ない。

どっちのプロトコルを使用するかはWebメールのサーバーが設定してくれているので。

 

再帰処理の流れ

用語じゃないけどメモ。

f(n) = n * (n - 1)  終了条件: f(1) = 1

上記の式でn = 4とすると処理は下記の順番になる。

  1. call f(4)
  2. call f(3)
  3. call f(2)
  4. call f(1)
  5. f(1) = 1
  6. f(2) = 2 * 1 = 2
  7. f(2) = 3 * 2 = 6
  8. f(2) = 4 * 6 = 24

先に再帰呼び出しが次々に実行される。ワインディングという。

再帰呼び出しが終了条件(ここではf(1) = 1)に達すると、呼び出し元の関数に制御が戻っていく。アンワインディングという

Privacy Policy

Privacy Policy

Thank you very much for using my blog.

The Privacy Policy (hereinafter, “the Policy”) sets forth our privacy information handling principles. You or users are deemed to have agreed with the Policy if you use our services.

What is privacy information?
Privacy information includes both personal information; and history information and characteristic information.
Personal information refers to the personal information prescribed in the Act on the Protection of Personal Information or information relating to a living individual, specifically the name, date of birth, address, telephone number and other contact information, and any other described information that can identify individuals.
Information other than personal information corresponds to history and characteristic information, such as services used, products purchased, history of pages/ads viewed, search keywords used by users, time and date of use, methods of using, using environment, postal code, gender, occupation, age, user’s IP address, cookie information, location information, and terminal identification information.

How do you collect privacy information?
We may collect personal information when a user makes a user registration or use any of our services and/or history and characteristic information of a user when a user uses any of our services or views any of the pages of our website.
If a user performs settings in such a way that the use of the services is linked with any external service, we will collect the ID to be used by the user in the external service and/or the information that the user agrees to disclose to the linked service under the external service’s privacy settings.

For what purpose do you use privacy information?
The following gives purposes of our collection and use of privacy information.
A) To present registered information including the user’s name, address, contact, and payment methods, used services, purchased products, and charges for such services/products so that users can view and/or correct their registered information and/or view the status of use
B) To use an e-mail address to notify or contact users, to use contact information such as name and address in order to send products to users, contact users as necessary
C) To use such information such as name, date of birth, address, telephone number, bank account number, credit card number, driving license number, and arrival of mails with delivery certificate for user identity verification
D) To use payment-related information such as names/quantities of products purchased, types/periods of services used, number of times of using services, amount billed, name, address, bank account number, and credit card number, in order to charge users
E) To display information registered to us on an input screen so that users can enter data easily or forward such information to external services under instructions of users
F) To use information for identify individuals, such as state of using, name and address, to refuse the use of the Service by those users who violate the Terms of Use of the Service, for example, failing to pay charge and causing damage to a third party or by those users who try to use the Service for unjust/unlawful purposes
G) To use information necessary for our provision of services for users, such as information about details of inquiries and billing, status of use of services by users, and contact information of users so as to answer inquires by users
H) To prepare statistical data that is processed in the form that does not permit personal identification in connection with our services
I) To distribute or display advertisements of us or a third party
J) To use privacy information for marketing
K) Purposes incidental to the purposes of using above

Do you provide privacy information for a third party?
We will not provide privacy information for a third party without the prior approval of users except for the following. However, this excludes cases in which the provision is permitted under the Act on the Protection of Personal Information or any other laws and regulations.
A) Where requested under laws and regulations
B) Where the provision is required for protecting human life, body or property and it is difficult to obtain an approval of the user him/herself
C) Where it is especially necessary to improve public health or promote the sound growth of children and it is difficult to obtain the approval of the user him/herself
D) Where it is necessary to help any national organization, a local public organization, or a contractor perform the clerical work prescribed in laws and regulations and the approval of the user him/herself could disturb the performance of the clerical work

If we outsource all or part of privacy information handling to the extent necessary to achieve the purpose of the use or privacy information is provided along with succession of business due to merger or for any other reasons, it will not correspond to the provision of privacy information to a third party.

We may share or disclose privacy information upon user’s request if a user links any our services with any external services when using our services.

Can I check my privacy information or request you to correct it?
If a user himself/herself requests the disclosure of the privacy information (excluding history or characteristic information) to the user himself/herself, we will disclose it without delay. However, if disclosure could harm the life, body, property, or other interests of the user or a third party, could cause significant hindrance to the proper performance of our business, or violates laws and regulations, we will refrain from disclosing all or part of the information. If we decide not to disclose the information, we will inform you without delay.
We will charge you 1000 yen for each instance of disclosure of personal information.

If any user’s personal information we own is incorrect, the user can request us to correct or delete the personal information by the procedure stipulated by us. If a user makes such a request and we judge it is necessary to meet the request, we will correct or delete the personal information and inform the user without delay.

Can I request you to discontinue the use of my privacy information?
When the user requests discontinuation of the use of his/her privacy information (hereinafter, “Discontinuation of the Use”) claiming the privacy information is handled beyond the scope of the purposes of use or the privacy information is obtained by unjust means, we will conduct a necessary investigation, and based on the outcome of the investigation make take measures such as Discontinuation of the Use, and inform the user without delay.
However, we will take alternative measures if Discontinuation of the Use of privacy information involves an inordinate expense or if it is difficult and alternative measures are possible so as to protect rights and benefits of the users.

Change of Privacy Policy
This Privacy Policy is subject to changes without notice to users.
The changed Privacy Policy will take effect when it is placed on this website unless otherwise specified by us.

Inquiry contact
If you have any question about the policy, please contact us at the following google form.

 

新しいプロジェクトに参加したとき用の備忘録

最初にやること

とりあえずシステムを触ってみて、よくわからない所あったらマニュアル見たり、仕様書・設計書をみる。

自分の担当や修正対象のところを重点的に。

気になったところをメモっておく。

資料を読む

設計書とかって読んでもなかなか理解できない。

だが、どうせわからんからと流し読みをしない。参考記事↓

note.com

資料の読み方

資料は大→小の順に読む。

なんの資料か→大カテゴリの意味→中カテゴリ→小カテゴリ

コードを理解するのにやったこと

検索や更新のできるだけ簡単な処理をしてそうなところを探す。

デバッグモードでざっと流れを見る。

さらに手動で出てくるクラスをすべて見に行った。たいへん時間かかったけどお陰で全体の構成や処理の流れがわかった。

個人的にはRDBのテーブルと1対1になっているモデルクラスを見つけられると理解がしやすい。

1対1のモデルクラスを見つけたら、下記の点を意識しながらみると良き。

  • 画面からモデルクラスにどうやってたどり着くか。
  • DBの検索結果をモデルクラスに格納するのはどこでやってるか。
  • モデルクラスに格納したデータをどうやってViewに渡しているか。

知ってるものに当てはめる。

  • Strutsのバリデーションがわからん時、Springではこうだったよなーとか。
  • ControlllerからDBまでの道筋はStrutsもSpringもほぼ同じはずだよなーとか。

もっと良い方法編み出したら更新したい。

ちなみに今の現場はマニュアルも仕様書も設計書も何もないぞ!

DBも見れないから野生の勘で理解するのだ!!!

コンピュータはなぜ動くのか読んだメモ

参考

回路図書くの大変だったけど、マイコンにちょっと興味が湧いた。

これまた良い本でした。

コンピュータの3大原則

1, コンピュータは、入力、演算、出力を行う装置である

2, プログラムは命令とデータの集合体である

3,コンピュータの都合は人間の感覚と異なる場合がある

基本はCPU・メモリ・I/Oの3つ

基本動作は

  1. CPUはクロックジェネレーターが生成するカチカチという信号に合わせて、メモリやI/Oからデータを読み込む。
  2. CPUが読み込んだデータを解釈し、演算する。
  3. 演算結果をCPUからメモリ・/Oに出力する。

■機器の説明

  • CPU:メモリー・I/OのデータをCPUに入力し、内部で演算を行い、結果をメモリー・I/Oに出力する。レジスタという記憶素子も持つ。

  • メモリ:命令+データの記憶装置

  • I/O:周辺機器からのデータ入力(IN)と周辺機器へのデータ出力(OUT)。レジスタを持つ。

レジスタについて 最も高速な記憶素子。

e-words.jp

回路図

ディップスイッチのON / OFFでLEDランプの点灯/消灯をする回路です。

5V=2進数の1。0V=2進数の0。になるようで。

回路図
回路図

うーん、画像が小さくてテキストが読めない・・・。

■機器の説明

  • クロックジェネレーター:クロック信号を生成するための回路。中に水晶が入っているらしい。

  • 3ステートバスバッファ:BUSリクエストがONのときにディップスイッチからメモリに書き込める。OFF時は遮断

  • ディップスイッチ

  • LEDランプ

※BUSリクエストについて

ONにするとCPUが電気的に切り離される。

CPUを介さずにメモリ読み書きをする時用。

BUS(バス)はCPUに繋がっている配線のこと。

■ピンの略号

  • A0~A15:アドレス入出力。
  • D0~D7:データ入出力。0~7の8ビット=1バイトが、一度に入出力できるデータ量。
  • MREQ:メモリ接続要求
  • IQRQ:I/O接続要求
  • B/A:I/OのB or Aレジスタの選択
  • C/D:I/OのControll or Dataレジスタの選択

※B/A・C/Dについて

I/Oのレジスタ指定用。I/Oのレジスタは4つ。

Acontrol / Adata / Bcontrol / Bdata

この4つの切り替えをB/A・C/Dの電圧切替で行う。

■I/Oレジスタのアドレスと役割

  • (0)番ポート=Aポートデータレジスタ。Adata。
  • (1)番ポート=Bポートデータレジスタ。Bdata。
  • (2)番ポート=Aポート制御レジスタ。Acontroll
  • (3)番ポート=Bポート制御レジスタ。Bcontroll

  • Aポートデータレジスタ=ディップスイッチからの入力データ

  • Bポートデータレジスタ=LEDランプへの出力データ

回路図と機械語アセンブリ言語

同じ命令を機械語アセンブリ言語、回路図で表現してみる

命令の内容は

  1. CPUのAレジスタに207という値を書き込む
  2. Aレジスタの値をI/Oの(2)番ポートレジスタに書き込む

機械語

アドレス        機械語
00000000        00111110 // 00111110=LD命令
00000001        11001111 // 11001111=10進数の207
00000010        11010011 // 11010011=OUT命令
00000011        00000010 // 00000010=10進数の2=I/Oの(2)番ポート指定

※命令かデータかの判断はどうやってするの?

命令は予め決められている。

上記の例だと、00111110はLD命令と決められていて、CPUが命令だなと解釈して実行する。

11001111は命令ではないので、207というデータだなと解釈する。

アセンブリ言語

ラベル    オペコード    オペランド
             LD         A, 207 // CPUのAレジスタに207を読み込む
             OUT       (2), A // I/Oの(2)番ポート=AポートControllレジスタにAレジスタの値を書き込む

機械語アセンブリ言語

アドレス        機械語              ラベル    オペコード    オペランド
00000000        00111110  11001111             LD          A, 207
00000010        11010011  00000010             OUT        (2), A

アセンブリ言語の主な命令

  • 演算命令:ADD(加算)・SUB(減算)

  • メモリとCPUの入出力命令:LD(メモリから読み込んでCPUレジスタに書き込む)この命令の時にMREQがONになる。

  • I/OとCPUの入出力命令:IN(I/Oレジスタから読み込んでCPUレジスタに書き込む)・OUT(CPUレジスタからI/Oレジスタに書き込む)これらの命令の時にIORQがONになる。

回路図で表現すると

  1. MREQがON
  2. A0~A7が00000000
  3. D0~D7が00111110
  4. A0~A7が00000001
  5. D0~D7が11001111
  6. IQRQがON
  7. A0~A7が00000010
  8. D0~D7が11010011
  9. A0~A7が00000011
  10. D0~D7が00000010

多分こういう流れになると思う。

XMLとはなんぞや

Extensible Markup Language。

XMLマークアップ言語。

マークアップ言語とはタグによる意味付け言語

<>タグによって意味づけすることをマークアップという。

この意味付けをする言語がマークアップ言語。

HTMLもマークアップ言語。

HTMLとXMLの違いはタグが固定か拡張可能か

HTMLは<body><head>など決められたタグしか使えない「固定的なマークアップ言語」。

XMLは「拡張可能なマークアップ言語」でタグは何を使っても良い!<abc>でも<xxx>でも好きにタグを作れる。

XMLメタ言語

どんなタグを使っても良いということは、どんな使い方をしても良いということ。

つまり新しいマークアップ言語を作れる。

言語を作るための言語を「メタ言語」という。

XMLは情報に意味付けをする

自由にタグを作れるって言っても、一体XMLは何をするものなの?

情報に意味付けをする。

情報に意味付けをするとはいったい・・・。

下記のHTMLとXMLを見比べてほしい。

HTML

<body>
  <p>リン</p>
  <p>10</p>
</body>

XML

<cat>
  <name>リン</name>
  <age>10</age>
</cat>

HTMLでは「リン」と「10」が何を意味するかわからない。

XMLでは猫の名前「リン」で歳が「10」だと意味がわかる。

これが意味づけ。

XML名前空間

タグの名前は自由に作れるので、他の誰かが作ったタグと名前がかぶってしまうかもしれない。

例えば<name>でも人の名前という意味付けをした人、猫の名前という意味付けをした人がいるかもしれない。

そんな時に同じタグを区別するために名前空間を使う。

Namespaces in XML。「xmlns="名前空間"」と書く。

<?xml version="1.0" encoding="UTF-8"?> //←XML宣言
<cat xmlns="https://blog.hatena.ne.jp/dodosu/dodosu.hatenablog.jp"> // ←名前空間
  <name>リン</name>
  <age>10</age>
</cat>

通常は上記のようにURLを名前空間として使用する。絶対にかぶらないから。

区別できるならURLじゃなくても何でも良い。

XMLはコンピュータが見るもの、HTMLは人が見るもの

HTMLはレンダリングしてブラウザに表示して人が見るもの。

XMLはコンピュータが見て意味を解釈するもの。

リンはcatのnameですよ。10はcatのageですよ。ということをコンピュータに伝えている↓

<?xml version="1.0" encoding="UTF-8"?> //←XML宣言
<cat>
  <name>リン</name>
  <age>10</age>
</cat>

XMLからDOM操作でデータを取得

XMLからデータ取得する方法は色々あるようだけど、馴染み深いDOM操作の例をば。

<?xml version="1.0" encoding="UTF-8"?> 
<cat>
  <name>リン</name>
  <age>10</age>
</cat>

上記のXMLから取得する例。

String catName = cat.name;
int catAge = cat.age;

こんな感じでDOM操作で読み込む。

大体どの言語でもXMLをDOMで読み込むコンポーネントがあるらしい。

まとめ

コンピュータの基本まとめ

コンピュータは、入力、演算、出力を行うもの。

プログラムは命令とデータの集まり。

コンピュータの基本構成はCPU、メモリ、I/Oの3つ。

CPUは頭脳、メモリは記憶装置、I/Oは周辺機器との接続。

メモリ or I/O からCPUにデータと命令が入力され、CPUが演算し、結果をメモリ or I/Oに出力する。

XMLまとめ

XMLマークアップ言語を作るメタ言語

<>内のタグは何でも良い!ので自由に新しいマークアップ言語を作れるということ。

目的としては、データに意味付けをすること。

<catName>リン</catName>と書いて「リン」はcatNameですよとコンピュータに伝える。

オブジェクト指向でなぜつくるのかを読んだメモ

参考

最近なぜシリーズにはまっている。

わかりやすくて大変良いです。 www.nikkeibp.co.jp

オブジェクト指向の3大要素

オブジェクト指向はプログラムを簡単にわかりやすく作るためのもの。

カプセル化(クラス)

まとめて隠してたくさん作る。

クラスの目的は整理整頓。

  • まとめる:関連の強いメソッドや変数を1つのクラスにまとめて整理する。
  • 隠す:privateなどで隠して影響範囲を限定する。
  • たくさん作る:インタンスとして大量生産。

1クラスにごちゃまぜにするとわかりにくい。

public class Gotyamaze {
    private String humanName;
    private int accountNumber;
    private int humanAge;
    private String accountType;
}

分けるとわかりやすいよね。

class Human {
    private String humanName;
    private int humanAge;
}

class Account {
    private int accountNumber;
    private String accountType;
}

ポリモーフィズム多態性

メソッドの呼び出し方を共通化する。

異なる処理を同じ方法で呼び出せる。

ポリモーフィズムの目的は共通化

public abstract class Animal {
    public abstract void cry();
}
public class Cat extends Animal{
    @Override
    public void cry() {
        System.out.println("にゃーん");
    }
}
public class Dog extends Animal{
    @Override
    public void cry() {
        System.out.println("ワンワン!");
    }
}
public class Main {

    public static void main(String[] args) {
        // TODO 自動生成されたメソッド・スタブ
        Animal cat = new Cat();
        Animal dog = new Dog();
        cat.cry(); // にゃーん
        dog.cry(); // ワンワン!
    }
}

継承

クラスの継承。

継承の目的は重複を排除すること。

重複部分はスーパークラスに書く。

固有部分はサブクラスに書く。

public class Person {
    private int age;
        private String name;
}
public class Employee extends Person {
    private String CompanyName;
        private String CompnayAddress;
}
public class Student extends Person {
    private String SchoolName;
        private String SchoolAddress;
}

オブジェクト指向以前はどうだったのか

本当の最初は1つのファイルにベタ書きしていた。

そして、サブルーチン(関数)が誕生した。

その後にサブルーチンの独立性を高めるために、ローカル変数と値渡しが生まれた。

あと、昔の言語には条件分岐(if)と繰り返し(for)が書けなかった?

あやふただけど、昔のCOBOLではif文やfor文を素直に書けなかったらしい。

代わりにGOTO文なるものを書いていたらしいが、これがコードの難読化の原因になっていた。

メモリに関する話

なぜ型宣言するのか

静的領域・ヒープ領域・スタック領域

  • 静的領域:プログラム開始時に確保、終了まで固定。1つだけ。static/グローバル変数/コード情報などが入る。
  • ヒープ領域:プログラム実行時に動的に確保するメモリ領域。あらかじめ1つ確保しておく。 必要になったらヒープ領域が割り当てられ、不要になったら削除される。インスタンスが入る。
  • スタック領域:メソッド制御のためのメモリ領域。スレッドごとに1つ。メソッドの引数/ローカル変数/戻り先などの情報が入る。

閃いた!

staticメソッドが非static(インスタンス)を参照できない理由が!

静的領域は最初にメモリ領域が確保される。

対してインスタンスは必要に応じてメモリ領域が割り当てられる。

だから、staticメソッドからインスタンスを参照しようにも、まだインスタンスが存在しないから。

ガベージコレクションの対象となる条件

静的領域とスタック領域から辿れないインスタンスが対象。

インスタンス同士で循環参照していても、静的領域とスタック領域から辿れなければガベージされる。

用語:スレッドとプロセス

どちらもプログラムの実行単位。

プロセスのほうが大きい単位。

スレッドの集まりがプロセス。

スレッド<プロセス

用語:参照とポインタ

Javaで言うところの参照ってポインタと同じ意味なんだって。

知らなかったわあ。

使ってみたいUML

クラス図

クラスの仕様とクラス同士の関連。

ソース理解のために書いてみた。すごくいい。

シーケンス図

インスタンス間の処理の流れを時系列で表現。

アクティビティ図

役割ごとに分けた処理の流れを表現。

頭の整理に良い。

自分ハマったときに処理の流れを細かく分解するのだけど、その時にこれを使うと良さそう。

あと業務分析にも使えそう。

ユースケース

棒人間。

システムの機能と利用者の関係を表現。

これも頭の整理、業務分析に使えそう。

主に役割分担に良さげ。

関数型言語

存在は知っていたけど、どんなものかは初めて知った。

なんか楽しそうやなあ、使ってみたいわあ。

ちなみに副作用という話が出てきて、副作用というのは外部入出力のこと。

つまりI/Oを使用せず、CPUとメモリだけで処理が完了するということなのかしら。

低レイヤを勉強するとこんな感じで知識が活きるんやなあと実感。

まとめ

オブジェクト指向はプログラムを簡単に作るためのもの。

3大要素。

カプセル化(クラス)

整理整頓が目的。

関連の強いメソッドや変数をひとまとめにする。

private/protectedなどで影響範囲を限定する。

現実でいうと収納。キッチンの収納にはキッチン用品、玄関の収納には靴、というように関連の強いものを収納する。

メリットは人間にとってわかりやすく、修正しやすいプログラムを書ける。

ポリモーフィズム多態性

メソッドの呼び出し側を共通化する仕組み。

呼び出し方法は同じでも異なる処理が呼び出せる。

現実でいうと「Aさんアレやっといてー」みたいな。

有能なAさんはアレが何かを的確に判断し、その時々で必要なアレを処理する。

メリットは修正が簡易になること。

例えば呼び出される側(メソッド)を増やしても、呼び出し側を修正する必要がない。

・継承

クラスの重複を排除する仕組み。

サブクラスはスーパークラスの定義を含む。

サブクラスにはスーパークラスにはない固有の定義を書ける。

現実でいうと出産?人間の子は手足や頭、遺伝子を親から継承している。

しかし、子供固有の性格や身体的特徴を持つ。

ちょっとこの例えは無理があるかw

メリットは同じコードを何度も書かなくて済むこと。

UML

個人的に使いそうなのは

プログラミングだけでなく、業務分析や頭の整理にも使えそう。

Struts基本のキ

Struts1と2の内容が混在しています。完全に自分用メモです。

Struts2

参考サイト

qiita.com

リクエスト送信→受け取り→レスポンスまでの流れ

jspのformタグからリクエスト送信

index.jsp

<body>
        <s:form action="message">
            <s:textfield name="age"/>
            <s:submit value="年齢送信"/>
</body>

s:~~~はStrutsのタグライブラリ。

  • s:form action="message":struts.xmlのaction name="message"が呼び出される
  • <s:textfield name="age"/>:アクションクラスのprivate int ageに代入される
struts.xmlで動きを制御
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <!-- アクションのパッケージ定義 -->
    <package name="default" extends="struts-default">
        <action name="message" class="sample.MessageAction" method="ageMessage">
            <result name="fortune">/view/sample/fortune.jsp</result>
            <result name="good">/view/sample/good.jsp</result>
        </action>
    </package>
</struts>
  • action name="message":呼び出し用の名前
  • class="sample.MessageAction":呼び出されるクラス
  • method="ageMessage":呼び出されるメソッド
  • <result name="fortune" /view/sample/fortune.jsp:return "fortune"すると呼び出されるjsp
  • <result name="good" /view/sample/good.jsp:return "good"すると呼び出されるjsp
アクションクラスが呼び出される

MessageAction.java

package sample;

public class MessageAction {
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String ageMessage() {
        if (this.age >= 70) {
            return "good";
        }
        return "fortune";
    }
}

struts.xmlに対応したActionクラス、Actionメソッドを作る。

  • private int age:index.jspの<s:textfield name="age"/>の値が入る。勝手にgetter/setterが動くらしい
  • return "good":/view/sample/good.jspが呼び出される
  • return "fortune":/view/sample/fortune.jspが呼び出される
リクエストで受け取った値をjspで表示

good.jsp

<body>
<s:property value="age"/>才。よく生きましたね。<br>あなたの人生に幸あらんことを。
</body>

fortune.jsp

<body>
<s:property value="age"/>才、あなたの人生に幸あらんことを。
</body>

簡易まとめ

jspでAction名「message」を指定して呼び出す

struts.xml内で「message」を検索

→該当のActionメソッドが呼び出される

→Actionメソッドがreturn forutune or good する

struts.xml内でresultName「'fortune' or 'good'」を検索

→fortune.jsp or good.jspに遷移

jsp内の<s:property value="age"/>は、Actionクラスのage変数から取ってくる

Struts1

参考サイト

概要を学ぶならここ↓
Strutsフレームワークの「枠組み」を学ぶ:Strutsを使うWebアプリケーション構築術(2)(1/2 ページ) - @IT

もうちょっと踏み込んだ概要↓
【Struts入門】今さらStruts1.3.10を勉強したのでまとめてみた【初心者向け】 - Qiita

コード書くときの参考はここ↓
忘れっぽいエンジニアのJakarta Strutsリファレンス

コード書くときの参考2はここ↓
Javaの道>オープンソース

環境構築

下記サイトからstruts-1.3.10-all.zipをダウンロードして解凍。
https://struts.apache.org/releases

appsフォルダ内の「struts-blank-1.3.10.war」をEclipseからwarファイルのインポートを実行する。

インポートしたプロジェクトを実行して下記画面が出たらOK

welcomepage

あとは自由に中身を作り変えましょう。

jsp

下記コードはクライアントサイドとサーバーサイドの両方のバリデーションが有効。

クライアントサイドのバリデーションが優先される。

サーバーサイドのバリデーションメッセージを見る場合は「html:javascript~」と「onsubmit=~」を消す。

・index.jsp

<%@page contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%>
<% request.setCharacterEncoding("UTF-8"); %>
<body>
<!-- クライアントサイドのバリデーションを有効にしている -->
<html:javascript formName="SampleForm" />

    <!-- クライアントサイドのバリデーションを有効にしている2 onsubmit="return validate「Formクラス名」(this)" -->
    <html:form action="/SampleAction.do" onsubmit="return validateSampleForm(this)">
        <bean:message key="index.nameText" />
        <html:text property="name" />
        <!-- classはstyleClass。 idはstyleId で付与する -->
        <html:text property="age" styleClass="ageClass"/>
        <html:submit value="年齢送信" styleId="aaa" />
    </html:form>
    
    <!-- サーバーサイドのバリデーションメッセージ部分。 クライアントサイドのバリデーションを消すとこっちが動作する -->
    <html:errors property="name"/>
    <html:errors property="age" />
</body>

Welcom.jsp

<%@ page isELIgnored="false" %><!-- EL式を有効にする -->
<%@page contentType="text/html; charset=UTF-8" %>
<% request.setCharacterEncoding("UTF-8"); %>
<%@page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>

<html:html>
<head>
<title>welcome</title>
</head>

<h3><bean:message key="welcome.heading"/></h3>
<!-- SampleForm.nameとSampleForm.ageを取得 -->
<bean:parameter name="name" id="na"/>
<bean:parameter name="age" id="ag"/>
${sampleForm.name}<br><!-- ここだけEL式 -->
<%= na %><br>
<%= ag %><br>
</body>
</html:html>

Actionクラス

MVCで言うところのController。Actionクラスを継承する。

下記がActionクラスとActionメソッドの基本の書き方。

package controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import model.SampleForm;

public class SampleAction extends Action {
  public ActionForward execute (ActionMapping map, ActionForm form, HttpServletRequest request, HttpServletResponse response) {

            SampleForm sampleForm = (SampleForm)form;
            request.setAttribute("sampleForm", sampleForm); // ここはEL式使わないならなくてOK

            return map.findForward("success");
  }
}

ActionFormクラス

MVCのModelクラス。ValidatorFormクラスを継承。

package model;

import org.apache.struts.validator.ValidatorForm;

public final class SampleForm extends ValidatorForm {
  private String name;
  private int age;

  
public int getAge() {
    return age;
}
public void setAge(int age) {
    this.age = age;
}
public void setName(String name) {this.name=name;}
  public String getName() {return name;}
}

WebページのForm要素にあるパラメータ値を格納するためのJavaBean。

引用元:2. ActionForm | TECHSCORE(テックスコア)

ValidatorFormを継承してFormクラスを作るとHTMLのformタグから送られた値をget/setできる。
なおかつValidationも活用できる。

struts-config.xml

の重要な部分だけ。

※私の環境ではstruts-configを変更する度にプロジェクトのリフレッシュが必要でした。

下記サイトの画像による説明がめっちゃわかりやすいのでそれを見よう↓

参考:Strutsフレームワークの「枠組み」を学ぶ:Strutsを使うWebアプリケーション構築術(2)(2/2 ページ) - @IT

  • form-beans:Formクラスの場所と名前を定義するだけ。
  • action-mappings:アクションの定義
    • path:呼び出すアクションクラス。
    • name:アクションクラスが実行された時に実行されるアクションフォームBeanの名前
    • type:アクションクラスの完全修飾名
    • scope:request/sessionのどちらかを設定できる。
    • validate:バリデーションの有効化。
    • input:バリデーションエラーの場合に遷移するページを指定。
  • forward
    • name:Actionクラスでreturn "success"すると呼び出される。
    • path:呼び出されるファイル
<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
          "http://struts.apache.org/dtds/struts-config_1_3.dtd">

<struts-config>
    <form-beans>
    <form-bean name="SampleForm" type="model.SampleForm" />
    </form-beans>

    <global-exceptions>
    </global-exceptions>

   <global-forwards>
        <!-- Default forward to index.do -->
        <forward
            name="index"
            path="/index.do"/>
    </global-forwards>
  
    <action-mappings>
        <action
            path="/SampleAction"
            type="controller.SampleAction"
            name="SampleForm"
            scope="request"
            validate="true"
            input="/index.jsp">
            <forward name="success" path="/pages/Welcome.jsp"/>
         </action>
    </action-mappings>

  <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property
        property="pathnames"
        value="/org/apache/struts/validator/validator-rules.xml,
               /WEB-INF/validation.xml"/>
  </plug-in>
</struts-config>

validation.xml

各所の意味はこちらを参考に↓
Javaの道:Struts(17.Validator)

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE form-validation PUBLIC
     "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.3.0//EN"
     "http://jakarta.apache.org/commons/dtds/validator_1_3_0.dtd">

<form-validation>

    <global>

        <!-- An example global constant
        <constant>
            <constant-name>postalCode</constant-name>
            <constant-value>^\d{5}\d*$</constant-value>
        </constant>
        end example-->

    </global>
    
        <formset>
            <form name="SampleForm">
                <field property="name" depends="required">
                <arg key="index.nameText" />
                </field>
                
            <field property="age" depends="minlength">
            <arg0 key="index.ageText" />
            <arg1 key="${var:minlength}" resource="false"/> <!--  ${var:minlength}は変数。<var-value name="value">の値「4」をとってくる。 resource="false"でmessage.propertiesの参照をとめる -->
                <var>
                    <var-name>minlength</var-name>
                    <var-value name="value">4</var-value>
                </var>
            </field>
                
            </form>
        </formset>
</form-validation>

MessageResource.properties

# -- standard errors --
errors.header=<UL>
errors.prefix=<LI>
errors.suffix=</LI>
errors.footer=</UL>
# -- validator --
errors.invalid={0} is invalid.
errors.maxlength={0} can not be greater than {1} characters.
errors.minlength={0} can not be less than {1} characters.
errors.range={0} is not in the range {1} through {2}.
errors.required={0} is required.
errors.byte={0} must be an byte.
errors.date={0} is not a date.
errors.double={0} must be an double.
errors.float={0} must be an float.
errors.integer={0} must be an integer.
errors.long={0} must be an long.
errors.short={0} must be an short.
errors.creditcard={0} is not a valid credit card number.
errors.email={0} is an invalid e-mail address.
# -- other --
errors.cancel=Operation cancelled.
errors.detail={0}
errors.general=The process did not complete. Details should follow.
errors.token=Request could not be completed. Operation is not in sequence.
# -- index --
index.nameText=name
index.ageText=age

ActionMessagesクラス

ページにメッセージを渡すクラス。

エラーメッセージ表示とかに使う。

ActionErrorsというクラスもあり、使い方もほぼ同じ。

メッセージ本文はmessages.propertiesとかから取得。

messages.add(プロパティ, ActionMessage);// メッセージを追加
saveMessages(request, messages); // メッセージを保存

参考:いまさらながらStruts – ActionMessages | 雑廉堂の雑記帳

ActionMappingクラス

struts-config.xmlでアクション名とか決めてる所。

ActionMapping.getAttributeとかでname要素を取得できるんだと思う。

// こんな感じでアクションメソッドの引数にとりあえず入れておく
public ActionForward executeAction(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)

参考:Strutsリファレンス<action-mapping>

.doの謎

.doが付いてたり、付いてなかったりで混乱した。

  • <html:form>要素内だと.doいらない。自動でつく。
  • その他は.doいる。

.doをつけないとアクションサーブレットが呼ばれない。

呼ばれないとstruts-config.xmlを経由しないのでAction呼べない。

つまり直リンクで画面遷移しかできない。

参考↓ 下のほう、まとめの上あたりに書いてある

atmarkit.itmedia.co.jp

簡易まとめ

jspでActionのpath名「/SampleAction」で呼び出す

struts.xml内で「/SampleAction」を検索

→該当のActionクラスのexecuteメソッドが呼び出される

→同時に「name="SampleForm"」の部分で、SampleFormクラスに値がセットされる。

→Actionメソッドがreturn success する

struts.xml内でforward name「success」を検索

→Welcome.jspに遷移

もっと新しい技術を触りたいなあ(´;ω;`)