todoAppの作成

49085 ワード

返されるタイプは2種類あります
  • 内部移動アドレス.("/model2-todo.home.hta")
  • 再要求されたアドレス.("redirect:/model2-todo.home.hta")
  • mapを使用すると、Front Controlのif文を削除できます.
    FrontController_if.ver
    
    @WebServlet("*.hta")
    public class FrontControllerServlet extends HttpServlet {
    
    	@Override
    	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		
    		// 웹 애플리케이션의 ContextPath를 조회한다.
    		// ContextPath는 웹 애플리케이션을 식별하는 이름이다.
    		// 특별히 지정하지않으면 프로젝트이름이 contextPath가 된다.
    		// Tomcat에 배포된 여러 웹애플리케이션은 서로 다른 contextPath를 가지며, contextPath가 웹 애플리케이션 프로젝트를 구분하는 식별자가 된다.
    		String contextPath = request.getContextPath();
    		
    		// 클라이언트의 요청URI를 조회한다.
    		String requestURI = request.getRequestURI();
    		requestURI = requestURI.replace(contextPath, "");
    		System.out.println("요청URI [" + requestURI + "]");
    		
    		// 요청URI에 해당하는 컨트롤러 객체를 생성하고 실행시킨다.
    		try {
    			if ("/home.hta".equals(requestURI)) {
    				new HomeController().execute(request, response);
    
    			} else if ("/registerform.hta".equals(requestURI)) {
    				new RegisterFormController().execute(request, response);
    				
    			} else if ("/register.hta".equals(requestURI)) {
    				new RegisterController().execute(request, response);
    				
    			} else if ("/loginform.hta".equals(requestURI)) {
    				new LoginFormController().execute(request, response);
    				
    			} else if ("/login.hta".equals(requestURI)) {
    				new LoginController().execute(request, response);
    				
    			} else if ("/logout.hta".equals(requestURI)) {
    				new LogoutController().execute(request, response);
    				
    			} else if ("/el1.hta".equals(requestURI)) {
    				new ElSampleController1().execute(request, response);
    				
    			} else if ("/el2.hta".equals(requestURI)) {
    				new ElSampleController2().execute(request, response);
    				
    			} else if ("/el3.hta".equals(requestURI)) {
    				new ElSampleController3().execute(request, response);
    			
    			} else if ("/jstl1.hta".equals(requestURI)) {
    				new JstlCotroller1().execute(request, response);
    
    			} else if ("/jstl2.hta".equals(requestURI)) {
    				new JstlCotroller2().execute(request, response);
    				
    			} else if ("/jstl3.hta".equals(requestURI)) {
    				new JstlCotroller3().execute(request, response);
    				
    			} else if ("/jstl4.hta".equals(requestURI)) {
    				new JstlCotroller4().execute(request, response);
    				
    			} else if ("/jstl5.hta".equals(requestURI)) {
    				new JstlCotroller5().execute(request, response);
    				
    			}
    		} catch (Exception e) {
    			throw new ServletException(e);
    		}
    	}
    }
    FrontControllerServlet.java
    @WebServlet("*.hta")
    public class FrontControllerServlet extends HttpServlet {
    
    	private static final long serialVersionUID = 339661543186959731L;
    	private Map<String, Controller> controllers = new HashMap<>();
    	
    	public void init() throws ServletException {
    		controllers.put("/home.hta", new HomeController());
    		controllers.put("/loginform.hta", new LoginFormController());
    		controllers.put("/login.hta", new LoginController());
    		controllers.put("/logout.hta", new LogoutController());
    		controllers.put("/todo/list.hta", new TodoListController());
    		controllers.put("/todo/detail.hta", new TodoDetailController());
    		controllers.put("/todo/form.hta", new TodoFormController());
    		controllers.put("/todo/insert.hta", new TodoInsertController());
    		controllers.put("/todo/update.hta", new TodoUpdateController());
    	}
    	
    	@Override
    	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		
    		try {
    			String requestURI = request.getRequestURI().replace(request.getContextPath(), "");
    			Controller controller = controllers.get(requestURI);
    			if (controller == null) {
    				throw new RuntimeException("요청 URI에 대응되는 컨트롤러가 존재하지 않습니다.");
    			}
    			String path = controller.execute(request, response);
    			if (path == null) {
    				throw new RuntimeException("내부이동 혹은 재요청할 경로가 null입니다.");
    			}
    			if (path.startsWith("redirect:")) {
    				response.sendRedirect(path.replace("redirect:", ""));
    			} else {
    				path = "/WEB-INF/views/" + path;
    				request.getRequestDispatcher(path).forward(request, response);
    			}
    			
    		} catch (Exception e) {
    			throw new ServletException(e);
    		}
    	}
    }

  • initメソッドは、要求URIをMapperに格納する.
  • サービス方法では、アドレスウィンドウから受信したuriを含む変数を使用して、コントローラマッパに格納された値をロードする.
  • controllerがnull(ファイルがない場合)の場合、例外処理を行います.
  • コントローラを実行して、文字列形式のpathを返します.
  • コントローラの実行時に返されるパスが空の場合(ファイルが存在しない場合)、異常処理が行われます.
  • コントローラが返すパスがリダイレクト(再要求)で開始されると、リダイレクト(startsWith)が送信される.
  • 先の条件が成立しない場合、WEB-INF/views/後にpath(戻されたjspファイル名)を付けて内部移動する.
  • ログイン画面スキップ
  • Front Controllerからのリクエスト対象はLoginForm ControllerとLoginformです.
  • だからloginformjspのparam.errorが利用可能です.
  • ログイン、ログアウト


    登録、変更、削除は内部移動を必要とせず、再要求URLを送信するだけです.
    機能を実行する際に表示できるものは何もないので
  • 開発手順
  • loginController
  • リクエストオブジェクトからリクエストパラメータ(id、password)をクエリーします.
  • UserDaoのgetUserById(ID)を実行してユーザ情報を問合せます.
  • ユーザー情報がnullの場合は、「redirect:/model 2-todo/loginform.hta?error=notfound」を返します.
  • パスワードが一致しない場合は、「redirect:/model 2-todo/loginform.hta?error=不一致」を返します.
  • ユーザが存在し、パスワードが一致する場合、HttpSessionオブジェクトを取得し、ユーザ情報を「loginUser」属性名でHttpSessionオブジェクトに格納する.
  • 再要求
  • ホームページのURL(「redirect:/model 2-todo/home.hta」)を返します.
  • loginform.jsp
  • c:ifの条件で、idまたはパスワードが一致しないエラータイプごとに異なるアラートが表示されます.
  • navbar.jsp
  • ログインフォームには、c:ifを条件としてログインしているユーザにのみログイン可能なメニューが表示されます.
  • logout.jsp
  • HttpSessionオブジェクト(request.getSession())を取得し、セッションオブジェクト(session.invalidate()を破棄します.
  • 要求
  • ホームページの再要求URLを応答として送信する.
  • 通常のモデル1とは異なり、Redirectに直接応答するのではなく、アドレスを返す必要があります.
    移動の方法も2つあります.1)内部移動2)リダイレクトの再要求
    loginController
    public class LoginController implements Controller {
    
    	@Override
    	public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
    		
    		String id = request.getParameter("id");
    		String password = request.getParameter("password");
    		User user = UserDao.getInstance().getUserById(id);
    		if (user == null) {
    			return "redirect:/model2-todo/loginform.hta?error=notfound";
    		}
    		if (!user.getPassword().equals(password)) {
    			return "redirect:/model2-todo/loginform.hta?error=mismatch";
    		}
    		HttpSession session = request.getSession();
    		session.setAttribute("loginUser", user);
    		
    		return "redirect:/model2-todo/home.hta";
    	}
    }
    loginform.jsp
    <div class="col-8">
    			<c:if test="${param.error eq 'notfound'}">
    			<div class="alert alert-danger mb-3">
    				<strong>아이디 오류</strong> 아이디에 해당하는 사용자가 존재하지 않습니다.
    			</div>
    			</c:if>
    			<c:if test="${param.error eq 'mismatch' }">
    			<div class="alert alert-danger mb-3">
    				<strong>비밀번호 오류</strong> 비밀번호가 일치하지 않습니다.
    			</div>
    			</c:if>
    ログインフォームでは、c:ifの条件で、異なるerrorタイプが表示されます.
    navbar.jsp
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
    			<ul class="navbar-nav me-auto mb-2 mb-lg-0">
    				<li class="nav-item"><a class="nav-link" href="/model2-todo/home.hta"></a></li>
    				<c:if test="${not empty loginUser }">
    					<li class="nav-item"><a class="nav-link" href="/model2-todo/todo/list.hta">일정 목록</a></li>
    					<li class="nav-item"><a class="nav-link" href="/model2-todo/todo/form.hta">일정 등록</a></li>
    				</c:if>		
    			</ul>
    			<ul class="navbar-nav">
    			<c:if test="${empty loginUser }">
    				<li class="nav-item"><a class="nav-link" href="/model2-todo/loginform.hta">로그인</a></li>
    			</c:if>
    			<c:if test="${not empty loginUser }">
    				<li class="nav-item"><a class="nav-link" href="/model2-todo/logout.hta"><strong>홍길동</strong>님 로그아웃</a></li>
    			</c:if>
    			</ul>
    		</div>
    logout.jsp
    public class LogoutController implements Controller {
    
    	@Override
    	public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
    		/*
    		 * 1. HttpSession객체를 획득(request.getSession())해서 session객체를 폐기(session.invalidate())시킨다.
    		 * 2. 홈화면을 요청하는 재요청URL을 응답으로 보낸다.
    		 */
    		HttpSession session = request.getSession();
    		session.invalidate();
    		
    		return "redirect:/model2-todo/home.hta";
    	}
    }
    要求スケジュール登録画面

    新しいスケジュール情報を登録します.(todo insert)
  • リクエストオブジェクトからHttpSessionオブジェクトを取得します.
  • セッション・オブジェクトからログインしたユーザー情報を問合せます.
  • ログインユーザー情報が空の場合は、「redirect:/model 2-todo/loginform.hta?error=required」を返します.
  • todo/form.jspがコミットした値をクエリーします.
    前処理日はjavです.util.日付タイプに変換します.
    DateUtils.ParseDate(日付、「yyy-MM-dd」)
  • Todoオブジェクトを生成してクエリー値を保存します.
    カテゴリ番号、タイトル、前処理日、ユーザー番号、コンテンツをtodoオブジェクトに格納します.
  • Todoオブジェクトをdaoに渡して保存します.
  • 返信要求
  • 画面リストのurl.
  • 要求スケジュール一覧画面

    スクリーンにこぼします.

  • スケジュールリストの表示
    クエリ
  • HttpSession.
  • HttpSessionログインのユーザー情報を問い合せます.
  • ユーザー情報が存在しない場合、ログインフォームへの応答を再要求します.
  • ページ
    クエリ
  • はページ番号を要求し、ない場合は1ページ目
  • クエリ合計
  • Paginationオブジェクト
  • を作成
  • クエリー開始範囲、クエリー終了範囲を取得します.
  • クエリ
  • は、その範囲に属するスケジュールのリストである.
  • Paginationオブジェクトを
  • 要求オブジェクトとして保存する属性
  • リクエストオブジェクトにクエリーされたスケジュールリストを属性
  • として保存します.

  • スケジュールリスト出力→スケジュールリスト画面

  • ページング出力→スケジュールリスト画面

  • ————————————————————————————————————————————

  • todo/detail.hta?No=2&page=1 frontcontrollerに転送します.

  • FrontController→オブジェクトが作成されます.中の小さな物体も小さな橋で持ち上げられます.

  • FrontControllerオブジェクトには、要求パラメータno,pageが含まれます.

  • execute(req,res)を使用してToDoDetailControllerに移動します.

  • TodoDetailController
  • HttpSessionオブジェクトを取得します.
  • 認証されたユーザ情報は、
  • HttpSessionオブジェクトから照会される.
  • ユーザ情報が存在しない場合、ログインフォームを再要求する応答が送信される.
  • 要求パラメータでスケジュール番号を問合せます.
  • スケジュール番号のスケジュール詳細(TodoDto)を問い合せます.
  • クエリ
  • 完全カテゴリリスト(List).
  • クエリ
  • の完全な固定状態リスト(List).
  • 要求オブジェクトには、属性として一定の詳細情報が格納される.
  • カテゴリリスト情報は、属性として
  • リクエストオブジェクトに格納される.
  • 要求オブジェクトには、一定状態リスト情報
  • が属性で格納.
  • の内部を移動するjspページ(todo/detail.jsp)を返します.
  • 属性はFrontControllerに保存されます.

  • todo/detail.jsp
  • スケジュール詳細出力
  • ${todo.no} ${todo.title} ${todo.content}....
  • カテゴリリスト出力

  • ステータスリスト出力

  • は全てスケジュール詳細画面に出力される.
  • Springでは、要求パラメータから値、mybatis、dbアクセス、およびコントローラを抽出することが容易で簡単になり、ロジックの実装に専念できます.