ELBOOKS
の編集
https://wiki.el-dev.net:443/index.php?ELBOOKS
[
トップ
] [
編集
|
差分
|
バックアップ
|
添付
|
リロード
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
-- 雛形とするページ --
2021年議事録
Best Casual Dating Platform To For Just Sex
BracketName
Eclipse 環境構築
ELBOOKS
FormattingRules
FrontPage
Github
Help
InterWiki
InterWikiName
InterWikiSandBox
MenuBar
PHP
PukiWiki
PukiWiki/1.4
PukiWiki/1.4/Manual
PukiWiki/1.4/Manual/Plugin
PukiWiki/1.4/Manual/Plugin/A-D
PukiWiki/1.4/Manual/Plugin/E-G
PukiWiki/1.4/Manual/Plugin/H-K
PukiWiki/1.4/Manual/Plugin/L-N
PukiWiki/1.4/Manual/Plugin/O-R
PukiWiki/1.4/Manual/Plugin/S-U
PukiWiki/1.4/Manual/Plugin/V-Z
RecentDeleted
SandBox
where to find promo codes
WikiEngines
WikiName
WikiWikiWeb
YukiWiki
エラー
タイピング
画像ファイルを選択したときにプレビュー表示する方法
議事録テンプレート
質問方法
[[FrontPage]] &size(20){目次}; #contents(level=1) *スケジュール作成サンプル [#i6862607] #ref(./EL-BOOK ワークフロー サンプル.xlsx,80%); *コーディング作業が楽になるショートカットの一覧 [#i6862607] [[Windows:https://dekiru.net/article/18619/]] [[Eclipse:https://www.casleyconsulting.co.jp/blog/engineer/172/]] 覚えておくと良いこと &br;ファイル保存 [Ctrl + S] &br;全てを保存 [Ctrl + Shift + S] &br;文字列検索 [Ctrl + F] &br;コピー[Ctrl + C] ペースト [Ctrl + V] &br;候補[Ctrl + Space] *設計書作成 [#x48eecb0] **機能一覧表 [#l9240598] #ref(./function_list.png,80%); **画面構成 [#c3141316] #ref(./view.png,80%); **テーブル定義書 [#t0ef638c] テーブル定義書とはテーブルを作成するための設計書です。データベースにテーブルを定義するためのDDL文を作成するために必要な設計書ということです。 &br; &ref(./table.png,80%); **テスト仕様書 [#wc39b0f7] |画面|区分1|区分2|確認項目|結果|h |ログイン|テキストボックス|メールアドレス|文字が入力できること&br();必須項目になっていること|OK| |~|~|パスワード|文字が入力できること&br();必須項目になっていること&br();入力したときに***で隠れていること|NG| **ER図 [#f1d67711] [[ER図とは:https://it-koala.com/entity-relationship-diagram-1897]] #ref(./er.png,80%); **クラス図 [#feca588a] #ref(./uml_line.png,80%); &br;多重度はそのクラスのインスタンスが何個関連を持つかを表します。表記法としては以下の3パターンを覚えておけば十分でしょう。n..m:n以上m以下n..*:n以上n , m:n個またはm個 #ref(class.png); **シーケンス図 [#l0ee201a] Visual Studio Codeを開きます。 左側のメニューに拡張機能があるので PlantUMLと入力してください &br;検索すると一番上に出てくると思うのでクリックしてインストールします。 インストールが終えたら &br;左上のメニューにあるファイルから新規作成を選択してください。 Untitled-1が作成されるのでCTRL + SHIFT + S を押します。 &br;任意のファイル名を入力し、ファイルの種類をPlantUMLに選択して保存します。 .wsdという形式のファイルができればOKです。 下記がUMLのサンプルになります。 @startuml Update mainframe ユーザー編集 actor User participant "ユーザー一覧画面" as View participant "編集モーダル" as Modal participant "エンコード" as encode participant "更新処理" as Update database "データベース" as DB alt 権限あり User -> View : 編集したい activate View else 権限なし User <-- View : エラー end View -> Modal : 一覧から選択する activate Modal Modal <-- DB : ユーザーID,変更前の名前,メールアドレス,パスワード activate DB Modal -> Update : 入力(名前,メールアドレス) activate Update Modal -> encode : 入力(パスワード) deactivate Modal activate encode encode -> Update : 暗号化したパスワード deactivate encode Update -> DB :更新 deactivate Update View <-- DB : 更新したユーザー情報を反映 deactivate DB deactivate View @enduml &br;ALT+Dを押すとプレビューに図が表示されます。 &br;図を画像ファイルとして保存したい場合は ファイル内で右クリックすると ファイル内のダイアグラムをエクスポートとあるのでクリックします。 &br;pngを選択するとのファイルを作成した場所にフォルダが作成されているのでフォルダ内に画像ファイルがあります。 *github[#q8a7110e] Git Hubのアカウント作成 以下のリンクから作成してください &br;[[アカウント作成:https://github.com/]] &br;ユーザー名とメールアドレスとパスワードを入力して登録します。 無料版であるfreeを選択してContinue押して作成されます。 Git Bashのダウンロード~インストールまで 下記からサイトへ移動してDownloadボタンを押します。 Git Bashの[[ダウンロード:https://gitforwindows.org/]] インストーラーを起動してセットアップをおこないます。 最初のウィンドウからNextを押して進みます。 &br;Git Bash Hereにチェックが付いていることを確認して Next &br;Use Git from the Windows Command Promptを選択して Next &br;Use the OpenSSL libraryを選択して Next &br;Checkout Windows-style,commit Unix-style line endingsを選択して Next &br;Use MinTTY(the default terminal of MSYS2)を選択して Next &br;Enable file system cachingとEnable Git Credential Managerにチェックを入れて Next &br;いくつかチェックボックスがありますが入れずにNextを押してインストールが開始されます。 Git Bashを開いて以下のコマンドを入力してユーザーの設定をします。 &br; git config --global user.name git config --global user.email [[だいたい使うコマンド一覧:https://qiita.com/myalpine/items/84f983d3c93c373e77be]] *フレームワーク [#f45892c1] **mybatis[#ea99b799] <?xml version="1.0" encoding="UTF-8"?> 作成したxmlファイルにmybatisを使うための設定をします。 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> Mapperを指定します。 <mapper namespace="com.example.demo.mapper.UserMapper"> 検索結果をデータ型に変換するためクラスをresultTypeで指定する <select id="findUser" resultType="com.example.demo.entity.User"> select user_id,user_name from m_user; </select> </mapper> parameterTypeはinsert文でvalueの値やupdateでsetする値を指定するときに使う。 **Spring [#b68c10c5] [[こちらのサイト参考に:https://learning-collection.com/springboot%e5%85%a5%e9%96%80/]]だいたい覚えました。 ***アノテーション [#e5a17a0a] &br;@RequestParam URLに含まれるクエリパラメータを受け取ることができる &br;@Autowired 外部から呼び出して自動的に初期化してくれる。 &br;@PathVariable @GetMappingで指定したメソッドの引数につけると、URLに含まれる動的なパラメータを受け取ることができます。 &br;@ModelAttribute コントローラーの引数につけて使う HTMLのフィールド属性から値を取得することができる &br;@Data クラスに@Getter、@Setter、@RequiredArgsConstructor、@EqualsAndHashCode、@ToStringを指定したことと同じ作用になります。 &br;@Mapper Mapperを定義するために必要なアノテーション 定義する場所はインターフェースです。 &br;@Controller MVCパターンのCの役割を担うコンポーネント。このアノテーションを付与したコンポーネントでは、クライアントからのリクエスト/レスポンスに関わる処理をする。 &br;@Service ビジネスロジックを実装するコンポーネントであることを表すアノテーション。 &br;@Repository データの永続化に関わる処理を提供するコンポーネント。ORMなどを利用して、データのCRUD処理を実装する。 &br;@Component 上記3つに当てはまらないコンポーネント。ユーティリティクラスなどに付与する。 &br;@Configuration クラス宣言の前に記述します。このアノテーションは、このクラスがBeanの設定を行うものであることを示します。Bean設定クラスには常にこれをつけます。 Controllerクラスに書かれている@〇〇Mappingとは 簡単に言うとSpringBootの外部からのアクションに対するプログラムの処理の入り口です。 @RequestMappingは全体の処理 使い方はクラスの頭に付ける ※クラス内での@RequestMappingは避けたい@GetMappingも@PostMapping両方できてしまうため読んでいてわかりづらい @GetMappingは取得の処理 登録しているデータを取得したりします。 @PostMappingは投稿の処理 新しいデータを登録したりします。 ***画像 [#t24ee141] base64形式のメリット &br;base64処理を用いるメリットとしては、画像ファイルをbase64に変換すると文字列になりますので、サーバーにデータを送信する場合などに元のバイナリデータのままよりも、処理が単純になります。 &br;また、base64エンコードされた画像はウェブページに直接埋め込むこともできます。 application.propertiesの設定 max-file-size...................................1ファイルにおける最大バイト数 &br;max-request-size ...............................(複数アップロード時の)1リクエストにおける最大バイト数 spring.servlet.multipart.max-file-size=10MB spring.servlet.multipart.max-request-size=30MB 「org.springframework.web.multipart.multipartfile」というインタフェースでアップロードしたファイルを受け取る。 import org.springframework.web.multipart.MultipartFile; import lombok.Data; @Data public class File { private byte[] fileName; private MultipartFile uploadFile; } HTML フォームの設定 「enctype="multipart/form-data"」を忘れないようにする。これを設定しないと(HTML仕様上)ファイルの中身が送信されない。 <form th:action="@{/upload}" method="post" enctype="multipart/form-data"> HTMLから受け取ったファイルの処理 controller データベースに追加するときはbyte[]の変数からBLOB型のカラムへ格納 import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.security.NoSuchAlgorithmException; import java.util.Base64; // htmlからファイル名を受け取る 今回はjava.png String fileName = uploadFile.getImage().getOriginalFilename(); // 受け取ったファイル名(String)からbute[]に変換し、ファイルの形式をpngからBase64形式に変換 Charset charset = StandardCharsets.UTF_8; byte[] encode = Base64.getEncoder().encode(fileName.getBytes(charset)); // フォルダを作成する場所を指定 ※パスは各自変更 Path path = Paths.get(""); // ファイルの転送先 + ファイル Path transferTarget = Paths.get("" + addFileName); try{ // 転送するフォルダの作成 Files.createDirectory(path); // メソッドを呼び出して転送する uploadFile.getImage().transferTo(transferTarget); }catch(IOException e){ System.out.println(e); } 画面に出力させる処理 controller // データベースからファイルを受け取る byte[] b = encodeFile.getFile_name(); // Base64形式から元の形式に(.png)に戻す byte[] decode = Base64.getDecoder().decode(b); // byte[]から元の文字に戻す(java.png) Charset charset = StandardCharsets.UTF_8; String strDecode = new String(decode,charset); HTMLで保存してあるフォルダを指定して画像を表示させる <img th:src = "'/images/'+${decodefile}"> *Thymeleaf [#v61b6007] HTML5などのテンプレートエンジン メリットとしては変数の部分を属性値で記述しているため、ブラウザで表示しても崩れないのが大きい &br;[[使い方はこちらを参考に:https://qiita.com/opengl-8080/items/eb3bf3b5301bae398cc2]] *返却期限の表示 [#e02985d7] この機能はJava Scriptを使って実現させます。 /** * 返却期限の表示処理の内容 * 期限が過ぎた書籍の返却期限は赤色で表示します。 * 期限が過ぎていない書籍は黄色で表示します。 */ // ページ読み込み時に実行処理 window.onload = function() { const elements = document.getElementsByClassName('class'); //現在の日付を取得します let now_date = new Date(); let comparison_date = now_date.getFullYear() + "/" + (now_date.getMonth() + 1) + "/" + (now_date.getDate() - 2); /* 関数の引数に書籍の返却予定日と書籍ID HTMLのname属性には返却予定日を格納してid属性には書籍IDを格納しています*/ function comparison(name, id) { // 返却期限が過ぎている時 if (new Date(comparison_date) > new Date(name)) { let book_object = document.getElementById(id); book_object.style.backgroundColor = '#ff2020'; } // 返却期限が過ぎていない時 else { let book_object = document.getElementById(id); book_object.style.backgroundColor = '#fff450'; } } // 借りている書籍の数だけ処理をする for (let step = 0; step < elements.length; step++) { comparison(elements[step].name, elements[step].id); } } *モーダルウィンドウ [#u84b8a83] jQueryを使った作成方法 HTMLはこんな感じです。 <link rel="stylesheet" href="/css/****.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> <script src="/js/****.js"></script> <button type = "button" class = "modal-button"></button> <div id="modal-content"> <p>モーダルウィンドウに表示されます。</p> </div> CSSにはオーバーレイとモーダルの設定を書きます。 #modal-content { width: 50% ; height: 50% ; margin: 0 ; padding: 10px 20px ; border: 2px solid #aaa ; background: #fff ; position: fixed ; display: none ; z-index: 2 ; } #modal-overlay { z-index: 1 ; display: none ; position: fixed ; top: 0 ; left: 0 ; width: 100% ; height: 120% ; background-color: rgba( 0,0,0, 0.75 ) ; } jQueryにはオーバレイとモーダルの操作を書きます。 $(function() { $('.modal-button').click(function() { /*キーボード操作などにより、オーバーレイが多重起動するのを防止する ボタンからフォーカスを外す*/ $(this).blur(); //新しくモーダルウィンドウを起動しない if ($("#modal-overlay")[0]) return false; //オーバーレイを出現させる $("body").append('<div id="modal-overlay"></div>'); $("#modal-overlay").fadeIn("slow"); //モーダルウィンドウをセンタリングする centeringModalSyncer(); //モーダルウィンドウをフェードインする $("#modal-content").fadeIn("slow"); //[#modal-overlay]をクリック $("#modal-overlay).unbind().click(function() { //[#modal-content]と[#modal-overlay]をフェードアウト $("#modal-content,#modal-overlay").fadeOut("slow", function() { //[#modal-overlay]を削除する $('#modal-overlay').remove(); }); }); }); //リサイズされたら、センタリングをする関数[centeringModalSyncer()]を実行する $(window).resize(centeringModalSyncer); //画面(ウィンドウ)の幅、高さを取得 const w = $(window).width(); const h = $(window).height(); //センタリングを実行する関数 function centeringModalSyncer() { // モーダルウィンドウ(#modal-content)の幅、高さを取得 const cw = $("#modal-content").outerWidth(); const ch = $("#modal-content").outerHeight(); //センタリングを実行する $("#modal-content").css({ "left": ((w - cw) / 2) + "px", "top": ((h - ch) / 2) + "px" }); } }); ボタンを押してモーダルウィンドウを表示し、画面外を押して閉じれば成功です。 *Spring Security [#dc361df8] **ログインページの作成 [#x82f74e9] Spring Securityの依存性を注入するとアプリケーションを起動した際にSpring Securityのデフォルトのログイン画面が表示されるようになります。 &br;まずは、自前で作成したログイン画面を表示させたいので 適当に作成したHTMLをcontrollerクラスのgetmappingで呼びます。 &br;次に、javaconfigで設定を行います。 設定を行うためのwebsecurityconfigクラスを作成します。このクラスは、websecurityconfigureradapterを継承します。 import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter{ @Override public void configure(WebSecurity web) throws Exception { // spring securityで無視するリクエストパスを設定 / **より下の階層は自由にアクセス可能 web.ignoring().antMatchers("/css/**", "/images/**", "/js/**"); } @Override protected void configure(HttpSecurity http) throws Exception { /*ログインページ ログインのアクション 認証するときのパラメーター 認証成功時の遷移先 ログアウトのアクション ログアウト成功時のURL cookieの削除 セッションを無効にする*/ http.formLogin() .loginPage("/login/form") .loginProcessingUrl("/signin") .usernameParameter("mailaddress") .passwordParameter("password") .defaultSuccessUrl("/mypage") .and() .logout() .logoutRequestMatcher(new AntPathRequestMatcher("/signout")) .logoutSuccessUrl("/login/form") .deleteCookies("JSESSIONID") .invalidateHttpSession(true) .permitAll(); //ログイン前に許可する処理 http.authorizeRequests() .antMatchers("/user/add").permitAll() .antMatchers("/login/change/password").permitAll() .anyRequest().authenticated(); } @Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } } ハッシュ化の方式はbcryptpasswordencoderを用いたいのでbcryptpasswordencoderをjavaconfigでbeanに追加します。 ここまで完了すると自作したログインページが表示されるようになります。 **ハッシュ化 [#yed31014] 新規ユーザー作成画面からパスワードの入力フォームに入力された文字をcontrollerクラスで取得します。 serviceクラスにパスワードをハッシュ化するメソッドを作成します。 import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; @Autowired PasswordEncoder passwordEncoder; public void hashPassword(String password) { passwordEncoder.encode(password); } controllerにserviceで作成したメソッド呼び出し取得した文字を引数に渡してハッシュ化させて登録します。 &br;データベースに登録したユーザーのパスワードがハッシュ化されているか確認してください。 **ユーザー認証 [#yf911960] userテーブルからユーザーを取得するmapperを書きます。 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.mapper.UserMapper"> <select id="findUser" resultType="com.example.demo.entity.User"> select user_id,user_name,mailaddress,password,admin_flg,isdeleted from m_user where mailaddress = #{mailaddress}; </select> </mapper> @Mapper public interface UserMapper { public Optional<User>findUser(String mailaddress); } ユーザーを照合するクラスを書きます。 import java.util.ArrayList; import java.util.Collection; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import lombok.Data; @Data public class LoginUserDetailsImpl implements UserDetails{ private User loginUser; private Collection<GrantedAuthority>authorities; public LoginUserDetailsImpl(User loginUser) { this.loginUser = loginUser; String role = null; if(loginUser.getAdmin_flg() == 1) { role = "ADMIN"; }else if(loginUser.getAdmin_flg() == 0) { role = "USER"; } this.authorities = new ArrayList<>(); this.authorities.add(new SimpleGrantedAuthority("ROLE_" + role)); } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return authorities; } @Override public String getPassword() { return loginUser.getPass(); } @Override public String getUsername() { return loginUser.getUser_name(); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { if(loginUser.getIsdeleted() == 1) { return false; } return true; } } ログイン画面から直接URL書き換えて遷移しないようにloginconfigクラスを作成します。 import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class LoginConfig implements WebMvcConfigurer{ public void addViewContorllers(ViewControllerRegistry registry) { registry.addViewController("/login/form").setViewName("/pages/login_form"); } } *junit [#u16feb79] 今回はjunit5を使ってテストしました。 調べてみるとjunit4でテストを書いているのを多く見かけるのでリンク参照 [[junit5のメリット:https://parasoft.techmatrix.jp/repeating-the-benefits-of-junit-5]] [[junit5のアノテーション:https://blogs.oracle.com/otnjp/migrating-from-junit-4-to-junit-5-important-differences-and-benefits-ja]] アノテーション @Testはテストケースを宣言するために使用します。 @AutoConfigureMockMvcコントローラ層のモック(MockMvc)を作成でき、これでコントローラのJUnitテストが可能になる モックとは、クラスの動作を意図的に設定し、擬似的シミュレートするためのオブジェクトの事を指します。 @WithUserDetailsはUserDetailsServiceからユーザー情報を取得して認証情報を設定するためのアノテーション 画面テスト //コントローラクラスのメソッド @GetMapping("/home") public ModelAndView index(ModelAndView mav) { mav.setViewName("index"); return mav; } ※コントローラクラスに画面を呼び出すメソッドをString型で作成されているのはよく見かけますが 戻り値が文字列として認識してエラーになります。動作自体は問題ないです。 テストする際はModelAndViewを使ってテストします。 //テストクラスのメソッド @Test public void getIndexTest() throws Exception { mockMvc.perform(get("/home")) .andExpect(status().isOk()) .andExpect(view().name("index")); } ログインとmapperのテスト package com.example.demo; import static org.junit.jupiter.api.Assertions.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.test.context.support.WithUserDetails; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import com.example.demo.mapper.EmployeeMapper; import com.example.demo.model.Employee; @SpringBootTest @AutoConfigureMockMvc class ApplicationTests { @Autowired MockMvc mockMvc; @Autowired EmployeeMapper employeeMapper; // データベースアクセス処理テスト @Test public void findOneTest() { Employee e = new Employee(); e = employeeMapper.findOne("testemail@gmail.com"); assertEquals("testname", e.getName()); } // 認証テスト @Test @WithUserDetails(value = "testemail@gmail.com") public void certificationTest() throws Exception { // 認証情報を取得 Authentication auth = SecurityContextHolder .getContext().getAuthentication(); String message = "class = " + auth.getClass() + "\n" + "name = " + auth.getName() + "\n" + "credentials = " + auth.getCredentials() + "\n" + "authorities = " + auth.getAuthorities() + "\n" + "principal = " + auth.getPrincipal() + "\n" + "details = " + auth.getDetails(); // 今回は確認のために標準出力しているだけ(ここまで本来は不要らしいです。) System.out.println(message); // モックを使用してテスト対象のURL(ログイン成功画面)にアクセスする MvcResult mvcResult = mockMvc.perform(get("/home/view")).andReturn(); // ユーザ認証許可する設定のためアクセス可能であることを確認 assertEquals("homepage", mvcResult.getModelAndView().getViewName()); } }
タイムスタンプを変更しない
[[FrontPage]] &size(20){目次}; #contents(level=1) *スケジュール作成サンプル [#i6862607] #ref(./EL-BOOK ワークフロー サンプル.xlsx,80%); *コーディング作業が楽になるショートカットの一覧 [#i6862607] [[Windows:https://dekiru.net/article/18619/]] [[Eclipse:https://www.casleyconsulting.co.jp/blog/engineer/172/]] 覚えておくと良いこと &br;ファイル保存 [Ctrl + S] &br;全てを保存 [Ctrl + Shift + S] &br;文字列検索 [Ctrl + F] &br;コピー[Ctrl + C] ペースト [Ctrl + V] &br;候補[Ctrl + Space] *設計書作成 [#x48eecb0] **機能一覧表 [#l9240598] #ref(./function_list.png,80%); **画面構成 [#c3141316] #ref(./view.png,80%); **テーブル定義書 [#t0ef638c] テーブル定義書とはテーブルを作成するための設計書です。データベースにテーブルを定義するためのDDL文を作成するために必要な設計書ということです。 &br; &ref(./table.png,80%); **テスト仕様書 [#wc39b0f7] |画面|区分1|区分2|確認項目|結果|h |ログイン|テキストボックス|メールアドレス|文字が入力できること&br();必須項目になっていること|OK| |~|~|パスワード|文字が入力できること&br();必須項目になっていること&br();入力したときに***で隠れていること|NG| **ER図 [#f1d67711] [[ER図とは:https://it-koala.com/entity-relationship-diagram-1897]] #ref(./er.png,80%); **クラス図 [#feca588a] #ref(./uml_line.png,80%); &br;多重度はそのクラスのインスタンスが何個関連を持つかを表します。表記法としては以下の3パターンを覚えておけば十分でしょう。n..m:n以上m以下n..*:n以上n , m:n個またはm個 #ref(class.png); **シーケンス図 [#l0ee201a] Visual Studio Codeを開きます。 左側のメニューに拡張機能があるので PlantUMLと入力してください &br;検索すると一番上に出てくると思うのでクリックしてインストールします。 インストールが終えたら &br;左上のメニューにあるファイルから新規作成を選択してください。 Untitled-1が作成されるのでCTRL + SHIFT + S を押します。 &br;任意のファイル名を入力し、ファイルの種類をPlantUMLに選択して保存します。 .wsdという形式のファイルができればOKです。 下記がUMLのサンプルになります。 @startuml Update mainframe ユーザー編集 actor User participant "ユーザー一覧画面" as View participant "編集モーダル" as Modal participant "エンコード" as encode participant "更新処理" as Update database "データベース" as DB alt 権限あり User -> View : 編集したい activate View else 権限なし User <-- View : エラー end View -> Modal : 一覧から選択する activate Modal Modal <-- DB : ユーザーID,変更前の名前,メールアドレス,パスワード activate DB Modal -> Update : 入力(名前,メールアドレス) activate Update Modal -> encode : 入力(パスワード) deactivate Modal activate encode encode -> Update : 暗号化したパスワード deactivate encode Update -> DB :更新 deactivate Update View <-- DB : 更新したユーザー情報を反映 deactivate DB deactivate View @enduml &br;ALT+Dを押すとプレビューに図が表示されます。 &br;図を画像ファイルとして保存したい場合は ファイル内で右クリックすると ファイル内のダイアグラムをエクスポートとあるのでクリックします。 &br;pngを選択するとのファイルを作成した場所にフォルダが作成されているのでフォルダ内に画像ファイルがあります。 *github[#q8a7110e] Git Hubのアカウント作成 以下のリンクから作成してください &br;[[アカウント作成:https://github.com/]] &br;ユーザー名とメールアドレスとパスワードを入力して登録します。 無料版であるfreeを選択してContinue押して作成されます。 Git Bashのダウンロード~インストールまで 下記からサイトへ移動してDownloadボタンを押します。 Git Bashの[[ダウンロード:https://gitforwindows.org/]] インストーラーを起動してセットアップをおこないます。 最初のウィンドウからNextを押して進みます。 &br;Git Bash Hereにチェックが付いていることを確認して Next &br;Use Git from the Windows Command Promptを選択して Next &br;Use the OpenSSL libraryを選択して Next &br;Checkout Windows-style,commit Unix-style line endingsを選択して Next &br;Use MinTTY(the default terminal of MSYS2)を選択して Next &br;Enable file system cachingとEnable Git Credential Managerにチェックを入れて Next &br;いくつかチェックボックスがありますが入れずにNextを押してインストールが開始されます。 Git Bashを開いて以下のコマンドを入力してユーザーの設定をします。 &br; git config --global user.name git config --global user.email [[だいたい使うコマンド一覧:https://qiita.com/myalpine/items/84f983d3c93c373e77be]] *フレームワーク [#f45892c1] **mybatis[#ea99b799] <?xml version="1.0" encoding="UTF-8"?> 作成したxmlファイルにmybatisを使うための設定をします。 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> Mapperを指定します。 <mapper namespace="com.example.demo.mapper.UserMapper"> 検索結果をデータ型に変換するためクラスをresultTypeで指定する <select id="findUser" resultType="com.example.demo.entity.User"> select user_id,user_name from m_user; </select> </mapper> parameterTypeはinsert文でvalueの値やupdateでsetする値を指定するときに使う。 **Spring [#b68c10c5] [[こちらのサイト参考に:https://learning-collection.com/springboot%e5%85%a5%e9%96%80/]]だいたい覚えました。 ***アノテーション [#e5a17a0a] &br;@RequestParam URLに含まれるクエリパラメータを受け取ることができる &br;@Autowired 外部から呼び出して自動的に初期化してくれる。 &br;@PathVariable @GetMappingで指定したメソッドの引数につけると、URLに含まれる動的なパラメータを受け取ることができます。 &br;@ModelAttribute コントローラーの引数につけて使う HTMLのフィールド属性から値を取得することができる &br;@Data クラスに@Getter、@Setter、@RequiredArgsConstructor、@EqualsAndHashCode、@ToStringを指定したことと同じ作用になります。 &br;@Mapper Mapperを定義するために必要なアノテーション 定義する場所はインターフェースです。 &br;@Controller MVCパターンのCの役割を担うコンポーネント。このアノテーションを付与したコンポーネントでは、クライアントからのリクエスト/レスポンスに関わる処理をする。 &br;@Service ビジネスロジックを実装するコンポーネントであることを表すアノテーション。 &br;@Repository データの永続化に関わる処理を提供するコンポーネント。ORMなどを利用して、データのCRUD処理を実装する。 &br;@Component 上記3つに当てはまらないコンポーネント。ユーティリティクラスなどに付与する。 &br;@Configuration クラス宣言の前に記述します。このアノテーションは、このクラスがBeanの設定を行うものであることを示します。Bean設定クラスには常にこれをつけます。 Controllerクラスに書かれている@〇〇Mappingとは 簡単に言うとSpringBootの外部からのアクションに対するプログラムの処理の入り口です。 @RequestMappingは全体の処理 使い方はクラスの頭に付ける ※クラス内での@RequestMappingは避けたい@GetMappingも@PostMapping両方できてしまうため読んでいてわかりづらい @GetMappingは取得の処理 登録しているデータを取得したりします。 @PostMappingは投稿の処理 新しいデータを登録したりします。 ***画像 [#t24ee141] base64形式のメリット &br;base64処理を用いるメリットとしては、画像ファイルをbase64に変換すると文字列になりますので、サーバーにデータを送信する場合などに元のバイナリデータのままよりも、処理が単純になります。 &br;また、base64エンコードされた画像はウェブページに直接埋め込むこともできます。 application.propertiesの設定 max-file-size...................................1ファイルにおける最大バイト数 &br;max-request-size ...............................(複数アップロード時の)1リクエストにおける最大バイト数 spring.servlet.multipart.max-file-size=10MB spring.servlet.multipart.max-request-size=30MB 「org.springframework.web.multipart.multipartfile」というインタフェースでアップロードしたファイルを受け取る。 import org.springframework.web.multipart.MultipartFile; import lombok.Data; @Data public class File { private byte[] fileName; private MultipartFile uploadFile; } HTML フォームの設定 「enctype="multipart/form-data"」を忘れないようにする。これを設定しないと(HTML仕様上)ファイルの中身が送信されない。 <form th:action="@{/upload}" method="post" enctype="multipart/form-data"> HTMLから受け取ったファイルの処理 controller データベースに追加するときはbyte[]の変数からBLOB型のカラムへ格納 import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.security.NoSuchAlgorithmException; import java.util.Base64; // htmlからファイル名を受け取る 今回はjava.png String fileName = uploadFile.getImage().getOriginalFilename(); // 受け取ったファイル名(String)からbute[]に変換し、ファイルの形式をpngからBase64形式に変換 Charset charset = StandardCharsets.UTF_8; byte[] encode = Base64.getEncoder().encode(fileName.getBytes(charset)); // フォルダを作成する場所を指定 ※パスは各自変更 Path path = Paths.get(""); // ファイルの転送先 + ファイル Path transferTarget = Paths.get("" + addFileName); try{ // 転送するフォルダの作成 Files.createDirectory(path); // メソッドを呼び出して転送する uploadFile.getImage().transferTo(transferTarget); }catch(IOException e){ System.out.println(e); } 画面に出力させる処理 controller // データベースからファイルを受け取る byte[] b = encodeFile.getFile_name(); // Base64形式から元の形式に(.png)に戻す byte[] decode = Base64.getDecoder().decode(b); // byte[]から元の文字に戻す(java.png) Charset charset = StandardCharsets.UTF_8; String strDecode = new String(decode,charset); HTMLで保存してあるフォルダを指定して画像を表示させる <img th:src = "'/images/'+${decodefile}"> *Thymeleaf [#v61b6007] HTML5などのテンプレートエンジン メリットとしては変数の部分を属性値で記述しているため、ブラウザで表示しても崩れないのが大きい &br;[[使い方はこちらを参考に:https://qiita.com/opengl-8080/items/eb3bf3b5301bae398cc2]] *返却期限の表示 [#e02985d7] この機能はJava Scriptを使って実現させます。 /** * 返却期限の表示処理の内容 * 期限が過ぎた書籍の返却期限は赤色で表示します。 * 期限が過ぎていない書籍は黄色で表示します。 */ // ページ読み込み時に実行処理 window.onload = function() { const elements = document.getElementsByClassName('class'); //現在の日付を取得します let now_date = new Date(); let comparison_date = now_date.getFullYear() + "/" + (now_date.getMonth() + 1) + "/" + (now_date.getDate() - 2); /* 関数の引数に書籍の返却予定日と書籍ID HTMLのname属性には返却予定日を格納してid属性には書籍IDを格納しています*/ function comparison(name, id) { // 返却期限が過ぎている時 if (new Date(comparison_date) > new Date(name)) { let book_object = document.getElementById(id); book_object.style.backgroundColor = '#ff2020'; } // 返却期限が過ぎていない時 else { let book_object = document.getElementById(id); book_object.style.backgroundColor = '#fff450'; } } // 借りている書籍の数だけ処理をする for (let step = 0; step < elements.length; step++) { comparison(elements[step].name, elements[step].id); } } *モーダルウィンドウ [#u84b8a83] jQueryを使った作成方法 HTMLはこんな感じです。 <link rel="stylesheet" href="/css/****.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> <script src="/js/****.js"></script> <button type = "button" class = "modal-button"></button> <div id="modal-content"> <p>モーダルウィンドウに表示されます。</p> </div> CSSにはオーバーレイとモーダルの設定を書きます。 #modal-content { width: 50% ; height: 50% ; margin: 0 ; padding: 10px 20px ; border: 2px solid #aaa ; background: #fff ; position: fixed ; display: none ; z-index: 2 ; } #modal-overlay { z-index: 1 ; display: none ; position: fixed ; top: 0 ; left: 0 ; width: 100% ; height: 120% ; background-color: rgba( 0,0,0, 0.75 ) ; } jQueryにはオーバレイとモーダルの操作を書きます。 $(function() { $('.modal-button').click(function() { /*キーボード操作などにより、オーバーレイが多重起動するのを防止する ボタンからフォーカスを外す*/ $(this).blur(); //新しくモーダルウィンドウを起動しない if ($("#modal-overlay")[0]) return false; //オーバーレイを出現させる $("body").append('<div id="modal-overlay"></div>'); $("#modal-overlay").fadeIn("slow"); //モーダルウィンドウをセンタリングする centeringModalSyncer(); //モーダルウィンドウをフェードインする $("#modal-content").fadeIn("slow"); //[#modal-overlay]をクリック $("#modal-overlay).unbind().click(function() { //[#modal-content]と[#modal-overlay]をフェードアウト $("#modal-content,#modal-overlay").fadeOut("slow", function() { //[#modal-overlay]を削除する $('#modal-overlay').remove(); }); }); }); //リサイズされたら、センタリングをする関数[centeringModalSyncer()]を実行する $(window).resize(centeringModalSyncer); //画面(ウィンドウ)の幅、高さを取得 const w = $(window).width(); const h = $(window).height(); //センタリングを実行する関数 function centeringModalSyncer() { // モーダルウィンドウ(#modal-content)の幅、高さを取得 const cw = $("#modal-content").outerWidth(); const ch = $("#modal-content").outerHeight(); //センタリングを実行する $("#modal-content").css({ "left": ((w - cw) / 2) + "px", "top": ((h - ch) / 2) + "px" }); } }); ボタンを押してモーダルウィンドウを表示し、画面外を押して閉じれば成功です。 *Spring Security [#dc361df8] **ログインページの作成 [#x82f74e9] Spring Securityの依存性を注入するとアプリケーションを起動した際にSpring Securityのデフォルトのログイン画面が表示されるようになります。 &br;まずは、自前で作成したログイン画面を表示させたいので 適当に作成したHTMLをcontrollerクラスのgetmappingで呼びます。 &br;次に、javaconfigで設定を行います。 設定を行うためのwebsecurityconfigクラスを作成します。このクラスは、websecurityconfigureradapterを継承します。 import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter{ @Override public void configure(WebSecurity web) throws Exception { // spring securityで無視するリクエストパスを設定 / **より下の階層は自由にアクセス可能 web.ignoring().antMatchers("/css/**", "/images/**", "/js/**"); } @Override protected void configure(HttpSecurity http) throws Exception { /*ログインページ ログインのアクション 認証するときのパラメーター 認証成功時の遷移先 ログアウトのアクション ログアウト成功時のURL cookieの削除 セッションを無効にする*/ http.formLogin() .loginPage("/login/form") .loginProcessingUrl("/signin") .usernameParameter("mailaddress") .passwordParameter("password") .defaultSuccessUrl("/mypage") .and() .logout() .logoutRequestMatcher(new AntPathRequestMatcher("/signout")) .logoutSuccessUrl("/login/form") .deleteCookies("JSESSIONID") .invalidateHttpSession(true) .permitAll(); //ログイン前に許可する処理 http.authorizeRequests() .antMatchers("/user/add").permitAll() .antMatchers("/login/change/password").permitAll() .anyRequest().authenticated(); } @Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } } ハッシュ化の方式はbcryptpasswordencoderを用いたいのでbcryptpasswordencoderをjavaconfigでbeanに追加します。 ここまで完了すると自作したログインページが表示されるようになります。 **ハッシュ化 [#yed31014] 新規ユーザー作成画面からパスワードの入力フォームに入力された文字をcontrollerクラスで取得します。 serviceクラスにパスワードをハッシュ化するメソッドを作成します。 import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; @Autowired PasswordEncoder passwordEncoder; public void hashPassword(String password) { passwordEncoder.encode(password); } controllerにserviceで作成したメソッド呼び出し取得した文字を引数に渡してハッシュ化させて登録します。 &br;データベースに登録したユーザーのパスワードがハッシュ化されているか確認してください。 **ユーザー認証 [#yf911960] userテーブルからユーザーを取得するmapperを書きます。 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.mapper.UserMapper"> <select id="findUser" resultType="com.example.demo.entity.User"> select user_id,user_name,mailaddress,password,admin_flg,isdeleted from m_user where mailaddress = #{mailaddress}; </select> </mapper> @Mapper public interface UserMapper { public Optional<User>findUser(String mailaddress); } ユーザーを照合するクラスを書きます。 import java.util.ArrayList; import java.util.Collection; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import lombok.Data; @Data public class LoginUserDetailsImpl implements UserDetails{ private User loginUser; private Collection<GrantedAuthority>authorities; public LoginUserDetailsImpl(User loginUser) { this.loginUser = loginUser; String role = null; if(loginUser.getAdmin_flg() == 1) { role = "ADMIN"; }else if(loginUser.getAdmin_flg() == 0) { role = "USER"; } this.authorities = new ArrayList<>(); this.authorities.add(new SimpleGrantedAuthority("ROLE_" + role)); } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return authorities; } @Override public String getPassword() { return loginUser.getPass(); } @Override public String getUsername() { return loginUser.getUser_name(); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { if(loginUser.getIsdeleted() == 1) { return false; } return true; } } ログイン画面から直接URL書き換えて遷移しないようにloginconfigクラスを作成します。 import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class LoginConfig implements WebMvcConfigurer{ public void addViewContorllers(ViewControllerRegistry registry) { registry.addViewController("/login/form").setViewName("/pages/login_form"); } } *junit [#u16feb79] 今回はjunit5を使ってテストしました。 調べてみるとjunit4でテストを書いているのを多く見かけるのでリンク参照 [[junit5のメリット:https://parasoft.techmatrix.jp/repeating-the-benefits-of-junit-5]] [[junit5のアノテーション:https://blogs.oracle.com/otnjp/migrating-from-junit-4-to-junit-5-important-differences-and-benefits-ja]] アノテーション @Testはテストケースを宣言するために使用します。 @AutoConfigureMockMvcコントローラ層のモック(MockMvc)を作成でき、これでコントローラのJUnitテストが可能になる モックとは、クラスの動作を意図的に設定し、擬似的シミュレートするためのオブジェクトの事を指します。 @WithUserDetailsはUserDetailsServiceからユーザー情報を取得して認証情報を設定するためのアノテーション 画面テスト //コントローラクラスのメソッド @GetMapping("/home") public ModelAndView index(ModelAndView mav) { mav.setViewName("index"); return mav; } ※コントローラクラスに画面を呼び出すメソッドをString型で作成されているのはよく見かけますが 戻り値が文字列として認識してエラーになります。動作自体は問題ないです。 テストする際はModelAndViewを使ってテストします。 //テストクラスのメソッド @Test public void getIndexTest() throws Exception { mockMvc.perform(get("/home")) .andExpect(status().isOk()) .andExpect(view().name("index")); } ログインとmapperのテスト package com.example.demo; import static org.junit.jupiter.api.Assertions.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.test.context.support.WithUserDetails; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import com.example.demo.mapper.EmployeeMapper; import com.example.demo.model.Employee; @SpringBootTest @AutoConfigureMockMvc class ApplicationTests { @Autowired MockMvc mockMvc; @Autowired EmployeeMapper employeeMapper; // データベースアクセス処理テスト @Test public void findOneTest() { Employee e = new Employee(); e = employeeMapper.findOne("testemail@gmail.com"); assertEquals("testname", e.getName()); } // 認証テスト @Test @WithUserDetails(value = "testemail@gmail.com") public void certificationTest() throws Exception { // 認証情報を取得 Authentication auth = SecurityContextHolder .getContext().getAuthentication(); String message = "class = " + auth.getClass() + "\n" + "name = " + auth.getName() + "\n" + "credentials = " + auth.getCredentials() + "\n" + "authorities = " + auth.getAuthorities() + "\n" + "principal = " + auth.getPrincipal() + "\n" + "details = " + auth.getDetails(); // 今回は確認のために標準出力しているだけ(ここまで本来は不要らしいです。) System.out.println(message); // モックを使用してテスト対象のURL(ログイン成功画面)にアクセスする MvcResult mvcResult = mockMvc.perform(get("/home/view")).andReturn(); // ユーザ認証許可する設定のためアクセス可能であることを確認 assertEquals("homepage", mvcResult.getModelAndView().getViewName()); } }
テキスト整形のルールを表示する