전체 글 205

JSP에서 스프링 시큐리티 사용하기

JSP에서 스프링 시큐리티 사용하기 스프링 시큐리티 관련 정보를 출력하려면 시큐리티 관련 태그 라이브러리를 선언해야 한다. 태그는 과 principal이라는 이름의 속성을 사용한다. 사용 예제 admin.jsp ... principal : MemberVO : 사용자 이름 : 사용자 아이디: 사용자 권한 : .. ...결과 표현식을 이용하는 동적 화면 어떤 페이지에서, 일반 사용자로 로그인했을 때 보여지는 내용과, 관리자로 로그인 했을 때 보여지는 내용이 달라야 한다면(이를테면 관리자용 메뉴 같은 것) 표현식을 이용하여 동적으로 구성할 수 있다. 표현식 설명 hasRole([role]) hasAuthority([authority]) 해당 권한이 있으면 true hasAnyRole([role,role2]) ..

Spring legacy 2020.09.13

Spring Security - UserDetailsService

UserDetailsService JDBC를 이용한 인증방식의 단점은 사용자의 여러 정보들 중에서 제한적인 내용만을 이용한다는 점이다. 스프링 시큐리티에서는 username이라고 하는 정보만을 이용하므로 이름이나 이메일 등 자세한 정보를 이용할 경우 충분하지 못하다. UserDetailsService이스를 구현하는 방식으로 이러한 문제를 해결할 수 있다. UserDetailsService는 loadUserByUserName이라는 하나의 메서드만 가지고 있다. loadUserByUserName()는 UserDetails를 반환하는데, UserDetails는 사용자의 정보와 권한 정보를 담는 인터페이스다. UserDetails는 getAuthorities(), getPassword(), getUserName..

Spring legacy 2020.09.13

Spring Security - 기존 테이블을 이용하는 인증방법

기존의 테이블을 이용한 시큐리티 인증 방법 1. 테이블 설계 회원 테이블과 권한 테이블 -- 회원 테이블 create table tbl_member( userid varchar(50) not null primary key, userpw varchar(100) not null, username varchar(100) not null, regdate timestamp default now(), moddate timestamp default now(), enabled char(1) default '1' ); -- 권한 테이블 create table tbl_member_auth( userid varchar(50) not null, auth varchar(50) not null, constraint fk_memb..

Spring legacy 2020.09.13

[MySQL]Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column. To disable safe mode, toggle the option in Preferences -> SQL Editor and reconnect.

Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column. To disable safe mode, toggle the option in Preferences -> SQL Editor and reconnect. "안전 업데이트 모드를 사용 중이며 KEY 열을 사용하는 WHERE없이 테이블을 업데이트하려고했습니다. 안전 모드를 비활성화하려면 기본 설정-> SQL 편집기에서 옵션을 토글하고 다시 연결합니다." MySQL에서 update하던 중 에러가 발생했다. 게시글 목록을 담아두는 테이블 tbl_board에 각 게시글에 달린 댓글 수를 조회할 수 있도록..

ERROR!!!!!!! 2020.09.13

자바스크립트를 이용한 페이징 삽질 - 일반 함수의 this와 화살표 함수의 this는 다르다

JS 삽질기 js에 미숙하다 보니까 별것 아닌데 몇 시간을 삽질했다. 나는 여기서 a태그의 href속성을 받아오려고 했다. 모던 자바스크립트를 써보겠다고 화살표 함수를 고집했다. 자꾸 this값이 오지 않았다. 화살표 함수 때문일 것이라고는 1도 생각 못하고 계속 딴짓만 했다. 원하는 결과는 페이지 넘버 3페이지면 3. 5페이지면 5였는데, 자꾸 이런 결과만 나왔다. 속성을 뒤져봐도 내가 원하는 값을 가진 프로퍼티는 없었다. 도대체 뭘까? 별 걸 다 해봤는데. 그러니까 $(document).ready(() => {....})로 선언했던 것을 $(document).ready(function() {....})로 다시 바꿔도 보고. 그러면서도 화살표 함수를 바꿀 생각을 왜 하지 못했는지 모르겠다. 난 표현식만..

ERROR!!!!!!! 2020.09.13

👿[Spring Error] java.lang.IllegalStateException: No primary or default constructor found for class || @Builder && @NoArgsConstructor

java.lang.AssertionError: Request processing failed; nested exception is java.lang.IllegalStateException: No primary or default constructor found for class com.coco.domain.BoardVO at org.junit.Assert.fail(Assert.java:89) at com.coco.controller.BoardControllerTest.registerTest(BoardControllerTest.java:78) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAc..

ERROR!!!!!!! 2020.09.13

👿[Spring Error] java.lang.NoClassDefFoundError: javax/servlet/SessionCookieConfig

MockMvc로 컨트롤러 테스트 중 에러 @Test public void getAllPostTest() { ModelMap result; try { result = mockMvc.perform(MockMvcRequestBuilders.get("/board/list")) .andReturn() .getModelAndView() .getModelMap(); assertNotNull(result); log.info(result); } catch (Exception e) { fail(e.getMessage()); } } java.lang.NoClassDefFoundError: javax/servlet/SessionCookieConfig at org.springframework.test.context.web.Ab..

ERROR!!!!!!! 2020.09.13

👿 [Spring Error]java.lang.NoClassDefFoundError: org/springframework/jdbc/datasource/TransactionAwareDataSourceProxy

MyBatis - Spring 연결 테스트 중에 이런 에러가 발생했다. INFO : org.springframework.test.context.support.DefaultTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.con..

ERROR!!!!!!! 2020.09.13

👿[Git Error] Lf will be replaced by CRLF in README.md.

가끔 git add하다 보면 이런 에러가 발생한다. warning: Lf will be replaced by CRLF in README.md. The file will have its original line endings in your working directroyWindow는 Line Ending으로 CR(Carriage-Return, \r)과 LF(Line Feed, \n)를 사용한다. 반면 유닉스나 맥은 LF만 쓴다. 윈도에서는 CRLF 를 사용하므로 저장소에서 가져올 때 LF 를 CRLF 로 변경하고 저장소로 보낼 때는 CRLF 를 LF 로 변경하도록 true 로 설정한다. Windows git config --global core.autocrlf true

ERROR!!!!!!! 2020.09.13

Servlet/JSP에서 Ajax 사용

Ajax(Asynchronous Javascript XML) 비동기 통신. 클라이언트 - 서버 간에 XML 또는 JSON 데이터를 주고 받는 기술이다. 페이지 이동 없이 데이터 처리가 가능하다. 새로 고침 없이 화면이 변한다! 제이쿼리 - Ajax 사용법 $.ajax({ type:'post or get', async:'true or false', url:'요청할 url', data:{서버로 전송할 데이터}, dataType: '서버에서 전송받을 데이터 형식', success: { //정상 요청, 응답 시 처리 작업 }, error : function(xhr,status,error) { //오류 발생 시 처리 }, complete:function(data,textStatus) { //작업 완료 후 처리 }..

UriComponentBuilder

UriComponentBuilder 게시물을 POST방식으로 처리하고 나서도 페이지나 검색 조건을 유지하기 위해서는 페이지 정보와 검색 조건, 검색 키워드 정보를 RedirectAttribute객체로 직접 지정해야 했다. @PostMapping("/modify") public String modify(BoardVO boardVO, PageInfo pageInfo,RedirectAttributes redirect) { log.info("/board/modify"); log.info("BoardVO : " + boardVO); int result = boardService.modify(boardVO); log.info("MODIFY RESULT : " + result); redirect.addAttribut..

Spring legacy 2020.09.12

Spring 게시판 구현 - Presentation Layer II

Presentation Layer II 화면 CRUD 레이아웃은 BootStrap4의 Sb Admin을 이용했다. 링크 폴더 구조는 이렇다. /board/list /board/write /board/post post페이지에서 수정 따로 수정 페이지를 만들지 않고 자바스크립트를 이용하여 조회 페이지에서 바로 수정할 수 있도록 했다. /board/remove 모달 창을 쓸까, 말까 고민했지만 쓰지 않기로 했다. 네이버나, 페이스북 같은 웹에서 게시물을 삭제했을 때, 따로 삭제했다는 메세지 같은 것을 받은 기억이 없다. 따라서 굳이 필요한가... 있어도 되고 없어도 되는 기능이고, 없다고 사용자 입장에서 불편한 기능이 아니라고 판단해서 사용하지 않았다. 코드가 궁금하다면 참고 페이징 게시글을 조회했다가, 다시..

Spring legacy 2020.09.12

Spring 게시판 구현 - Presentation Layer

Presentation Layer 컨트롤러와 화면처리를 담당할 jsp가 프레젠테이션 계층이다. 컨트롤러를 완성하고 화면처리를 할 것이다. URL분기는 참고 달라진 점은 수정 페이지를 따로 만들지 않고 자바스크립트를 이용해서 처리할 것이므로 따로 분기하지 않았다. 컨트롤러 @Controller @RequiredArgsConstructor @RequestMapping("/board") @Log4j public class BoardController { private final BoardService boardService; @GetMapping("/list") public void getAllPost(Model model) { log.info("/board/list"); model.addAttribute("..

Spring legacy 2020.09.12

Spring 게시판 구현 - Business Layer

Business Layer 비지니스 계층은 'Service'라는 이름을 주로 사용한다. BoardService라는 인터페이스를 만들고 BoardServiceImpl클래스가 구현하는 형태로 만들 것이다. 굳이 인터페이스를 중간에 두는 이유는 다음에 구현할 프레젠테이션 계층과 강결합을 피하기 위해서다. service패키지 생성 public interface BoardService { Long register(BoardVO boardVO); List getAllPost(); BoardVO getPost(Long bno); int modify(BoardVO boardVO); int remove(Long bno); } @Service @RequiredArgsConstructor @Log4j publ..

Spring legacy 2020.09.12

Spring게시판 구현 - Data/Persistence Layer

영속 계층 구현 순서 VO 생성 @Data @Builder public class BoardVO { private Long bno; private String title; private String content; private String writer; private Date regdate; private Date moddate; } MyBatis Mapper인터페이스 & Mapper.xml public interface BoardMapper { int insert(BoardVO boardVO); List getAllPost(); BoardVO getPost(Long bno); int update(BoardVO boardVO); int delete(Long bno); Long lastInsertId()..

Spring legacy 2020.09.12

Spring 게시판 구현 준비

요구사항 사용자는 게시물을 등록할 수 있다. 사용자는 게시물을 조회할 수 있다. 사용자는 게시물을 수정할 수 있다. 사용자는 게시물을 삭제할 수 있다. 레이아웃 무료로 제공하는 부트스트랩을 이용할 것이다. 링크 URL 설계 URL 전송 방식 비고 /board/list GET 전체 게시물 목록 /board/write GET 게시물 등록 양식 /board/write POST 게시물 등록 처리 /board/post GET 게시물 조회 /board/modify GET 게시물 수정 양식 /board/modify POST 게시물 수정 처리 /board/remove POST 게시물 삭제 데이터베이스(MySQL) CREATE TABLE `tbl_board` ( `bno` int NOT NULL AUTO_INCREMEN..

Spring legacy 2020.09.12

Model, RedirectAttribute

Model Servlet은 request.setAttribute()로 데이터를 전달한다면, 스프링은 Model객체로 데이터를 전달한다. Controller @GetMapping("/testModel") public void model(SampleDTO sampleDTO,Model model) { SampleDTO dto = new SampleDTO(); dto.setName("cocokim"); dto.setAge(123); //dto객체를 Model객체에 바인딩 model.addAttribute("dto", dto); } view Model Test Model로 전달 받은 데이터 : ${dto } name : ${dto.name } age : ${dto.age } @ModelAttribute @Mode..

Spring legacy 2020.09.12

Spring MVC

스프링 MVC 이미지 출처 스프링의 목적은 웹이 아니다. 위에 보이는 것처럼 스프링 웹은 스프링의 기능 중 하나일 뿐이다. 스프링 MVC 프로젝트를 생성하면, 자바 영역(POJO)과 웹 영역을 연동해서 프로젝트를 구동하게 된다. 웹 영역이 MVC설정을 포함하고 있다. 스프링 MVC의 사상 스프링 MVC 이전까지는 Servlet/JSP API를 이용했다. HttpServletRequest/Response 같은 클래스를 이용해서 브라우저와 서버 간 데이터를 주고 받았다. 이런 부분을 내부적으로 처리하고, 개발자는 자바 코드로 개발에만 몰두할 수 있도록 하자는 생각에서 탄생한 것이 스프링 MVC다. 스프링 MVC 구조 이미지 출처 모든 요청은 DispatcherServlet(web.xml)으로 들어온다. Ha..

Spring legacy 2020.09.12

파라미터 수집Binding

자동 수집 DTO @Data public class SampleDTO { private String name; private int age; } 컨트롤러 @GetMapping("/autoCollect") public void parameterAutoCollect(SampleDTO dto) { SampleDTO parameters = dto; log.info(parameters); log.info(parameters.getAge() == 1); } 이렇게만 해두고 브라우저에 http://localhost:8080/sample/autoCollect?name=cocolee&age=20를 요청한다. INFO : com.coco.controller.SampleController - SampleDTO(name=co..

Spring legacy 2020.09.12

콘솔에서 쿼리 확인하는 log4jdbc-log4j2 라이브러리

log4jdbc-log4j2 해당 라이브러리를 이용하면 콘솔에서 SQL문과 결과를 가지런하게 확인할 수 있다. 우선 메이븐 설정을 추가한다. 링크 org.bgee.log4jdbc-log4j2 log4jdbc-log4j2-jdbc4.1 1.16 RootConfig.java @Bean public DataSource dataSource() { HikariConfig config = new HikariConfig(); // config.setDriverClassName("com.mysql.cj.jdbc.Driver"); // config.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/springex?serverTimezone=Asia/Seoul"); config.setDriverCla..

Spring legacy 2020.09.12

MyBatis

💣 마이바티스는 무엇인가? 마이바티스는 개발자가 지정한 SQL, 저장프로시저 그리고 몇가지 고급 매핑을 지원하는 퍼시스턴스 프레임워크이다. 마이바티스는 JDBC로 처리하는 상당부분의 코드와 파라미터 설정및 결과 매핑을 대신해준다. 마이바티스는 데이터베이스 레코드에 원시타입과 Map 인터페이스 그리고 자바 POJO 를 설정해서 매핑하기 위해 XML과 애노테이션을 사용할 수 있다 출처 퍼시스턴트? 객체가 생성되면 메모리에 올라간다. 객체를 이용해서 다루는 데이터들은 객체가 사라지면 함께 사라진다. 이렇게 일회용으로 버려지는 데이터들을 유지하려면, 객체가 사라지기 전에 어딘가에 저장해두어야 한다. 그러면 나중에 객체가 다시 생성되었을 때 이전에 사용했던 데이터를 재사용할 수 있다. 다시 말해, 객체가 사라지기..

Spring legacy 2020.09.12

의존성 주입(DI)

의존성 주입의 세 가지 방식 스프링 DI에는 세 가지 방식이 있다. set메서드 주입 필드 주입 생성자 주입 이 중에서 필드 주입이 사용하기 가장 간단하지만, 생성자 주입을 사용하라고 권장되고 있다. 참고 세 가지 모두 테스트 해 볼 것이다. 흐름 Market이라는 클래스를 만들고, 마켓에서 판매할 상품인 고기와 야채, 스낵 클래스를 주입하는 테스트를 해볼 것이다. Lombok과 spring-test 라이브러리를 이용할 것이다. 📖스프링 설정 참고 상품 마켓에서 판매할 고기와 야채를 클래스로 정의한다. @Component @ToString public class Vegetable { } @Component @ToString public class Snack { } @Component @ToString p..

Spring legacy 2020.09.12

Spring 5.0 Setting & Lombok

스프링 5.0 pom.xml 설정 🚥 XML설정 && 자바 설정 둘 중 하나를 골라서 설정해야 한다. 나는 java 클래스를 이용해 설정했다. 선택한 두 개의 root-context.xml과 web.xml을 삭제한다. 추가 해당 경로의 servlet.xml까지 삭제한다. 그 다음 삭제한 xml들을 대체할 자바 클래스를 생성한다 RootConfig.java package com.coco.config; @Configuration //참조할 패키지 @ComponentScan(basePackages = {"com.coco.sample"}) public class RootConfig { } ServletConfig.java @EnableWebMvc @ComponentScan(basePackages = {"com...

Spring legacy 2020.09.12

스프링이란?

스프링이라는 프레임 워크 image 🌍Wikipedia 프레임워크의 사전적 의미는 뼈대, 근간이다. 이까짓 뼈대가 왜 필요하나? a,b,c, ...z가 함께 일하는데 모두가 다른 방식으로 일한다면 어떨까? 뭐 그럭저럭 흘러는 가겠지만... 지금은 상상할 수 없는 어떤 무시무시한 일들이 벌어질지도 모르겠다. a와 w가 밤새 개발한 다음, 이제 우리 코드를 합쳐 보자! 했을 때, a의 방식과 w의 방식이 전혀 달라서 대략난감한 경우 말이다. 흠. 이렇게 하자고 했잖아! 난 이게 더 좋단 말이야! 이런이런. 프레임워크는 독재차처럼 흐름을 제어한다. 개발자는 프레임워크가 제어하는 흐름을 따라 개발할 수밖에 없다. 위에서 예로든 a부터 z로 이루어진 알파벳 팀 모두가 Spring을 쓴다고 해보자. 그럼 a와 w는..

Spring legacy 2020.09.12

Servlet/JSP 답변형 게시판 만들기 - 페이징

페이징 구성 화면으로부터 페이지 번호와 몇 개의 게시물을 볼 것인지(기본1, 10) 데이터를 받는다. 컨트롤러는 페이징 하는 서비스 메서드를 호출한다. 화면에서 받은 페이지 데이터를 인자로 입력한다. 요청 받은 페이지의 게시물을 DB에 조회한다. 게시물 개수가 100개가 넘고, 현재 조회하고 있는 페이지에서 '이전 페이지'버튼이 활성화 되어야 하는지 '다음 페이지'버튼이 활성화되어 있어야 하는지 연산해서 화면으로 데이터를 보낸다. 화면은 전달 받은 데이터를 띄우고, next, prev 버튼 사용 여부를 결정한다. SQL 우선 limit을 이용해 페이징 쿼리를 만든다. limit 0, 10은 1페이지 limit 10, 10은 2페이지 limit 20, 10은 3페이지 limit..

게시글 삭제할 때 고민했던 점

❓ 🤯 게시글 삭제할 때 고민했던 점 삭제 했을 때 원글만 지운다. 원글은 '삭제된 글입니다.'라고 띄우고 답글은 살려두는 형태 답글까지 지운다. 원글을 지우면 답글까지 지워지는 경우. 페이스북의 경우는 답글까지 지우는 형태다. 반면 네이버는 답글은 두고 원글만 지운다. 뭐가 더 좋은 방법일까? 상황에 따라 다를 것이다. 나는 1번 원글만 지우는 방식을 선택했다. 댓글의 권한은 댓글을 쓴 사람에게 있다고 보기 때문이다. 어떻게 ? 처음 생각한 방식은 쿼리를 두 번 날리는 것이다. 1. 카운트 쿼리를 날린다. 2. 이 결과가 0보다 크다면, 답글이 존재하는 것이므로, delete가 아닌, 기존의 데이터를 없애고 '삭제된 게시물입니다.' 라는 문구로 update 한다. 3. 결과..

Servlet/JSP 답변형 게시판 만들기 - 게시글 삭제

com.test.dao.BoardDAOTest @Test public void deleteTest() throws ClassNotFoundException { Class.forName(DRIVER); String sql = "DELETE FROM t_board WHERE bno = ?"; log.info(sql); try( Connection conn = DriverManager.getConnection(URL,USER,PW); PreparedStatement pstmt = conn.prepareStatement(sql); ) { assertNotNull(conn); pstmt.setInt(1, 44); assertTrue(pstmt.executeUpdate()==1); } catch(Exception ..

Servlet/JSP 답변형 게시판 만들기 - 수정

com.test.dao.BoardDAOTest 테스트 코드 @Test public void updateTest() throws ClassNotFoundException { Class.forName(DRIVER); String sql = "UPDATE t_board " + " set title = ?, content= ?" + " where bno = ?"; log.info(sql); try( Connection conn = DriverManager.getConnection(URL,USER,PW); PreparedStatement pstmt = conn.prepareStatement(sql); ) { pstmt.setString(1, "update"); pstmt.setString(2, "con...ten..

Servlet/JSP 답변형 게시판 만들기 - 조회

com.test.BoardDAO @Test public void getPostTest() throws ClassNotFoundException { Class.forName(DRIVER); String sql = "SELECT * FROM t_board" +" WHERE bno > 0 AND bno = ?"; log.info(sql); try( Connection conn = DriverManager.getConnection(URL,USER,PW); PreparedStatement pstmt = conn.prepareStatement(sql); ) { pstmt.setInt(1, 7); ResultSet rs = pstmt.executeQuery(); assertNotNull(rs); rs.next(); ..