1. 비트

사전적 의미로는

  • 조금, 약간
  • 잠깐
  • 조각

으로 적혀 있다.

 

비트는 두 가지 뜻으로 나뉘는 데 스위치로 따지면 on/off라고 할 수 있다.

  • on/off
  • yes/no
  • true/false
  • 1/0

∴ 0 또는 1 중 하나의 정보를 가지는 정보 단위.

 

2. 코드

하지만 모든 대화를 이분법적으로 해결할 수는 없다. 

그래서 자릿수를 늘려서 보기를 늘린다음 그 중 해당하는 것이 있으면 선택한다.

 

예를 들어보자.

Q. 당신은 학생입니까?

A. 1(참)

Q. 그럼 현재 몇 학년입니까?

A. (???)

Q. 1학년이면 001, 2학년이면 010, 3학년이면 011, 4학년이면 100 5학년이면 101, 6학년이면 110으로 대답해주세요.

당신은 몇 학년입니까?

A. 101

 

이렇게 약속된 0과 1로 만들어진 부호를 코드라고 부른다.

코드의 사전적 의미로는

  • 암호, 부호
  • 관례, 규칙
  • 법규, 규정

등으로 나타나며 순하게 표현하면 '약속'이라고 볼 수 있다.

 

그러므로 프로그래밍에서 코드란,

서로 간의 약속의 의미가 더해진 '약속된 부호'라고 이해하면 된다.

 

3. 바이트

비트 8개를 묶으면 바이트라는 새로운 단위가 만들어진다.

쉽게 생각해서 비트의 상위호환이라고 보면 된다.

 

4. 인코딩, 디코딩, 디코딩 오류

 

인코딩

사람의 언어를 컴퓨터 언어로 바꾸는 과정을 의미한다.

 

디코딩

반대로 컴퓨터의 언어를 인간이 알아볼 수 있는 언어로 바꾸는 과정을 의미한다.

 

디코딩 오류

간혹 웹 사이트를 사용하다 보면 사이트의 한글이 다 깨진 것을 경험하였을 것이다.

검은색 다이아에 ?가 박혀있는 글들이 페이지에 도배되어져 있으면 디코딩 오류가 난 것이다.

검은색 다이아에 ? = 위와 같은 도형

5. 아스키와 유니코드

아스키

  • 미국표준협회에서 만든 코드.
  • American Standard Code for Information Interchange의 약자
  • 영어 대/소문자, 숫자, 특수문자를 8비트 안에 약속한 코드
  • 대소문자 구분하므로 A와 a의 코드가 서로 다르다.
  • A_01000001 / a_01100001

유니코드

  • 컴퓨터의 사용이 보편화되면서 세계 여러 나라의 문자도 표기해야 하는 상황이 됨.
  • 아스키 코드보다 약속 공간을 더 늘린 코드가 바로 유니코드
  • 총 16비트 (2바이트)의 크기를 사용하며 한글도 코드화가 가능해짐.
  • 정식 명칭은 UTF이며, Unicode Transformation Format의 약자이다.

 

6. 컴파일

위에서 알게 된 비트(0과 1), 바이트(00000000~11111111)는

초기에 인간이 컴퓨터에게 명령을 내릴 때 그대로 입력하였다.

가히 미친 짓이다.

하지만 현재는 여러 '프로그래밍 언어'라는 것이 나와 

사람의 언어로 작성하면 기계어로 '번역'해서 컴퓨터에게 알려준다.

 

이 작업을 '컴파일(Compile)'이라고 한다.

사전적 의미로는 '편집하다'라는 뜻이 있으며

프로그래밍에서는 컴퓨터가 읽을 수 있는 비트 형태로 편집하는 과정을 '컴파일'이라고 하고

편집하는 도구를 '컴파일러'라고 한다.

 

7. 하이레벨 vs 로우레벨 언어

프로그래밍 언어에는 로우레벨 언어와 하이레벨 언어가 있다.

 

로우레벨은 

  • 기계 중심의 언어지만
  • 실행 속도가 빠르고
  • 기계마다 다른 코드를 가진다.

기계어와 어셈블리어가 이에 해당된다.

기계어:

컴퓨터가 직접 이해할 수 있는 언어이자 0과 1로 표현되며 전문적인 지식 없이는 작성과 이해가 어렵다.

기종마다 기계어가 달라 호환성이 없다고 보면 되고 유지보수가 어렵다.

 

어셈블리어:

기계어를 알파벳 문자로 변환하여 그나마 알아볼 수 있게 기호화한 언어이다.

어셈블(Assemle)의 사전적 의미는 '조립하다'이며, 말 그대로 0과 1의 조합으로 나올 수 있는 단어를 모아

익숙한 알파벳 기호로 1:1로 바꾼 상징적인 기호 언어이다.

 

반면에 하이레벨은

사람 중심의 언어이며 실행을 위해 번역하는 과정이 필요하다.

서로 다른 기계에서 소스 수정 없이 실행할 수 있다.

 

하이레벨의 언어로는 C, JAVA, Python 등이 있다.

 

근 한 달만에 이 카테고리에 글을 적는 듯 하다.

이번 시간엔 내장 객체의 영역, 무엇이 영역인지, 어느 정도의 영역을 가지는지 등을 알아볼 것이다.

 

[목표]

  • 내장 객체에서의 영역
  • 영역에 해당하는 개념 4가지
  • 각 영역의 특징 및 사용 예제 알아보기

1. 내장 객체의 영역이란?

한 줄로 표현하면 각 객체가 저장되는 메모리의 유효기간이라고 할 수 있다.

자바에서 지역변수 개념, for문 내 변수선언과 유사하다.

메소드 내에서 선언된 변수는 그 메소드를 벗어나면 소멸되며 for문에서 선언된 변수도 for문을 벗어나면 소멸된다.

 

하지만 JSP는 페이지 단위로 구성되며 A에서 선언한 변수를 B로 넘겨받아야 하기에 JAVA와는 다르게 접근해야 한다.

이를 위해 JSP에서는 영역을 통해 내장 객체에 저장된 값들을 공유할 수 있도록 하였다.

 

2. 영역에 해당하는 개념 4가지

(1) Page

동일한 페이지에서만 공유되며 페이지를 벗어나면 소멸된다.

 

(2) Request

하나의 요청에 의해 호출된 페이지와 전달된 페이지까지 공유됩니다.

 

(3) Session

클라이언트가 처음 접속 후 웹 브라우저를 닫을 때까지 공유됩니다.

 

(4) Application

한 번 저장되면 웹 어플리케이션이 종료될 때까지 유지됩니다.

 

(5) 범위의 크기 순서

: Application > Session > Request > page

 

(6) API 사용법

//영역이 제공하는 주요 메소드들
// 1)
void setAttribute(String name, Object value) 
// 2)
Object getAttribute(String name) 
// 3)
void removeAttribute(String name)

    1) setAttribute

  • 각 영역에 속성 저장.
  • (속성명, 저장할 값)
  • 값의 타입은 Object이므로 모든 타입의 객체를 저장할 수 있다.

    2) getAttribute

  • 영역에 저장된 값 받아옴.
  • Object로 자동 형 변환되어 저장되므로 원래 타입으로 캐스팅 후 사용해야 함. (★)

    3) removeAttribute

  • 영역에 저장된 속성 삭제
  • 삭제할 속성명이 존재하지 않아도 에러는 발생하지 않는다.

 

(7) 추가개념: 데이터 전송객체 (DTO, Data Transfer Object)

데이터 전송 객체란?

데이터를 전송하거나 저장하는 데 쓰이는 객체로 순수하게 데이터만 담고 있다.

데이터만 담고 있는 객체라 하여 VO(Value Object)라는 명칭을 갖고 있기도 하다.

 

DTO는 자바빈즈(JavaBeans)의 규약에 따라 작성한다.

 

자바빈즈란 자바로 작성한 SW Component로 다음 5가지의 규약이 있다.

  1. 자바빈즈는  default 패키지 이외의 패키지에 속해야 한다. (이를 위해 VO 패키지를 하나 만들었다)
  2. 멤버 변수의 접근 지정자는 private으로 선언한다.
  3. 기본생성자가 있어야 한다.
  4. 멤버 변수에 접근할 수 있는 getter/setter 메소드가 있어야 한다.
  5. getter/setter 메소드의 접근 지정자는 public으로 한다.

지금 보고 있는 책에서는 안 하지만 spring에 가니 lombok이란 친구가

어노테이션 하나만 붙여주면 3번부턴 알아서 다 해주더라

 


3. 각 영역의 예제 살펴보기

(1) DTO 작성

DTO는 Java 파일이므로 Java Resources 하위의 src에 생성한다. 

이 때 1번 규약을 지키기 위해 따로 패키지를 만들어 그 안에 넣도록 한다.

//규약 1번
package vo;

public class PersonVO {

	//규약 2번 private
	private String name;
	private int age;
	
	//규약 3번 default 생성자
	public PersonVO() {
	}
    
        public PersonVO(String name, int age) {
            this.name = name;
            this.age = age;
        }

	//규약 4, 5번 : getter/setter, public
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

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

vo 패키지 안에 PersonVO.java 파일 생성

 

(2) page 영역

page 영역은 클라이언트의 요청을 처리하는 데 쓰이는 JSP 페이지마다 하나씩 생성된다.

(로그인 페이지, 회원가입페이지, 약관동의페이지, 회원입력 페이지 등등)

이 때 각 page는 page 영역을 사용하기 위한 pageContext 객체를 할당 받는다.

 

pageContext 객체는 2장에서 설명하지 않은 내장 객체로, 

이 객체에 저장된 정보는 해당 페이지에서만 사용 가능하고 페이지를 벗어나면 소멸된다.

하지만 include 지시어로 포함한 파일은 하나의 페이지로 통합되므로 page 영역이 공유된다.

 

여기서 살펴볼 예제는 page에 값을 저장하고 불러오는 예이며 작성한 DTO를 사용한다.

 

총 제작된 jsp 파일 갯수: 3개

  • PageContextMain.jsp
  • PageInclude.jsp
  • PageLocation.jsp
<!-- PageContextMain.jsp -->

<%@ page import="vo.PersonVO" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
pageContext.setAttribute("pageInteger", 1000);
pageContext.setAttribute("pageString", "문자열");
pageContext.setAttribute("pagePerson", new PersonVO("이순신", 54)); 
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>내장 객체의 영역 - PAGE</title>
</head>
<body>
<h2>PAGE 속성값 읽기</h2>
<%
int pInt = (Integer) (pageContext.getAttribute("pageInteger"));
String pString = pageContext.getAttribute("pageString").toString();
PersonVO person = (PersonVO) (pageContext.getAttribute("pagePerson"));
%>
<ul>
<li>Integer객체: <%=pInt %></li>
<li>String객체: <%=pString %></li>
<li>PersonVO객체: <%=person.getName() %>, <%=person.getAge() %></li>
</ul>

<hr>

<h2>include 사용하여 page 읽어오기</h2>
<%@ include file="PageInclude.jsp" %>

<hr>

<h2>Page 이동 후 page 영역 읽어오기</h2>
<a href="PageLocation.jsp">PageLocation.jsp로 바로가기</a>
</body>
</html>

 

<!-- PageInclude.jsp -->

<%@page import="vo.PersonVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<h2>Include Page</h2>
<%
int pInt2 = (Integer) (pageContext.getAttribute("pageInteger"));
String pString2 = pageContext.getAttribute("pageString").toString();
PersonVO person2 = (PersonVO) (pageContext.getAttribute("pagePerson"));
%>
<ul>
<li>Integer객체: <%=pInt2 %></li>
<li>String객체: <%=pString2 %></li>
<li>PersonVO객체: <%=person2.getName() %>, <%=person2.getAge() %></li>
</ul>

 

<!-- PageLocation.jsp -->

<%@page import="vo.PersonVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
Object pInt = (pageContext.getAttribute("pageInteger"));
Object pString = pageContext.getAttribute("pageString");
Object person = (pageContext.getAttribute("pagePerson"));
%>
<ul>
<li>Integer객체: <%=(pInt==null) ? "값 없음": pInt%></li>
<li>String객체: <%=(pString==null) ? "값 없음": pString %></li>
<li>PersonVO객체: <%=(person==null) ? "값 없음": ((PersonVO)person).getName()  %></li>
</ul>
</body>
</html>

[결과화면]

PageContextMain.jsp(맨 위), IncludePage.jsp(중간), PageLocation.jsp(맨 아래)
PageLocation.jsp 실행 화면

 

[알게 된 사실]

page 공유에서 include는 결국 삽입되어지는 내용이기에 결과가 Main과 같이 나온다는 것을 볼 수 있으나

PageLocation처럼 이동된 후에는 값 없음으로 나오는 것을 볼 수 있다.

 

같은 페이지에 속한 것과 그렇지 않은 차이에 대해 알 수 있었다.

 


(3) request 영역

클라이언트가 요청할 때마다 새로운 request 객체가 생성되고 

같은 요청을 처리하는 데 사용하는 JSP 페이지가 공유한다.  

 

따라서 request 영역에 저장된 정보는 현재 페이지와 포워드되는 페이지까지 공유할 수 있다.

단, 위와 같이 페이지 이동 시에는 소멸되어 사용할 수 없게 된다.

 

request는 요청에 대한 응답이 완료될 때 소멸하므로 page보다 조금 더 넓다고 볼 수 있다.

 

[총 제작된 파일 갯수: 2개]

  • RequestMain.jsp
  • RequestForward.jsp
<!-- RequestMain.jsp -->

<%@page import="vo.PersonVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
request.setAttribute("requestString", "문자열");
request.setAttribute("requestPerson", new PersonVO("2000년생", 22));
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>내장 객체의 영역 - Request</title>
</head>
<body>
<h2>속성값 삭제</h2>
<%
//없는 것을 삭제하려 해도 에러는 발생하지 않음.
request.removeAttribute("requestString");
request.removeAttribute("requestInteger");
%>
<hr>
<h2>속성값 읽기</h2>
<%
PersonVO person = (PersonVO) request.getAttribute("requestPerson");
%>
<ul>
<li>String 객체: <%=request.getAttribute("requestString") %></li>
<li>Person 객체: <%=person.getName() %>, <%=person.getAge() %></li>
</ul>
<hr>
<h2>포워드된 페이지에서 request 속성값 읽기</h2>
<%
request.getRequestDispatcher("RequestForward.jsp?paramHan=한글&paramEng=English").forward(request, response);
%>
</body>
</html>

 

<!-- RequestForward.jsp -->

<%@page import="vo.PersonVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>포워드된 페이지</title>
</head>
<body>
<%
PersonVO person = (PersonVO) request.getAttribute("requestPerson");
%>
<ul>
<li>String 객체: <%=request.getAttribute("requestString") %></li>
<li>Person 객체: <%=person.getName() %>, <%=person.getAge() %></li>
</ul>
<h2>매개변수로 전달된 값 출력하기</h2>
<%
//인코딩설정, because of paramHan,, maybe
request.setCharacterEncoding("UTF-8");
out.println(request.getParameter("paramHan"));
out.println(request.getParameter("paramEng"));
%>
</body>
</html>

 

포워드 된 페이지, 하지만 주소는 RequestMain.jsp

[알게 된  사실]

1) RequestMain.jsp에서 removeAttribute를 할 때 없는 변수를 삭제하겠다고 해도 에러 발생하지 않음.

2) forward문이 작성되어져 있으면 main을 실행해도 forward 페이지가 출력되어짐.

3) 전달되는 변수에 한글이 있으면 setCharacterEncoding을 사용하여 "UTF-8"을 지정해줘야 함.

 

 


(4) session 영역

클라이언트가 웹 브라우저를 최초로 열고난 후 닫을 때까지 요청되는 모든 페이지는 session 객체를 공유할 수 있다.

세션이란 클라이언트가 서버에 접속해 있는 상태 혹은 단위를 말하며, 

로그인 상태를 유지하는 처리에 주로 사용된다.

포털 사이트에서 웹 브라우저를 닫으면 자동으로 로그아웃이 되는 이유가 바로 session의 특성 때문이다.

 

총 제작된 파일 갯수: 2개

  • SessionMain.jsp
  • SessionLocation.jsp
<!-- SessionMain.jsp -->

<%@page import="java.util.ArrayList"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
ArrayList<String> list = new ArrayList<String>();
list.add("리스트");
list.add("컬렉션");
session.setAttribute("list", list);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>내장 객체의 영역 - session</title>
</head>
<body>
<h2>페이지 이동 후 session 영역의 속성 읽기</h2>
<a href="SessionLocation.jsp">SessionLocation.jsp 바로가기</a>
</body>
</html>

 

<!-- SessionLocation.jsp -->

<%@page import="java.util.ArrayList"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>session 이동</title>
</head>
<body>
<h2>페이지 이동 후 session 속성 읽기</h2>
<%
ArrayList<String> list = (ArrayList<String>)session.getAttribute("list");
for(String str : list) 
	out.print(str + "<br/>");
%>
</body>
</html>

SessionMain.jsp to SessionLocation.jsp
SessionLocation.jsp 파일

[알게 된 사실]

1) session을 완전히 종료하고 싶으면 해당하는 탭만 닫는 것이 아니라 브라우저 전체를 닫아야 한다.

2) ArrayList<String>은 java.util 패키지의 것을 import하여 사용한다.

 


(5) Application 영역

웹 어플리케이션은 단 하나의 application 객체만 생성하고 

클라이언트가 요청하는 모든 페이지가 applicaion 객체를 공유한다.

application은 웹 서버가 시작할 때 만들어져서 웹 서버를 내릴 때 삭제된다.

그러므로 application에 한 번 저장된 정보는 페이지를 이동하거나 브라우저를 닫았다 다시 접속해도 삭제되지 않는다.

 

총 제작된 파일 갯수: 2개

  • ApplicationMain.jsp
  • ApplicationResult.jsp
<!-- ApplicationMain.jsp -->

<%@page import="vo.PersonVO"%>
<%@page import="java.util.Map"%>
<%@page import="java.util.HashMap"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>내장 객체의 영역 - Application</title>
</head>
<body>
<h2>Application 영역의 공유</h2>
<%
Map<String, PersonVO> map = new HashMap<>();
map.put("p1", new PersonVO("한여름", 34));
map.put("p2", new PersonVO("한겨울", 11));
application.setAttribute("map", map);
%>
application 영역에 속성이 저장되었습니다.
<a href="ApplicationResult.jsp">바로보기</a>
</body>
</html>

 

<!-- ApplicationResult.jsp -->

<%@page import="java.util.Set"%>
<%@page import="vo.PersonVO"%>
<%@page import="java.util.Map"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Application 영역</title>
</head>
<body>
<h2>appication 속성 읽기</h2>
<%
Map<String, PersonVO> map = (Map<String, PersonVO>)application.getAttribute("map");
Set<String> keys = map.keySet();
for (String key : keys) {
	PersonVO person = map.get(key);
	out.print(String.format("이름: %s, 나이: %d<br/>", person.getName(), person.getAge()));
}
%>
</body>
</html>

 

ApplicationMain.jsp에서 속성 저장
ApplicationResult.jsp만 열었을 때 저장되어져 있는 값들이 보임


(6) 마치며

1) page: 동일한 페이지에서만 공유 / 벗어나면 소멸

2) request: 하나의 요청에 의해 호출 및 포워드된 페이지까지 공유 / 페이지 이동하면 소멸

3) session: 클라이언트가 처음 접속한 후 웹 브라우저를 닫을 때까지 공유 / 포워드, 페이지 이동시에도 소멸 X

4) application: 한 번 저장되면 서버가 셧다운되지 않는 한 계속 공유

'ebook > jsp' 카테고리의 다른 글

[9] 내장 객체 - exception  (0) 2022.05.30
[8] 내장 객체 - application  (0) 2022.05.28
[7] 내장 객체 - out  (0) 2022.05.27
[6] 내장 객체 - response  (0) 2022.05.25
[5] 내장 객체 - request  (0) 2022.05.24

 

//spring HomeController.java 실행 시 customLogin으로 이동하도록
//com.kb.controller.HomeController.java

@Controller
public class HomeController {
	
	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
	
	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		
		return "/customLogin";
	}

 

 

//infinity 파일을 학습재료로 삼아 dashboard를 각각 게시판과 멤버관리 페이지로 이동되도록
//webapp/WEB-INF/views/includes/header.jsp

<li class="has-submenu">
  <a href="javascript:void(0)" class="submenu-toggle">
    <i class="menu-icon zmdi zmdi-view-dashboard zmdi-hc-lg"></i>
    <span class="menu-text">Smart JAVA</span>
    <i class="menu-caret zmdi zmdi-hc-sm zmdi-chevron-right"></i>
  </a>
  <ul class="submenu">
    <li><a href="/member/list"><span class="menu-text">MemberManage</span></a></li>
    <li><a href="/board/list"><span class="menu-text">Board & Gallery</span></a></li>
  </ul>
</li>

 

//로그인한 사람에 따라 보여줄 페이지 바꿔라
//com.kb.security.LoginSuccessHandler.java

package com.kb.security;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

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

import org.springframework.security.authentication.jaas.AuthorityGranter;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

public class LoginSuccessHandler implements AuthenticationSuccessHandler{

	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication auth) throws IOException, ServletException {
		
		List<String> roleNames = new ArrayList<String>();
		
		//ROLE_MEMBER, ROLE_ADMIN 배열로 받아오겠다.
		auth.getAuthorities().forEach(authority -> {
			roleNames.add(authority.getAuthority());
		});
		
		if(roleNames.contains("ROLE_ADMIN")) {
			response.sendRedirect("/member/list");
			return;
		}
		
		if(roleNames.contains("ROLE_MEMBER")) {
			response.sendRedirect("/member/list");
			return;
		}
		
		//이도 저도 아니면 Home으로 가서 시간을 보여라
		response.sendRedirect("/");
	}

	
}

 

 

//header.jsp _ logout
//javascript + jquery
<a class="text-color" onclick="logout_btn();">
    <span class="m-r-xs"><i class="fa fa-power-off"></i></span>
    <span>Logout</span>
</a>
<form action="/customLogout" method="post" id="logout">
	<input type="hidden" name="${_csrf.parameterName }" value="${_csrf.token }"/>
</form>
<script type="text/javascript">
function logout_btn() {
    $("#logout").submit();
}
</script>
                  
//jquery

 

 

//로그인한 사람의 아이디가 프로필에 등록되도록 변경

webapp/WEB-INF/views/includes/header.jsp
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec" %>

 //프로필 위치에 로그인한 사람의 아이디 집어넣기
 <h5><a href="javascript:void(0)" class="username"><sec:authentication property="principal.member.uname"/></a></h5>

 

 

절친급 에러

//상황: 
<input type="hidden" name="authority" value="ROLE_MEMBER"/>
//member/register 를 통해 등록하던 중 발생
//(1) 누군가는 405가 발생하는 반면, 다른 누군가는 500이 발생하였음.
//(2) 다 똑같은 화면을 보고 같이 따라쳤는데 에러가 다르게 나온다?

//현재 위치: com.kb.service.MemberServiceImpl.java

@Override
@Transactional
public void register(MemberVO member) {
    log.info("register");
    mapper.insert(member);
    authMapper.insert(member.getAuthList().get(0));
}

//현재 위치: com.kb.controller.MemberController.java

@RequestMapping(value = "/register", method = RequestMethod.POST)
public String register(MemberVO member, RedirectAttributes rttr) {

    List<AuthorVO> list = new ArrayList<AuthorVO>();

    AuthorVO authorvo = new AuthorVO();
    authorvo.setUid(member.getUid());
    authorvo.setAuthority("ROLE_MEMBER");
    //authorvo.setAuthority(member.getAuthList().get(0).getAuthority());

    member.setAuthList(list);
    
    list.add(authorvo);

    service.register(member);

    return "redirect:/member/list";
}

 

 

//web.xml
//세션 유지시간 60분으로 설정 
<session-config>
    <session-timeout>60</session-timeout>
</session-config>

 

아래

//멤버들에게 권한 추가 및 삭제하기

<table class="table table-hover">
    <thead>
        <tr><th>#번호</th><th>회원명</th><th>학교명</th><th>학년반</th><th>전화번호</th><th>가입일</th><th>권한관리</th></tr>
    </thead>
    <c:forEach items="${list}" var="member">
    <tr>
        <td>${member.num}</td><td>
        <a href="get?num=${member.num}">${member.uname}</a></td>
        <td>${member.schoolname}</td>
        <td>${member.gradeclass}</td>
        <td>${member.uid}</td>
        <td><fmt:formatDate pattern="yyyy-MM-dd HH:mm:ss" value="${member.joindate}"/></td>
        <td><a href="getMemberAuths?uid=${member.uid }">추가 / 삭제</a></td>
    </tr>
    </c:forEach>
</table>
//MemberController.java
@RequestMapping(value = "/getMemberAuths", method = RequestMethod.POST)
	public String readAuthsByUid(@RequestParam("uid") int uid, Model model) {
		 
		service.readAuthsByUid(uid);
		model.addAttribute("list" ,list);
		return "redirect:/member/list";
	}
    
//MemberServiceImpl.java
@Override
public void readAuthsByUid(int uid) {

    List<AuthorVO> list = authMapper.readAuthsByUid(uid);
    return list;

}

//MemberService.java
public List<AuthorVO> readAuthsByUid(int uid); //추가

//AuthorMapper.xml
<select id="readAuthsById" resultType="com.kb.domain.AuthorVO">
    SELECT * FROM tbl_author WHERE uid = #{uid}	
</select>

 

 

//리스트에서 멤버 권한 주기 
//authList.jsp

<table class="table table-hover">
    <thead>
        <tr><th>#번호</th><th>ID</th><th>권한</th><th>권한관리</th></tr>
    </thead>

    <c:forEach items="${list}" var="author" varStatus="num">
    <tr>
        <td>${num.count }</td>
        <td>${author.uid }</td>
        <td>${author.authority }</td>
        <td></td>
    </tr>
    <!-- <c:set value="${author.uid }" var="uid"></c:set> -->
    <%-- <tr>
        <td>${member.num}</td><td>
        <a href="get?num=${member.num}">${member.uname}</a></td>
        <td>${member.schoolname}</td>
        <td>${member.gradeclass}</td>
        <td>${member.uid}</td>
        <td><fmt:formatDate pattern="yyyy-MM-dd HH:mm:ss" value="${member.joindate}"/></td>
        <td><a href="getMemberAuths?uid=${member.uid }">추가 / 삭제</a></td>
    </tr> --%>
    </c:forEach>
</table>

<div class="col-xs-7 pagination">
  <form method="post">
  <input type="hidden" name="${_csrf.parameterName }" value="${_csrf.token }"/>
  <input type="hidden" name="uid" value="${uid }"/>
    <select name="type" class="form-control" style="float:left; width:50%; height:32px;">
        <option value="">Add authority</option>
        <option value="ROLE_ADMIN" >Admin</option>
        <option value="Role_MEMBER">Manager</option>
        <option value="Role_USER">User</option>
    </select>
    <button class="btn btn-default btn-sm" style="float:left;">add authority</button>
  </form>
</div>

 

//권한주기(2).java

//Controller.java
@RequestMapping(value = "/getMemberAuths", method = RequestMethod.GET)
public String readAuthsByUid(@RequestParam("uid") String uid, Model model) {

    List<AuthorVO> list = service.readAuthsByUid(uid);
    model.addAttribute("list", list);
    model.addAttribute("uid", uid);
    return "/member/authList";
}
	
@RequestMapping(value = "/getMemberAuths", method = RequestMethod.POST)
public String insertAuthByUid(AuthorVO vo) {

    service.insertAuthByUid(vo);

    return "redirect:/member/getMemberAuths?uid=" +vo.getUid();
}

//ServiceImpl.java
@Override
public void insertAuthByUid(AuthorVO vo) {
    authMapper.insert(vo);

}

//Service.java
public void insertAuthByUid(AuthorVO vo);

//Mapper.java
public List<AuthorVO> readAuthsByUid(String uid);

//Mapper.xml
<insert id="insert">
    INSERT INTO tbl_author (uid, authority)
    VALUES (#{uid}, #{authority})
</insert>

<select id="readAuthsByUid" resultType="com.kb.domain.AuthorVO">
    SELECT * FROM tbl_author WHERE uid = #{uid}	
</select>

<delete id="delete">
    DELETE FROM tbl_author WHERE bno = #{bno}
</delete>

 

 

문제 발생 원인: 아마도 _csrf
<input type="hidden" name="${_csrf.parameterName }" value="${_csrf.token }"/>

해결
[web.xml]
<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>
    <init-param>  
       <param-name>forceEncoding</param-name>  
       <param-value>true</param-value>  
    </init-param> 
</filter>

<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

GET방식은 _csrf값 넘기지 않아도 된다.
POST방식일 땐 넘겨야 한다.

+ Recent posts