반응형
SMALL

클래스

1. 객체란?

객체 : 쉽게 말해 덩어리. 속성과 동작으로 구성. 사람이 객체라고 치면, 사람은 이름이라는 속성이 있고, 걷다 등의 동작이 가능하다. 있다.

이러한 속성과 동작을 각각 필드(field)와 메소드(method)라고 부른다.

 

이러한 객체로 소프트웨어를 설계하면 객체지향 프로그래밍이 된다.

특징은 캡슐화, 상속, 다형성이 있음.

 

- 캡슐화 : 객체의 필드(=데이터)와 메소드(=동작)를 하나로 묶어서 내부를 감추면 외부의 객체는 알 수 없고 객체가 노출하는 필드와 메소드만 사용 가능하다. 이러면 외부에서 잘못사용해도 객체가 망가질 일이 없음. 

- 상속 : 부모와 자식으로 역할을 부여해서 자식은 부모의 것을 사용가능하다. 단, 부모는 자식꺼를 사용할 수 없음. 코드를 재사용할 수 있기 때문에 효율적임. 그리고 부모를 수정하면 그 아래 자식들이 자동으로 수정된 걸 쓰기 때문에 편함.

- 다형성 :  사용방법은 동일하지만 실행결과가 다양하게 나온다는 뜻. 객체를 바꾸면 프로그램의 실행 결과가 다르게 나올 수 있다.

 

 

2. 인스턴스

 클래스로부터 생성된 객체를 해당 클래스의 인스턴스(instance)라고 부른다. 클래스로부터 객체를 만드는 과정을 인스턴스화라고 함. 동일한 클래스로부터 여러 개의 인스턴스를 만들 수 있는데, 동일한 설계도로 여러대의 자동차를 만드는 것과 같다.

 

클래스 선언은 객체 생성을 위한 설계도를 작성하는 것과 같다.

 

 이 설계도(클래스) 접근 권한을 어떻게 할 것인지는 클래스 앞에 접근권한자를 붙여서 판단한다.

 

[클래스의 접근제한자]

public - 전부 공개(같은 패키지, 다른 패키지 전부 가능)

(default) - 같은 패키지 ㅇㅋ, 다른패키지는 안됨.

 

3. new 클래스()

객체 생성 연산자이다. 객체를 만드는데, 걔 이름이 이거라고 변수에 담아준다.

Student s1 = new Student();
//앞에 있는 Student와 뒤에 있는 Student는 같다.

Student라는 class가 있는데 그걸 new로 객체화해준다. 단, s1이라는 이름에 담아서.

이렇게 되면 인스턴스화 되어서 인스턴스가 생성되었으므로 Student 라는 클래스 안에 있는 애들을 s1 이름으로 불러다 쓸 수 있다.

 

1번 Student 클래스

//Student.java
public class Student{

}

2번 StudentExample 클래스

//StudentExample.java

public class StudentExample {

	public static void main(String[] args) {
		
		Student s1 = new Student();
		System.out.println("s1 변수가 Student 객체를 참조합니다." + s1);
		
		Student s2 = new Student();
		System.out.println("s2 변수가 또다른 Student 객체를 참조합니다.");
	}
}

총 2가지의 클래스가 있는데 클래스는 Student 처럼 실행은 못하지만 다른 클래스가 사용할 수 있도록 라이브러리 역할을 하는 클래스가 있고, StudentExample  처럼 main()메소드를 가지고 있어 실행 가능한 클래스가 있다.

 

4. 클래스 구성 멤버(필드, 생성자, 메소드)

public class 요소 {
	//--------- 필드 선언 ------------
	String company = "현대자동차";
	String 문자1;
	String 문자2;
	Boolean 불린;
	int 숫자;
	//--------- 아이템 생성 끝 ------------
	
	//-------- 여러개의 생성자 선언 ------------
	/*왜? 생성자가 있어야 쓸 수 있는데(조합 어떻게 갖다씀?)
	순서에 따라서 뭘 갖다쓸지 모르니까.*/

	//첫번 째 생성자
	public 요소(){}
	
	//두번 째 생성자
	요소(String company, int 숫자){
		this.company = company;
		this.숫자 = 숫자; //야 숫자 좀 받아줘
	}
	
	//3번 째 생성자
	요소(String company, String 문자2, Boolean 불린){
		this.company = company;
		this.문자2 = 문자2;
		this.불린 = 불린;
	}
}

main()이 없는 라이브러리형 클래스의 경우, main()이 선언된 실행 클래스에서 가져가기 위해 작업이 필요하다.

 

1) 필드는 변수 선언과 비슷하다. 쉽게 말해서 값 담는 그릇임.

java는 javascript와 다르게 변수 타입(형)이 굉장히 중요하기 때문에 필드에 알맞는 형(그릇의 재질처럼)을 부여해준다.

 

이 필드가 외부에서 마음대로 값을 읽고 변경하면 무결성이 깨지므로, getter/setter를 사용해서 들어갔다가 나오는 통로를 만들어준다.

 

2) 생성자는 쉽게 말해 그릇의 묶음이다.

필드가 값을 담는 그릇이라 다양한 재질(String, Boolean 등)이 선언되어 있는데 main()이 있는 실행클래스에서 뭘 갖다쓸지 모른다. 이 때 생성자를 호출하면 비어있는 껍데기를 템플릿처럼 가져와서 초기화할 수 있음.

 

위에서는 main()을 가진 실행 클래스가 company와 숫자 묶음을 호출하면 두번째 생성자를 호출할 것이고, company와 문자, 불린 묶음을 호출하면 세번째 생성자를 호출할 것이다. (첫번째꺼는 기본 생성자로 값이 들어있는 company만 가능)

 

나는 라이브러리형 클래스를 s1으로도 가져오고, 또 s2로도 가져오고 해서 템플릿을 다양하게 가져와서 복사해서 쓸꺼다. 그러면 한개 이상의 생성자를 쓴다면 해당 묶음의 재질(형)에 따라서 다양하게 활용 가능하다. 물론 캡슐화도 가능!

 

=> 이렇게 매개변수를 달리하는 생성자를 여러개 선언하는 것을 생성자 오버로딩이라고 한다.

 

중복된 생성자의 경우, this로 묶어서 사용 가능.

	//다른거 불러와
	Car(String model){
    	this(model, "은색", 250);
	}
	
	//불러와지는 생성자
	Car(String model, String color, int maxSpeed){
		this.model = model;
		this.color= color;
		this.maxSpeed = maxSpeed;
	}
}

 

 

3) 메소드는 객체의 동작이다.

public class Calculator {

	void powerOn() {
		System.out.println("전원을 켭니다");
	};
	
	void powerOff() {
		System.out.println("전원을 끕니다");
	}

	int plus(int x, int y) {
		int result = x + y;
		return result;
	}
    
    double plus(double x, double y) {
        double result = x + y;
        return result;
	}
}
public class CalculatorExample {
	
	public static void main(String[] args) {
		Calculator myCalc = new Calculator();
		
		myCalc.powerOn(); //실행됨
		
		int result = myCalc.plus(3,5); 
		System.out.println(result); //실행하고 찍음
	}
}

 

라이브러리 클래스인 Calculator에는 powerOn, powerOff, plus 와 같은 메소드가 있다. 

return 해서 결과값을 전달하거나, 아니면 리턴값이 없는 경우 void를 선언해서 동작만 한다.

뱉는거 아니면 움직이기만 하는거임.

 

라이브러리 클래스에서 powerOn() 이라는 클래스를 void로 선언했다면 그 동작을 main()이 선언된 실행 클래스에서 가져다 썼을 때 리턴값은 없지만 powerOn 안에 선언된 행동은 한다.(sysout을 뱉는다.)

 

return 하면 종료의 의미이다. 뒤에 리턴값이 있다면 멈추고 값을 뱉어내는 것.

 

만약 plus를 부를 때 값을 double 값을 넣고 호출하면 double plus 에 있는 값이 호출된다.

=> 매소드 이름은 같은데 매개변수를 달리하는 메소드를 여러개 선언하는 것을 메소드 오버로딩이라고 한다.

 

4.) 정적 멤버(static)

필드(그릇)과 메소드(동작)은 기본적으로 객체를 생성해야만 사용할 수 있지만, 그냥 객체 없이도 고정적으로 사용할 수 있는 정적 멤버를 만들 수 있다.

 

즉, new 하지 않아도 갖다쓸 수 있음. 정적 필드와 정적 메소드가 생길 수 있다.

 

public class Calculator {

	static double PI = 3.141592; //파이는 변경될일 없는 값이라 정적으로 선언
    
    static plus(int x, int y){
    	~~~
    }
}

 

이렇게 정적인거 갖다쓰는 경우엔 아래와 같다.

double result = 10 * 10 * Calculator.PI;
int result2 = Calculator.plus(10,5);

 

 

다만 이건 다른게, 객체생성을 하는 new()로 만든 인스턴스 필드와 인스턴스 메소드를 사용할 수 없다. 즉, static 한 애에게 다른 멤버도 추가해주거나 변경해주고 싶은 경우 new()로 인스턴스로 복사해서 그걸 써야하는 것.

 

참고로 main()함수도 static이 붙은 정적 메소드이므로, 객체 생성 없이 인스턴스 필드와 인스턴스 메소드 사용이 불가하므로 객체 생성 후에 갖다써야 한다.

 

5) 값 변경 불가할 땐 final 필드와 상수

final이 붙으면 값 변경 못한다고 보면 된다. static 붙으면 불변의 다 갖다쓸 수 있는 값, 즉, 상수가 되는거임.

 

 

6) 필드, 생성자, 메소드의 접근제한자

[클래스의 접근제한자]

public - 전부 공개(같은 패키지, 다른 패키지 전부 가능)

(default) - 같은 패키지 ㅇㅋ, 다른패키지는 안됨.

 

클래스는 이 두개만 되지만 그 내부의 필드, 생성자, 메소드는 몇개 더 사용 가능하다.

 


[필드, 생성자, 메소드의 접근제한자]

public - 전부 공개(같은 패키지, 다른 패키지 전부 가능)

protected - 같은 패키지이거나, 자식 객체만 사용 가능

(default) - 같은 패키지 ㅇㅋ, 다른패키지는 안됨.

private - 현재 클래스 내부에서만 사용 가능.

 

 

7) 싱글톤 패턴

애플리케이션 전체에서 단 한개의 객체만을 생성해서 사용하는 것. (=private로 생성자 접근제한해서 외부에서 new 못하게 막음) 객체 얻는 것은 getInstance() 메소드 호출로만 가능하다.

 


상속

프로그램에서는 상속은 자식이 부모를 선택한다.

public class 자식클래스 extends 부모클래스 {

}

 

부모클래스는 여러개일 수 없다. 단, 각 자식클래스는 동일한 부모클래스를 상속할 수 있다.

 

자식클래스 변수 = new 자식클래스();

부모 없는 자식 없듯이 이렇게 자식 객체를 생성하면 부모가 자동으로 생성된다. 즉, extends 를 해놓은 부모클래스는 객체 생성 시 함께 생성되는 거다.(물론 눈에 보이지는 않지만)

 

만약 plus를 부를 때 값을 double 값을 넣고 호출하면 double plus 에 있는 값이 호출된다.
=> 매소드 이름은 같은데 매개변수를 달리하는 메소드를 여러개 선언하는 것을 메소드 오버로딩이라고 한다.

 

위에서 설명한 이 메소드 오버로딩을 자식이 부모한테 쓸 수 있다.

즉, 부모한테 상속받아 가져온 것을 자기가 재정의해서 입맛대로 사용하는 것.

단, Override 라는 어노테이션을 붙여준다.

 

public class Calculator {

	public double areaCircle(double r){
    	Sysyem.out.println("Calculator 객체 안의 areaCircle 입니다");
        return 3.14159 * r * r;
}
public class Computer extends Calculator {

	@Override
	public double areaCircle(double r){
    	Sysyem.out.println("Calculator 객체 안의 areaCircle메소드를 오버라이딩");
        return Math.PI * r * r;
}
public class ComputerExample {
	public static void main(String[] args) {
    
    	int r = 10; //원의 반지름
        
      //그냥 기본적인 부모 메소드의 값
      Calculator calculator = new Calculator();
      System.out.println(calculator.areaCircle(r)); //314.159
      
      //자식이 갖다가 오버라이딩 해서 쓴 메소드 값
      Computer computer = new Computer();
      System.out.println(computer.areaCircle(r)); //314.15926535...  
	}
}

 

이렇게 나온다는 것!

 

 

final

동일하게 값을 변경 못하므로 클래스에 붙으면 상속이 불가하고, 메소드에 붙으면 오버라이딩을 못한다.

 

타입 변환

자식은 부모의 특징과 기능을 상속받았기 때문에 부모와 동일한 취급을 받을 수 있다. 즉, 자동으로 타입이 변환된다.

물론 부모걸로 자동 타입이 변환되면 부모클래스의 필드와 메소드만 접근 가능하다.

 

하지만 반대로 부모는 자식 타입으로 자동변환 되지 않는다. 이 경우 casting 연산자로 강제 타입 변환을 한다.

 

Parent parent = new Child(); //자동 타입 변환
Child child = (Child) parent; //강제 타입 변환

 

추상클래스(abstract)

새, 곤충, 물고기 클래스가 각각 있는데 공통되는 부분이 있어서 그걸 따로 묶고싶다. 그러면 이걸 추상클래스로 만들어서 상속시킨다.

public absract class Phone {
	void trunOn(){ //핸드폰들은 공통적으로 켜는 기능을 가짐
    	...
    }	
}

 

 

봉인된(Sealed) 클래스

Java15 부터 무분별한 자식 클래스 생성을 방지하기 위해서 봉인된(Sealed) 클래스가 도입되었다.

 

 

반응형
LIST
반응형
SMALL

뭔 요상한 에러가 발생하는데 뭔가 싶었다.

이게 뭐여...

구글링 해보니 대부분의 경우 character set 관련 문제라고 함...

 

[오류] Error in executeUpdate, Incorrect string value: '\xAC\xED\x00\x05sr...' for column '컬럼명' at row 1

 - 오류내용 : insert나 update 할때 발생함.    Error in executeUpdate, Incorrect st...

blog.naver.com

확실히 문제가 된다는 PRODUCT 컬럼에 문자열이 좀 이상하게 들어가 있었음.

근데 아무리 해도 인코딩은 아닌 것 같아서 꼼꼼히 다시 살펴봤는데...

 

 

그게 아니고 form에 같은 key 값이 두개가 같이 있어서 그런거임....

중복된 값이 있으니까 쿼리에 둘 다 값을 보내고 그래서 오류가 발생했던 것.

네이밍 바꾸는 것은 다른 영향도가 무서워서 어렵고, product와 custCompName 과 같은 애들 id값과 name값을 빼줬다.

어차피 클래스로 해서 데이터 넣기 때문에 노상관.

싱글페이지이기 때문에 팝업이 나와도 id값 겹치지 않도록 클래스로 해서 폼에 값을 넣어줬다.

 

form 태그에 id값과 name값이 겹치지 않도록 조심할 것!!!

반응형
LIST
반응형
SMALL

[ 전자정부프레임워크 3.10 초기 설정 ]

전자정부프레임워크 기반의 제품 샘플을 제공하기 위해 기존에 만들어진 샘플 환경을 맞추고 최신제품으로 변환작업을 진행, 또한 새로운 샘플을 추가하기로 했다.

[ 작업 내용 ]
1. 기존 샘플을 최신버전 샘플로 변환하는 작업(7 -> 8) - 샘플 내용 및 데이터는 동일

2. 새로운 샘플 추가

1. 공통 적용 내용

  • 경로는 C://[제품명]_template/에 붙여넣기
  • 프로젝트 명 eGovTemplate 으로 맞출 것.
  • 최신화를 위해 jdk.1.8.0_192(x64)를 배포파일 내부에 넣고 적용.
  • 공통 문서 작업을 위해 포트번호 8090으로 통일함.

2. 기초 셋팅

1) eclipse.ini에서 -vm 으로 jdk 64bit 폴더 설정

기존 제품에서는 x86 버전의 jdk가 적용되어 있었다. 현재 사용하는 이클립스는 64비트용이므로 파일을 64bit용으로 변경해주고, 이클립스가 그걸 바라보도록 설정을 해줘야 한다.

공통 적용 내용대로 jdk.1.8.0_192를 배포파일 내부에 넣고 해당 경로를 가져와 openFile 아래에 -vm으로 추가해준다.

vm 추가 jdk 경로를 설정

openFile
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vm
C:\[제품명]_template\dev\jdk1.8.0_192\bin\javaw.exe

-vm

- 2~3번 라인에서는 -vm 옵션을 통해 eclipse가 사용할 JDK 경로를 설정한다. 
- '-vm' 옵션과 그의 value 값인 path는 별도 라인에 명시되어야 한다. 
- value 값인 path는 Java home 디렉토리가 아니라, Java executable 까지에 대한 path를 명시해주어야 한다.(exact path to javaw.exe)
- '-vm' 옵션은 '-vmargs' 옵션보다 먼저 수행된다. ('-vmargs' 옵션이 수행된 후에는 바로 JVM이 실행된다)
- 당연한거지만, 32bit 용 eclipse.exe에서는 32bit 용 JVM 이 사용되어야 하고, 64bit 용 eclipse.exe에서는 64bit용 JVM이 사용되어야 한다. 

참고 : (https://mine-it-record.tistory.com/307)

2) tomcat port 8090로 변경

이건 간단하게 서버 더블클릭해서 포트쪽 보면 HTTP/1.1 부분이 있다. 여기를 8090으로 바꿔준다.

포트번호 변경
server.xml 에서 변경해줘도 된다.

3) DB 확인

context-datasource.xml : 데이터베이스(DB) 연결 설정하는 곳 

 

전자정부 프레임워크 샘플 코드 분석 (context-datasource.xml)

전자정부 프레임워크 프로젝트 생성 시 샘플 코드를 포함시킨 상태로 생성하는 경우 샘플 코드에 대한 파일이 자동으로 구성된다. spring 설정 파일 중 context-datasource.xml 파일에 대해 내용이 어떻

bkjo94.tistory.com

 

<!-- datasource 설정(propertyConfigurer 활용) 사용할 데이터 소스를 여기서 가져와라 -->
<alias name="dataSource-${Globals.DbType}" alias="dataSource" />
<alias name="dataSource-${Globals.DbType}" alias="egov.dataSource" />

<!-- hsql -->

<jdbc:embedded-database id="dataSource-hsql" type="HSQL">
	<jdbc:script location= "classpath:/db/shtdb.sql"/>
	<jdbc:script location= "classpath:/db/ibsheetTemplatedb.sql"/>
</jdbc:embedded-database>

전자정부프레임워크 샘플에는 HSQL(구 HyperSQL)을 사용한다. HSQL은 메모리 DB라고도 불리는데, 작은사이즈의 시스템에서 무거운 DB 프로그램(오라클 등)을 사용하기 어려울 때 메모리에 적재되는 작은 DB를 설정하기 위해 사용된다.

HSQLDB는 메모리 방식이기 때문에 애플리케이션 실행될 때 HSQLDB가 초기화되면서 메모리에 적재된다. 즉, 애플리케이션이 실행될 때마다 모든 테이블 스키마와 데이터가 사라져버린다. 그래서 실행할 때마다 스키마 정보와 데이터를 데이터베이스에 적재시켜야한다.

그러므로 테이블을 생성하는 SQL이 들어있는 Schema.sql파일과 데이터를 추가하는 SQL이 들어있는 Data.sql파일을 생성한 후 임베디드 데이터베이스가 생성될 때마다 적재시켜준다.

▶ 고객들한테 매번 사용하는 DB 설정을 맞춰서 샘플을 열어보라고 할 필요없이 HSQL을 쓰면 조회 시 알아서 SQL 파일에 저장된 CRUD를 실행해준다.

<jdbc:embedded-database 쪽을 보면 내장 HSQL DB의 DataSource를 설정해 주었다. (type="HSQL" 이라고 명시되어있음.) 내장 DB의 위치도 링크를 걸어준다.(파일 2개) 그럼 db 폴더에 있는 sql을 알아서 실행해준다.

<alias name="dataSource-${Globals.DbType}" alias="dataSource" />

저 빨간색 부분에 hsql이 들어간다고 생각하면 된다. 즉, datasource 설정에서 alias(별칭)으로 dataSource-hsql 을 그냥 dataSource로 불러주는 것. 우리는 내장 메모리 DB를 사용할꺼야! 알아서 읽으렴!

globals.properties : 환경설정용... (데이터베이스, 첨부파일 경로 등)

# DB서버 타입(mysql,oracle,altibase,tibero) - datasource 및 sqlMap 파일 지정에 사용됨 전자정부에서 허용해주는 properties를 읽는 뭐..그런거 보안용 오라클 이름이나 이런거 감춰야허ㅏ니까.  주석 풀어서 사용
Globals.DbType = hsql
Globals.UserName=sa
Globals.Password=

# mysql
#Globals.DriverClassName=net.sf.log4jdbc.DriverSpy
#Globals.Url=jdbc:mysql://127.0.0.1:3306/sht

#oracle
#Globals.DriverClassName=oracle.jdbc.driver.OracleDriver
#Globals.Url=jdbc:oracle:thin:@127.0.0.1:1521:egovfrm

properties 파일은 응용 프로그램의 구성 가능한 파라미터들을 저장하기 위해 자바 관련 기술들을 사용하는 파일들을 위한 파일 확장. 즉, 설정파일의 설정파일인 것. properties는 키-값 형태로 저장된다.

globals.properties 스프링의 시스템 속성 설정 파일로 스프링의 서버, 시스템 타입 등을 설정한다. 여기서 DB 서버 타입을 설정할 수 있는데 위와 같이 hsql이라고 쓰여있다. #은 주석인데, 보니까 mysql과 oracle 등이 주석처리 되어있다. 우리는 hsql 사용하니까 이렇게 한거고, 다른 DB를 사용한다면 저 아래 주석 풀어서 사용되는 것.

전자정부프레임워크에서는 properties 파일들을 곧바로 이걸 한글로 읽을 수 있음. properties 를 읽을 수 있는 에디터가 내장되어있기 때문. 일반 스프링에서는 인코딩이 안맞아서 properties를 읽으려면 뭘 또 설치해줘야 한다.

사용 이유는 보안용이다. DB 오라클 이름이나 이런것들은 감춰야하니까...

4) 최신 버전 코어파일 넣기

만들기 전, 최신 버전 코어파일 및 설정파일을 따로 폴더를 파서 넣어준다. 우선 마이그레이션부터 진행할 예정.

반응형
LIST
반응형
SMALL

게시글 목록 페이지 만들기

관리자가 아닌 일반로그인 후 게시글 목록을 띄우는 블로그 메인페이지로 이동하도록 구현해보겠다.

[ 만들 기능 ]
1. 로그인 후 블로그 메인페이지로 이동
2. 메인페이지에 postDB에 있는 게시글 목록 리스트 띄우기

1. 로그인 후 일반회원이면 메인페이지로 가도록 링크 연결.
2. Controller에서 호출 URL을 받아 Action과 연결함.
3. Action에서 getPostList로 가져온 postList 배열값을 Service로 보내줌.
4. Service에서 커넥션 풀에서 DB 연결하고, 게시글 목록 배열로 담아옴.
5. DAO 안에서 SQL에 맞게 검색 후 결과값 리턴해서 Service에게 줌. (+커넥션 끊음)
6. Action에서 Service에게 받은 결과값(게시글 목록 배열)을 mainPage.jsp로 던져줌.
8. jsp 페이지에서 게시글 목록 리스트를 반복문으로 출력해줌.


1. 회원정보 테이블(기존 테이블) 및 게시글 테이블 만들기

--회원정보 테이블 생성
create table memberinfo(
    mem_no number(5) Primary key,
    mem_id varchar2(20) not null,
    mem_pwd varchar2(20) not null,
    mem_name varchar2(10) not null,
    mem_bir_yy VARCHAR(25),
    mem_bir_mm VARCHAR(25),
    mem_bir_dd VARCHAR(25),
    mem_gender VARCHAR(25),
    mem_mail VARCHAR(25),
    mem_phone VARCHAR(25),
    mem_regdate  date default sysdate,
    mem_pic  varchar2(90)
);

--임시 멤버 및 관리자 넣어놓기
insert into memberinfo values(1,'heannim12','heannim12','김히앤','2022','4','10','','','','','');
insert into memberinfo values(2,'shopAdmin','shopAdmin','관리자','2022','4','10','','','','','');
--게시글 테이블 생성(회원목록의 mem_no 연결)
create table post_info (
    post_no  number(4) Primary key,
    mem_no  number(5) not null,
    post_title  varchar2(60) not null,
    post_thumbnail  varchar2(80) not null,
    post_video varchar2(50),
    post_content  varchar2(5000) not null,
    visit_cnt  number(5) default 0,
    post_uploadtime  date default sysdate,
    
    foreign key(mem_no) REFERENCES memberinfo(mem_no)
);

--게시글도 테스트용 데이터 넣어놓기
insert into post_info values(1,1,'게시글1제목','post1.jpg','','게시글1내용게시글1내용게시글1내용게시글1내용게시글1내용게시글1내용',0,'');
insert into post_info values(2,1,'게시글2제목','post2.jpg','','게시글2내용게시글2내용게시글2내용게시글2내용게시글2내용게시글2내용',1,'');

2. 부트스트랩 연결

우선 메인페이지에 게시글 전체를 띄워보자.

블로그 메인페이지, 상세페이지 부트스트랩 사용함(부트스트랩 출처 : https://startbootstrap.com/template/blog-home)

블로그 메인페이지 부트스트랩

네이버와 깔맞춤 해주기 위해서 상단 네비게이션 배경색을 바꿔주었다.

--bs-dark-rgb: 0, 199, 60; /*네이버 배경색 맞춤*/

3. 어떤 화면에서 띄울 것인가?

로그인 화면에서 로그인을 할 때, "shopAdmin"이라는 아이디를 가진 관리자라면 회원목록이 나오도록 했다.

▼ MemberListAction.java

더보기
package action;
import java.io.PrintWriter;
import java.util.ArrayList;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import svc.MemberListService;
import vo.ActionForward;
import vo.MemberBean;

/* 인터페이스를 함께 추가했다. 로그인 후 분기 처리를 위한 클래스이다.*/
public class MemberListAction implements Action { //Action을 implements 해줌

	@Override
	public ActionForward execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {

		
		//session을 써서 서버 생성함.
		HttpSession session = req.getSession();
		// 로그인할 때는 setSession해서 가져오고
		// 여기 리스트에서는 get으로 뿌린다
		String id = (String) session.getAttribute("id");
		ActionForward forward = null; //어디로 갈지?

		
		//=========================== 로그인 후 분기처리 ================================
		//1. 회원 아님(id 정보 없음) => 로그인 안됨
		if (id == null) {
			// 세션에 저장된 아이디가 없다면~
			forward = new ActionForward();
			forward.setRedirect(true);
			forward.setPath("./memberLogin.me");
			// 회원이 아니니까 로그인 페이지로 이동하라.

			
		//2. 관리자 아니고 회원임 => 일반로그인
		} else if (!id.equals("shopAdmin")) {
			// 상점 주인이 아니면
			resp.setContentType("text/html;charset=UTF-8");
			PrintWriter out = resp.getWriter();
			out.println("<script>");
			out.println("alert('관리자가 아닙니다');");
			out.println("location.href='./postListAction.me'"); //관리자가 아니면 메인페이지로 이동
			out.println("</script>");

		//3. 관리자임 => 회원목록 보여짐
		} else {
			// 관리자가 맞다면 모든 회원 목록 표시.
			forward = new ActionForward();
			MemberListService memberListService = new MemberListService();
			ArrayList<MemberBean> memberList = memberListService.getMemberList();
			req.setAttribute("memberList", memberList);
			forward.setPath("./member_list.jsp");
		}

		return forward;
	}
}

이제 일반로그인을 하면 블로그 메인페이지로 연결되게 해주자. [postList]라는 이름으로 엮어줄 것임.

//2. 관리자 아니고 회원임 => 일반로그인
		} else if (!id.equals("shopAdmin")) {
			// 상점 주인이 아니면
			resp.setContentType("text/html;charset=UTF-8");
			PrintWriter out = resp.getWriter();
			out.println("<script>");
			out.println("alert('관리자가 아닙니다');");
			//관리자가 아니면 블로그 메인 페이지로 이동한다.
			out.println("location.href='./postListAction.me'");
			out.println("</script>");

4. Controller

먼저 컨트롤러에서 Action페이지로 연결해주자.

▼ MemberFrontController.java

//-------------------- 로그인이 된 후 메인페이지(게시글 목록) 보여주는 PostListAction 페이지 생성 ---------------------------
//메인 포스트 페이지에 정보만 띄워준다.
else if (command.equals("/member/postListAction.me")) {
    action = new PostListAction();
    // PostListAction, 로그인 후의 메인 포스트 페이지 표시.
    try {
        forward = action.execute(req, resp);
        System.out.println( "로그인 후 메인페이지 포스트 리스트 표시"))
    }
    catch (Exception e) {
        e.printStackTrace();
    }
}

5. Action

Action페이지에서 게시글 리스트를 PostBean에서 배열(ArrayList)로 받아 mainPage.jsp로 던져준다.

한번 더 로그인이 되어있는지 세션을 체크한다.

PostListAction.java

package action;
import java.util.ArrayList;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import svc.PostListService;
import vo.ActionForward;
import vo.PostBean;

/* 인터페이스를 함께 추가했다. 메인페이지 처리를 위한 클래스이다.*/
public class PostListAction implements Action { //Action을 implements 해줌

	@Override
	public ActionForward execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {
    
		//session을 써서 서버 생성함.
		HttpSession session = req.getSession();
		// 로그인할 때는 setSession해서 가져오고
		// 여기 리스트에서는 get으로 뿌린다
		String id = (String) session.getAttribute("id");
		ActionForward forward = null; //어디로 갈지?
        
		//1. 로그인 상태인지 확인
		if (id == null) {
			// 세션에 저장된 아이디가 없다면~
			forward = new ActionForward();
			forward.setRedirect(true);
			forward.setPath("./memberLogin.me");

		//2. 게시글 목록 보여짐	
		} else {
			// 모든 게시글 목록 표시.
			forward = new ActionForward();
			PostListService postListService = new PostListService();
			//배열로 게시글목록을 가져온다.
			ArrayList<PostBean> postList = postListService.getPostList(); 
			req.setAttribute("postList", postList);
			
			//mainPage로 게시글 목록을 던져준다.
			forward.setPath("./mainPage.jsp");
		}
		return forward;
	}
}

6. Service

service를 만들어주고 게시글 리스트를 가져오기 위해 DB와 JSP를 연결해준다.

커넥션 풀을 열어 커넥션 객체들을 풀에 저장해두었다가 클라이언트에서 요청하면 객체를 빌려주고 반납받아 풀에 저장한다. DB 접속용 DAO 객체도 참조로 얻어온다.

커넥션으로 DAO에서 selectPostList(=게시글 목록)를 받아오면 배열에 저장해서 리턴해준다.

리턴한 postList를 Action에서 받는 것.

PostListService.java

package svc;
import static db.JdbcUtil.close;
import static db.JdbcUtil.getConnection;
import java.sql.Connection;
import java.util.ArrayList;
import DAO.PostDAO;
import vo.PostBean;


/* 게시글를 띄울 시 DB와 JSP를 연결해주는 역할을 담당하는 클래스(Service) */
public class PostListService {
	
	public ArrayList<PostBean> getPostList() { //리스트이므로 배열로 가져온다.
		//커넥션 풀 : DB와 미리 연결해놓은 커넥션 객체들을 풀에 저장해뒀다가 클라에서 요청오면 객체 빌려주고 볼일 끝나면 다시 반납받아 풀에 저장하는 방식
		Connection con = getConnection();
		// DB와 연결을 얻어내고.
		PostDAO postDAO = PostDAO.getInstance();
		// DB접속용 DAO 객체 참조 얻어오기.(싱글톤 패턴 : 인스턴스가 1개만 생성됨)
		// import static db.JdbcUtil.*;
		postDAO.setConnection(con);
		// 얻어온 커넥션 저장. -> 연결해서 할일 함.
		ArrayList<PostBean> postList = postDAO.selectPostList(); //selectPostList는 PostDAO에서 받아온다.
		//커넥션으로 DB에서 게시글 목록 받아서 배열에 저장

		close(con);
		// 사용을 마친 커넥션 반환
		return postList;
		// 게시글 목록 리턴.
	}
}

7. DAO

DB접속용 DAO 객체를 만들어보자. 여기서 직접적으로 SQL 문을 돌려 원하는 데이터를 DB에서 가져온다.

DB에서 필요한 정보를 가져오되, 게시글 내용은 미리보기로 보여줄 것이므로 substring을 통해 잘라낸다.

PostDAO.java

package DAO;
import static db.JdbcUtil.close;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import javax.sql.DataSource;
import vo.PostBean;

public class PostDAO {

	//db패키지의 JdbcUtil을 통해 자바와 오라클이 연결이 가능해졌으니 이 두 프로그램을 연결했으면 이제 정보를 넘겨줘야한다.
	//DAO의 클래스에서 회원가입을 진행하면서 입력한 정보들을 오라클로 넘겨준다.
	
	public static PostDAO instance;
	Connection con;
	// jsp와 오라클 연결 유지.
	PreparedStatement pstmt;
	// 쿼리문 전달.
	ResultSet rs;
	// 쿼리문 결과 저장 객체.
	DataSource ds;
	// 어떤 DB에 연결할 지.

	private PostDAO() {

	}

	public static PostDAO getInstance() {
		if (instance == null) {
			instance = new PostDAO();
		} // 1개의 객체를 공동으로 사용.
		return instance;
	}

	public void setConnection(Connection con) {
		this.con = con;
	}

	//=========================== 로그인된 후 게시글 목록을 가져와 보여주는 SQL로직 ===============================
	// selectPostList : PostListService에서 DB와 JSP를 연결해서 게시글 목록을 배열로 가져와 저장할 때 인자로 쓰임.
	public ArrayList<PostBean> selectPostList() {
		// ArrayList: 객체 배열 비슷, 컬렉션 프로임워크
		// 여러 개의 게시글 정보를 저장한다.

		// 디비에 저장된 모든 게시글 목록을 확인하는 SQL문(DB 이름 확인하기***)
		String sql = "select * from post_info";

		ArrayList<PostBean> postList = new ArrayList<PostBean>();
		PostBean pb = null; //Bean(vo)은 그릇이다. 뭘 가져올지는 vo에 목록이 있다.

		try {
			pstmt = con.prepareStatement(sql);
			rs = pstmt.executeQuery(); //executeQuery : resultSet 객체 반환
			//select는 executeQuery()를 사용한다.
			//쿼리문 처리결과 ResultSet의 객체인 rs에 저장.

			if (rs.next()) {//조회된 결과가 있다면 아래 문장 수행.
				do {//한 번 수행하고 또 수행할 게 있으면 수행.
					pb = new PostBean();
					//게시글 1개의 정보를 저장할 수 있는 PostBean 객체 생성.
					pb.setPOST_NO(rs.getInt("POST_NO")); //게시글번호
					pb.setMEM_NO(rs.getInt("MEM_NO")); //회원번호
					pb.setPOST_TITLE(rs.getString("POST_TITLE")); //게시글제목
					pb.setPOST_THUMBNAIL(rs.getString("POST_THUMBNAIL")); //게시글섬네일
					pb.setPOST_VIDEO(rs.getString("POST_VIDEO")); //게시글비디오
					
					//--- 게시글 내용 가져와서 15자만 미리보기로 보여줌 ---
					String preStr=rs.getString("POST_CONTENT"); 
					if(preStr.length()>30){ 
						preStr=preStr.substring(0,15)+"..."; //자르고 ... 붙이기
					};
					pb.setPOST_CONTENT(preStr); //게시글내용 미리보기
					//----------------------------------------
					
					pb.setVisit_cnt(rs.getInt("Visit_cnt")); //게시글조회수
					pb.setPOST_UPLOADTIME(rs.getString("POST_UPLOADTIME")); //게시글업로드타임
					//조회된 결과를 PostBean객체에 저장.
					postList.add(pb);
					//저장하면서 생성된 것을 이제 List에 담아냄.(ArrayList)
					//반복문이 실행될 때마다 게시글 1개씩 누적 시킴.
				} while (rs.next());
				//rs.next때문에 어레이 리스트 다음 값으로 넘어간다.(차례차례 읽어옴)
			}
		} catch (Exception ex) {
			System.out.println("selectPostList 에러 : " + ex);
		} finally {
			close(rs);
			close(pstmt);
		}
		return postList;
	}
}

8. VO

DAO에서 가져온 DB데이터를 담을 변수를 선언한다. int와 String 등 자료형을 신경쓸 것!

 PostBean.java

package vo;

public class PostBean {
	
	//사용할 변수들 선언
	private int POST_NO;
	private int MEM_NO;
	
	private String POST_TITLE;
	private String POST_THUMBNAIL;
	private String POST_VIDEO;
	private String POST_CONTENT;
	private int visit_cnt;
	private String POST_UPLOADTIME;
	
	//그 후 source > getter,setter
	
	public int getPOST_NO() {
		return POST_NO;
	}
	public void setPOST_NO(int pOST_NO) {
		POST_NO = pOST_NO;
	}
	public int getMEM_NO() {
		return MEM_NO;
	}
	public void setMEM_NO(int mEM_NO) {
		MEM_NO = mEM_NO;
	}
	public String getPOST_TITLE() {
		return POST_TITLE;
	}
	public void setPOST_TITLE(String pOST_TITLE) {
		POST_TITLE = pOST_TITLE;
	}
	public String getPOST_THUMBNAIL() {
		return POST_THUMBNAIL;
	}
	public void setPOST_THUMBNAIL(String pOST_THUMBNAIL) {
		POST_THUMBNAIL = pOST_THUMBNAIL;
	}
	public String getPOST_VIDEO() {
		return POST_VIDEO;
	}
	public void setPOST_VIDEO(String pOST_VIDEO) {
		POST_VIDEO = pOST_VIDEO;
	}
	public String getPOST_CONTENT() {
		return POST_CONTENT;
	}
	public void setPOST_CONTENT(String pOST_CONTENT) {
		POST_CONTENT = pOST_CONTENT;
	}
	public int getVisit_cnt() {
		return visit_cnt;
	}
	public void setVisit_cnt(int visit_cnt) {
		this.visit_cnt = visit_cnt;
	}
	public String getPOST_UPLOADTIME() {
		return POST_UPLOADTIME;
	}
	public void setPOST_UPLOADTIME(String pOST_UPLOADTIME) {
		POST_UPLOADTIME = pOST_UPLOADTIME;
	}
}

9. jsp에서 게시글 목록 출력하기

ArrayList를 jsp로 뿌려주었으니 출력해보자. 간단하게 jstl를 이용해서 c:forEach로 리스트를 출력해줄 것이다.

단, 섬네일은 이름만 받아서 "post1.jpg"과 같이 이름만 받아왔으므로, 이미지 src에 정확한 경로를 앞에 추가해주어야 한다. 이미지는 미리 그 경로에 DB와 동일한 이름으로 저장해두자.

이미지는 미리 경로에 넣어둠

...

		<!-- Page header with logo and tagline-->
        <header class="py-5 bg-light border-bottom mb-4">
            <div class="container">
                <div class="text-center my-5">
                    <h1 class="fw-bolder"> ${postList[0].MEM_NO}회원님의 블로그 홈에 오신걸 환영합니다!</h1>
                    <p class="lead mb-0">여기는 블로그 홈페이지입니다.배경사진 넣을꺼임.</p>
                </div>
            </div>
        </header>
        <!-- Page content-->
        <div class="container">
       
            <div class="row">
                <!-- Blog entries-->
                <div class="col-lg-8">
                        <c:forEach var="postList" items="${postList}">
                    <!-- Featured blog post -->
                    <div class="card mb-4">
                        <div class="card-body">
                           <a href="#!"><img class="card-img-top" src="../resources/img/thumbnail/${postList.POST_THUMBNAIL}" alt="..." /></a>
                          
                          <div class="small text-muted">${postList.POST_UPLOADTIME}</div>
                            <h2 class="card-title">${postList.POST_TITLE} -----  ${postList.MEM_NO}</h2>
                            <p class="card-text">${postList.POST_CONTENT}</p>
                            <a class="btn btn-primary" href="#!">Read more →</a>
                        </div>
                    </div>
                    </c:forEach>
...

mainPage.jsp 전체

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ page import="vo.MemberBean"%>
<%@ page import="java.util.*"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- 빨간줄 그어지는데 jstl 설치 안해서 그럼. lib에 넣어준다. jsp 확장태그로 c로 쓴다.-->


<!DOCTYPE html>
<html lang="ko">
    <head>
    <!-- 부트스트랩 출처 : https://startbootstrap.com/template/blog-home -->
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
        <meta name="description" content="" />
        <meta name="author" content="" />
        <title>Blog Home</title>
        <!-- Favicon-->
      <!--   <link rel="icon" type="image/x-icon" href="assets/favicon.ico" />  -->
        <!-- Core theme CSS (includes Bootstrap)-->
        <link href="../resources/css/mainPage.css" rel="stylesheet" />
    </head>
    <body>
        <!-- Responsive navbar-->
        <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
            <div class="container">
                <a class="navbar-brand" href="#!">N Blog</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>
                <div class="collapse navbar-collapse" id="navbarSupportedContent">
                    <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
                        <li class="nav-item"><a class="nav-link" href="#">Home</a></li>
                        <li class="nav-item"><a class="nav-link" href="#!">About</a></li>
                        <li class="nav-item"><a class="nav-link" href="#!">Contact</a></li>
                        <li class="nav-item"><a class="nav-link active" aria-current="page" href="#">Blog</a></li>
                    </ul>
                </div>
            </div>
        </nav>
        <!-- Page header with logo and tagline-->
        <header class="py-5 bg-light border-bottom mb-4">
            <div class="container">
                <div class="text-center my-5">
                    <h1 class="fw-bolder"> ${postList[0].MEM_NO}회원님의 블로그 홈에 오신걸 환영합니다!</h1>
                    <p class="lead mb-0">여기는 블로그 홈페이지입니다.배경사진 넣을꺼임.</p>
                </div>
            </div>
        </header>
        <!-- Page content-->
        <div class="container">
       
            <div class="row">
                <!-- Blog entries-->
                <div class="col-lg-8">
                        <c:forEach var="postList" items="${postList}">
                    <!-- Featured blog post -->
                    <div class="card mb-4">
                        <div class="card-body">
                           <a href="#!"><img class="card-img-top" src="../resources/img/thumbnail/${postList.POST_THUMBNAIL}" alt="..." /></a>
                          
                          <div class="small text-muted">${postList.POST_UPLOADTIME}</div>
                            <h2 class="card-title">${postList.POST_TITLE} -----  ${postList.MEM_NO}</h2>
                            <p class="card-text">${postList.POST_CONTENT}</p>
                            <a class="btn btn-primary" href="#!">Read more →</a>
                        </div>
                    </div>
                    </c:forEach>
                    
                    <!-- Pagination-->
                    <nav aria-label="Pagination">
                        <hr class="my-0" />
                        <ul class="pagination justify-content-center my-4">
                            <li class="page-item disabled"><a class="page-link" href="#" tabindex="-1" aria-disabled="true">Newer</a></li>
                            <li class="page-item active" aria-current="page"><a class="page-link" href="#!">1</a></li>
                            <li class="page-item"><a class="page-link" href="#!">2</a></li>
                            <li class="page-item"><a class="page-link" href="#!">3</a></li>
                            <li class="page-item disabled"><a class="page-link" href="#!">...</a></li>
                            <li class="page-item"><a class="page-link" href="#!">15</a></li>
                            <li class="page-item"><a class="page-link" href="#!">Older</a></li>
                        </ul>
                    </nav>
                </div>
                <!-- Side widgets-->
                <div class="col-lg-4">
                    <!-- Search widget-->
                    <div class="card mb-4">
                        <div class="card-header">Search</div>
                        <div class="card-body">
                            <div class="input-group">
                                <input class="form-control" type="text" placeholder="Enter search term..." aria-label="Enter search term..." aria-describedby="button-search" />
                                <button class="btn btn-primary" id="button-search" type="button">Go!</button>
                            </div>
                        </div>
                    </div>
                    <!-- Categories widget-->
                    <div class="card mb-4">
                        <div class="card-header">Categories</div>
                        <div class="card-body">
                            <div class="row">
                                <div class="col-sm-6">
                                    <ul class="list-unstyled mb-0">
                                        <li><a href="#!">Web Design</a></li>
                                        <li><a href="#!">HTML</a></li>
                                        <li><a href="#!">Freebies</a></li>
                                    </ul>
                                </div>
                                <div class="col-sm-6">
                                    <ul class="list-unstyled mb-0">
                                        <li><a href="#!">JavaScript</a></li>
                                        <li><a href="#!">CSS</a></li>
                                        <li><a href="#!">Tutorials</a></li>
                                    </ul>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!-- Side widget-->
                    <div class="card mb-4">
                        <div class="card-header">Side Widget</div>
                        <div class="card-body">You can put anything you want inside of these side widgets. They are easy to use, and feature the Bootstrap 5 card component!</div>
                    </div>
                </div>
            </div>
           
        </div>
        <!-- Footer-->
        <footer class="py-5 bg-dark">
            <div class="container"><p class="m-0 text-center text-white">Copyright &copy; Your Website 2022</p></div>
        </footer>
        <!-- Bootstrap core JS-->
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
        <!-- Core theme JS-->
       <!-- <script src="js/scripts.js"></script> -->
    </body>
</html>

10. 마무리로 조절하기

이미지가 너무 커서 리스트 모양이 이쁘지 않으므로, css로 섬네일 이미지 크기를 고정해준다.

.card-img,
.card-img-top,
.card-img-bottom {
/* 섬네일 이미지 크기 고정 및 왼쪽으로 */
  width: 200px;
  height:200px;
  vertical-align:middle;
  float:left; 
}

 

결과

 

++추가) 게시글 목록에 이웃들 글만 보이게 하기(session값 DAO로 보냄)


전체 블로그 게시글 목록을 띄우는게 아니라 "로그인 한 나"를 제외한 나머지 글들이 보이게끔 변경해줘봤다.

약간 헤맸는데, 이미 로그인하면서 session에 현재 로그인한 id값은 저장되어 있고... 그럼 SQL 문에서 현재 session에 접속된 id값에 해당하는 멤버가 아닌 멤버의 게시글들을 전부 불러오면 되는거 아닌가?

select * from post_info p join memberinfo m on p.mem_no = m.mem_no 
where m.mem_id !='heannim12';

현재 로그인한 계정의 id는 [heannim12] 이다. JOIN 문을 써서 FK로 연결한 mem_no가 같다는 조건 하에 mem_id가 [heannim12]인 테이블만 전부 뽑아보았다.(즉, mem_no 가 1이 아니어야만 한다.)

mem_no가 1이 아닌 애들만 뽑혔다.

현재 나는 DAO에서 SQL문을 써서 진행하고 있는데...Action 페이지에서부터 어떻게 session값을 가져가야하나...생각하다가 파라미터로 들려주기로 했다.

이렇게 Service로 갈 때 들려보내고

ArrayList<PostBean> postList = postListService.getPostList(sessionId);

String sessionId로 받아서 그대로 다시 DAO에게 전달해줬다.

DAO 갈때도 들려보내줬다.

ArrayList<PostBean> postList = postDAO.selectPostList(sessionId);

DAO까지 잘 들고온 sessionId값을 SQL문의 물음표에 넣어준다!

SQL 문에 조건으로 넣어준다.

String sql = "select * from post_info p join memberinfo m on p.mem_no = m.mem_no where m.mem_id != ?";

...

//세션 id값 가져와서 SQL 문에 넣어줌.
pstmt.setString(1, sessionId);

결과

++추가) sessionScope 이용해서 jsp 페이지에 세션값 보여주기

${sessionScope.id} 를 사용하면 세션에 저장된 id 값을 가져올 수 있다. 그럼 위처럼 메인에 현재 접속된 세션값 회원 이름을 출력할 수 있음!

<div class="text-center my-5">
  <h1 class="fw-bolder"> ${sessionScope.id} 회원님! 블로그 메인홈에 오신걸 환영합니다!</h1>
  <p class="lead mb-0">이곳에서는 나를 제외한 모든 블로거들의 글을 볼 수 있습니다.</p>
</div>

 

 


다음은 게시글 목록과 게시글 상세보기를 연결해보자.

 

▼ 진행중인 gitHub 링크를 남깁니다.

 

GitHub - k-haein/BlogPrj: 회원가입/로그인/게시글 등록 등의 블로그를 처음부터 만듭니다.

회원가입/로그인/게시글 등록 등의 블로그를 처음부터 만듭니다. Contribute to k-haein/BlogPrj development by creating an account on GitHub.

github.com

 

반응형
LIST
반응형
SMALL

+ Recent posts

반응형
LIST