20220520 복습

2022 - 0520 - 복습

< Spring 기초 >




>>> pom.xml
12라인 -> 5.0.7
64라인 -> 1.2.17
116라인 -> 4.12
139라인 -> 3.5.1
141라인 -> 1.8
142라인 -> 1.8
-----------------------------------------------------------------------------------------------------
>>> root-context.xml

<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">

     <property name="driverClassName"
          value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property>
     <property name="jdbcUrl"
          value="jdbc:log4jdbc:oracle:thin:@localhost:1521:XE"></property>
     <property name="username" value="db53"></property>
     <property name="password" value="123456"></property>

</bean>

<!-- HikariCP configuration -->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource"
     destroy-method="close">
          <constructor-arg ref="hikariConfig" />
</bean>

<bean id="sqlSessionFactory"
     class="org.mybatis.spring.SqlSessionFactoryBean">
          <property name="dataSource" ref="dataSource">
</bean>

<mybatis-spring:scan
     base-package="com.jslhrd.mapper" />

<context:component-scan
     base-package="com.jslhrd.service">

-----------------------------------------------------------------------------------------------------
>>> buildpath
mysql-connector-java-8.0.28.jar
ojdbc8.jar
-----------------------------------------------------------------------------------------------------
>>>src/main/resources
log4jdbc.log4j2.properties 파일 생성
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator 내용입력
-----------------------------------------------------------------------------------------------------
>>>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j

@Setter(onMethod_ = @Autowired)
@Select("select sysdate from dual")

@Service // 계층 구조상 주로 비즈니스 영역을 담당하는 객체임을 표시하기 위해 사용함.
@Log4j
@AllArgsConstructor // 생성자를 만들고 자동으로 주입함.

<BoardController.java>
@Controller
@Log4j
@RequestMapping("/board/*")
@AllArgsConstructor

<BoardControllerTests.java>
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration({"file:src/main/webapp/WEB-INF/spring/root-context.xml",
               "file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml"})
@Log4j

>>>Tomcat 더블클릭 - Modules - Edit - controller 부분 지우기
-----------------------------------------------------------------------------------------------------
P.173
>>>Oracle 테이블

사용자 추가 후

system/123456

db53/123456


create user db53 identified by 123456;
grant connect,resource to db53;
grant create view to db53;

create sequence seq_board;

create table tbl_board(
bno number(10,0),
title varchar2(200) not null,
content varchar2(2000) not null,
writer varchar2(50) not null,
regdate date default sysdate,
updatedate date default sysdate
);

create table tbl_member(
userid varchar2(50) not null primary key,
userpw varchar2(100) not null,
username varchar2(100) not null,
regdate date default sysdate,
updatedate date default sysdate,
enabled char(1) default '1');

create table tbl_member_auth(
userid varchar2(50) not null,
auth varchar2(50) not null,
constraint fk_member_auth foreign key(userid) references tbl_member(userid)
);

alter table tbl_board add constraint pk_board primary key(bno);

insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user00');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user01');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user02');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user03');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user04');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user05');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user06');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user07');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user08');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user09');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user10');

-----------------------------------------------------------------------------------------------------
>>> BoardMapper.xml (@Select 어노테이션을 써도 되지만, 쿼리문이 복잡해질 경우 xml 파일로 관리하는게 유리하다 !!!)

src/main/resources -> com 폴더 -> jslhrd 폴더 -> mapper 폴더 생성 후, 그 안에 BoardMapper.xml 파일 생성
(com.jslhrd.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.jslhrd.mapper.BoardMapper">

     <!-- 부등호 들어가면 CDATA 처리 !!! -->

     <select id="getList" resultType="com.jslhrd.domain.BoardVO">
          <![CDATA[
               select * from tbl_board where bno > 0
          ]]>
     </select>

     <insert id="insert">
          insert into tbl_board(bno,title,content,writer) values(seq_board.nextval, #{title}, #{content}, #{writer})
     </insert>

     <insert id="insertSelectKey">
          <selectKey keyProperty="bno" order="BEFORE" resultType="long">
               select seq_board.nextval from dual
          </selectKey>
          insert into tbl_board(bno,title,content,writer) values(#{bno}, #{title}, #{content}, #{writer})
     </insert>

     <select id="read" resultType="com.jslhrd.domain.BoardVO">
          select * from tbl_board where bno = #{bno}
     </select>

     <update id="update">
          update tbl_board
          set title=#{title},
          content=#{content},
          writer=#{writer},
           updateDate=sysdate
          where bno=#{bno}
     </update>

     <delete id="delete">
          delete from tbl_board where bno=#{bno}
     </delete>

</mapper>

-----------------------------------------------------------------------------------------------------
src/main/resources -> com 폴더 -> jslhrd 폴더 -> mapper 폴더 생성 후, 그 안에 TimeMapper.xml 파일 생성
(com.jslhrd.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.jslhrd.mapper.TimeMapper">
     <select id="getTime2" resultType="string">
          select sysdate from dual
     </select>
</mapper>

-------------------------------------------------------------------------------------- src/main/resources -> com 폴더 -> jslhrd 폴더 -> mapper 폴더 생성 후, 그 안에 MemberMapper.xml 파일 생성
(com.jslhrd.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.jslhrd.mapper.MemberMapper">

     <resultMap type="com.jslhrd.domain.MemberVO" id="memberMap">
          <id property="userid" column="userid" />
          <result property="userid" column="userid" />
          <result property="userpw" column="userpw" />
          <result property="userName" column="username" />
          <result property="regDate" column="regdate" />
          <result property="updateDate" column="updatedate" />
          <collection property="authList" resultMap="authMap">
          </collection>
     </resultMap> <!-- 여러개의 데이터를 처리하는 경우 1:N의 결과를 처리할 수 있는 resultMap 태그 사용 -->

     <resultMap type="com.jslhrd.domain.AuthVO" id="authMap">
          <result property="userid" column="userid" />
          <result property="auth" column="auth" />
     </resultMap>

     <select id="read" resultMap="memberMap"> <!-- mem 테이블과 auth 테이블을 쪼인하여 userid에 해당하는 항목들을 가져옴. -->
          SELECT
               mem.userid, userpw, username, enabled, regdate, updatedate, auth
          FROM
               tbl_member mem LEFT OUTER JOIN tbl_member_auth auth on mem.userid = auth.userid where mem.userid = #{userid}
     </select>

</mapper>

--------------------------------------------------------------------------------------
>>> web.xml (인코딩 & Security)

<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- The definition of the Root Spring Container shared by all Servlets and Filters --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/root-context.xml /WEB-INF/spring/security-context.xml <!-- security-context.xml을 로딩하도록 빈 설정 --> </param-value> </context-param> <!-- Creates the Spring Container shared by all Servlets and Filters --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Processes application requests --> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 한글깨짐 현상 처리 시작 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 한글깨짐 현상 처리 끝 --> <!-- Spring Security 시작 --> <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> <!-- Spring Security 끝 --> </web-app>
--------------------------------------------------------------------------------------
>>> Modal 코드

<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
     <div class="modal-dialog">
          <div class="modal-content">
               <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
                    <h4 class="modal-title" id="myModalLabel">Modal title</h4>
               </div>
               <div class="modal-body">
(modal)
               </div>
               <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                    <button type="button" class="btn btn-primary">Save changes</button>
               </div>
          </div>
          <!-- /.modal-content -->
     </div>
     <!-- /.modal-dialog -->
</div>
<!-- /.modal -->


--------------------------------------------------------------------------------------
>>> security-context.xml
(WEB-INF / spring 폴더 내에 생성)
(Namespaces 에서 security 항목 체크 !!!)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security" xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 5.0버전은 에러가 발생 버그 때문에 지우기 --> <bean id="customAccessDenied" class="com.jslhrd.security.CustomAccessDeniedHandler"></bean> <bean id="customLoginSuccess" class="com.jslhrd.security.CustomLoginSuccessHandler"></bean> <!-- <bean id="customPasswordEncoder" class="com.jslhrd.security.CustomNoOpPasswordEncoder"></bean> --> <bean id="bcryptPasswordEndcoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean> <bean id="customUserDetailsService" class="com.jslhrd.security.CustomUserDetailsService"></bean> <security:http auto-config="true" use-expressions="true"> <security:intercept-url pattern="/sample/all" access="permitAll" /> <security:intercept-url pattern="/sample/member" access="hasRole('ROLE_MEMBER')" /> <security:intercept-url pattern="/sample/admin" access="hasRole('ROLE_ADMIN')" /> <security:intercept-url pattern="/board/list" access="hasRole('ROLE_MEMBER')" /> <security:intercept-url pattern="/board/insert" access="hasRole('ROLE_MEMBER')" /> <security:intercept-url pattern="/board/update" access="hasRole('ROLE_MEMBER')" /> <!-- <security:access-denied-handler error-page="/accessError" /> error-page 나 ref 둘 중 하나만 !!! --> <security:access-denied-handler ref="customAccessDenied" /> <!-- <security:form-login /> --> <!-- 로그인창으로 강제 이동 시 해당하는 페이지 --> <security:form-login login-page="/customLogin" authentication-success-handler-ref="customLoginSuccess"/> </security:http> <security:authentication-manager> <security:authentication-provider user-service-ref="customUserDetailsService"> <!-- 최종적으로 customUserDetailsService 사용 --> <!--<security:jdbc-user-service data-source-ref="dataSource" users-by-username-query="select userid,userpw,enabled from tbl_member where userid=?" authorities-by-username-query="select userid,auth from tbl_auth where userid=?" /> change to Bcrypt <security:password-encoder ref="customPasswordEncoder" /> --> <security:password-encoder ref="bcryptPasswordEndcoder" /> </security:authentication-provider> <!-- ********************************************************************************************* <security:authentication-provider> <security:user-service> <security:user name="member" password="{noop}member" authorities="ROLE_MEMBER" /> <security:user name="admin" password="{noop}admin" authorities="ROLE_MEMBER, ROLE_ADMIN" /> </security:user-service> </security:authentication-provider> *********************************************************************************************** --> </security:authentication-manager> </beans> --------------------------------------------------------------------------------------
>>> servlet-context.xml
( Namespace의 security 추가 )
( 상단의 시큐리티 버전 5.0 숫자 지우고, global-method 태그 추가 )
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:security="http://www.springframework.org/schema/security" xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure --> <!-- Enables the Spring MVC @Controller programming model --> <annotation-driven /> <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the /resources directory --> <resources mapping="/resources/**" location="/resources/" /> <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory --> <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <beans:property name="prefix" value="/WEB-INF/views/" /> <beans:property name="suffix" value=".jsp" /> </beans:bean> <context:component-scan base-package="com.jslhrd.controller" /> <security:global-method-security pre-post-annotations="enabled" secured-annotations="enabled" /> <!-- security 어노테이션을 사용하기 위한 태그 (Namespace의 security 추가 후, 상단의 5.0버전 숫자 제거) --> </beans:beans>


>>> STS 기초 세팅
Window -> Preference -> encoding 검색 -> Workspace,CSS,HTML,JSP,XML (UTF-8 변경)
Window -> Preference -> General -> Startup&Shutdown -> Workspaces (Prompt 체크, workspaces 선택)
Window -> Web Browser -> Chrome or Default
Servers -> Spring 기본 서버 삭제 -> New -> Tomcat v9.0 추가 후 경로 설정
Tomcat -> Overview (HTTP/1.1 -> 8087변경) -> Modules (Path -> / 변경)
main/wepapp/resources -> css,fonts,images,js 폴더 관리

-----------------------------------------------------------------------------------------------------------------------------

>>> hanulso/pom.xml 기초 세팅
java-version -> 1.8
springframework-version -> 5.0.7.RELEASE (@Get/PostMapping 어노테이션 사용 가능)
log4j-version -> 1.2.17

lombok-1.18.22 추가
HikariCP-2.7.4 추가 (커넥션 풀 처리)
mybatis, spring-txt, spring-jdbc 추가 (DB연동 처리)
commons-fileupload-1.3.3, commons-io-2.6 추가 (파일 첨부 처리)
thumbnailator-0.4.8 추가 (썸네일 이미지 생성시)
spring security 추가
jackson-databind-2.9.6 추가 (JOSN 포맷 변환)
jackson-dataformat-xml-2.9.6 추가 (xml 처리)
gson-2.8.2 추가 (테스트시 java instance를 json 타입의 문자열로 변환 처리)
javax.mail-1.6.2 추가 (메일 처리)
spring-context-support 추가 (캐쉬,메일,스케줄링,UI 등 부가적 기능)

junit-version -> 4.12
maven-compiler-plugin -version -> 3.5.1 & 1.8 & 1.8


https://mvnrepository.com/ <- dependency 검색
https://start.spring.io/ <- Spring Start Page

- 세팅이 반이다 !
- Test 중요 !
- build path (mysql-connector-java-8.0.28.jar , ojdbc8.jar)
- pom.xml 계속 수정

STS 세팅

    Window -> Preference -> encoding 검색 -> Workspace,CSS,HTML,JSP,XML (UTF-8 변경)
    Window -> Preference -> General -> Startup&Shutdown -> Workspaces (Prompt 체크, workspaces 선택)
    Window -> Web Browser -> Chrome or Default
    Servers -> Spring 기본 서버 삭제 -> New -> Tomcat v9.0 추가 후 경로 설정
    Tomcat -> Overview (HTTP/1.1 -> 8087변경) -> Modules (Path -> / 변경)
    main/wepapp/resources -> css,fonts,images,js 등의 폴더 관리

MVC

   (Model View Controller)

   Presentation - Client의 요청을 받아 Business에게 처리를 전달.
   Business - 실제 요청에 대한 처리를 담당. (Service)
   Persistence - Business의 처리에 따라 데이터베이스에 접근. 저장,조회,삭제 등 수행.

Layered Architecture


   각 계층은 자신의 계층이 갖는 책임에만 충실하도록 개발해야 한다.

View

Model Model

Presentation
@Controller

Model Model

Business
@Service

DTO Model

Persistence

DTO Model

DB
(Oracle)



초기 설정/관리해야 할 .XML

p.608
    - pom.xml : 프로그램 추가(버전관리), spring5.0.7
    - web.xml : 한국어 지원, 로그인 지원
    - root-context.xml : DB 연결 지원
    - servlet-context.xml : spring security 어노테이션 설정 추가
    - security-context.xml : 로그인 관련( 인증 + 권한 )


동기 VS 비동기


    - 동기(Synchronized) : 프로그램이 작성된 순서대로 실행되는 것.
       반드시 앞의 동작이 끝나야 다음의 동작이 실행 됨.
    - 비동기(Asynchronized) : 타임라인의 분기를 나눠서 두개 이상의 함수가 동시에 동작하는 것.
    - Callback 함수 : 비동기로 함수를 실행할 경우라도 A -> B 동작 순서가 구분되어야 하는데,
       이런 경우 B를 callback함수로 A함수의 인자로 호출하면 온전하게 실행 가능.
    - promise : 무수히 중첩되는 복잡한 callback함수의 지옥을 대신하여 사용.
       비동기 작업이 종료된 후, 작업 실행의 성공,실패,결과값의 내용이 무엇인지 반환해주겠다고 약속해주는 객체.