private Member loginMemberFindByToken(){
String loginEmail = SecurityContextHolder.getContext().getAuthentication().getName(); // 토큰에서 유저 email 확인return memberService.findMemberByEmail(loginEmail); //이메일을 통해 유저 엔티티 반환
}
필요한 코드 -
Service
public Member findMemberByEmail(String email){ //로그인 이메일을 통해 유저 엔티티 반환 메서드
Optional<Member> foundMember = memberRepository.findByEmail(email);
return foundMember.orElseThrow(()-> new BusinessLogicException(ExceptionCode.MEMBER_NOT_FOUND));
}
나는 400/401에러가 계속났는데 yml의 id와 key를 잘못 입력하고 원인을 다른곳에서 찾아 몇시간을 헤맸다.
yml 설정부
naver:#naver API 설정url:search:news:https://openapi.naver.com/v1/search/news.json#뉴스검색 URLimage:https://openapi.naver.com/v1/search/image#이미지검색client:id:ENC(rbiCFlHAp11Uusawse9EDX4NTmpRvfEJewqabaeeqefvZM=)#암호화된 키secret:ENC(CbqkdospKojXkFsiY2OueQOdLpMbveCTJkbKN9/)
Dto
publicclassSearchNewsDto{
@Data@NoArgsConstructor@AllArgsConstructorpublicstaticclassPost{ //검색 쿼리privateString query = ""; //검색어. UTF-8로 인코딩되어야 합니다.private int display = 20; //한 번에 표시할 검색 결과 개수(기본값: 10, 최댓값: 100)private int start = 1; //검색 시작 위치(기본값: 1, 최댓값: 1000)privateString sort = "sim"; // sim: 정확도순 , date: 날짜순/*데이터를 한꺼번에 들어가게 해주는 메서드*/public MultiValueMap<String, String> toMultiValueMap() {
var map = new LinkedMultiValueMap<String, String>();
map.add("query", query);
map.add("display", String.valueOf(display));
map.add("start", String.valueOf(start));
map.add("sort", sort);
return map;
}
}
@Data@NoArgsConstructor@AllArgsConstructorpublicstaticclassResponse{ //반환값privateString lastBuildDate; //검색한 결과를 생성한 시간private int total; // 총 검색결과 갯수private int start; // 검색 시작 위치private int display; // 한번에 표시할 검색결과 갯수private List<NewsItem> items;
@Data@NoArgsConstructor@AllArgsConstructorpublicstaticclassNewsItem{
privateString title; //제목privateString originallink; // 뉴스기사 원문 URLprivateString link; //뉴스 기사의 네이버 뉴스 URL. 네이버에 제공되지 않은 기사라면 기사 원문의 URL을 반환합니다.privateString description; // 뉴스기사 내용을 요약한 정보privateString pubDate;
}
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-web'
runtimeOnly 'com.mysql:mysql-connector-j'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-rest'// data rest기능 / api빠르게만들수있음
implementation 'org.springframework.data:spring-data-rest-hal-explorer'// 해당내용을 시각적으로 보는것
runtimeOnly 'com.h2database:h2'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'// queryDSL 설정// 엔티티 검색기능 사용 가능
implementation "com.querydsl:querydsl-jpa"
implementation "com.querydsl:querydsl-core"
implementation "com.querydsl:querydsl-collections"
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa"// querydsl JPAAnnotationProcessor 사용 지정
annotationProcessor "jakarta.annotation:jakarta.annotation-api"// java.lang.NoClassDefFoundError (javax.annotation.Generated) 대응 코드
annotationProcessor "jakarta.persistence:jakarta.persistence-api"// java.lang.NoClassDefFoundError (javax.annotation.Entity) 대응 코드
}
tasks.named('test') {
useJUnitPlatform()
}
// Querydsl 설정부
def generated = 'src/main/generated'//파일경로 // build디렉터리 안에 있는걸 눈에 보이게 꺼내옴// ide같은 툴을 사용해서 발생할 수 있는 잠재적 문제를 해결하기위함// querydsl QClass 파일 생성 위치를 지정
tasks.withType(JavaCompile) {
options.getGeneratedSourceOutputDirectory().set(file(generated))
}
// java source set 에 querydsl QClass 위치 추가
sourceSets {
main.java.srcDirs += [ generated ]
}
// gradle clean 시에 QClass 디렉토리 삭제
clean {
delete file(generated)//build clean할때 해당 파일도 같이 삭제
- Article 엔티티에 대한 레파지토리
package main22.community.repository;
import com.querydsl.core.types.dsl.DateTimeExpression;
import com.querydsl.core.types.dsl.StringExpression;
import main22.community.domain.entity.Article;
import main22.community.domain.entity.QArticle;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer;
import org.springframework.data.querydsl.binding.QuerydslBindings;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
//@Repository안붙여도 정상동작함 상속하는 클래스에 이미 붙어있음@RepositoryRestResource// spring data rest 사용하기 위함publicinterfaceArticleRepositoryextendsJpaRepository<Article, Long>,
QuerydslPredicateExecutor<Article>, //해당 엔티티 안에있는 모든 검색기능을 추가해줌 // 완전 동일해야만 동작
QuerydslBinderCustomizer<QArticle> // 부분검색, 대소문자 구분 등을 위함
{
@Overridedefaultvoidcustomize(QuerydslBindings bindings, QArticle root){
//Article에 대해 선택적인 필드에 대한 검색
bindings.excludeUnlistedProperties(true); //리스팅 하지 않은 프로퍼티 검색 제외
bindings.including(root.title, root.content, root.hashtag, root.createdAt, root.createdBy); //검색 컬럼
bindings.bind(root.title).first(StringExpression::containsIgnoreCase); // like '%${v}%'/ 부분검색
bindings.bind(root.content).first(StringExpression::containsIgnoreCase);
bindings.bind(root.hashtag).first(StringExpression::containsIgnoreCase);
bindings.bind(root.createdAt).first(DateTimeExpression::eq);//원하는 날짜검색 /시분초 동일하게 넣어야함
bindings.bind(root.createdBy).first(StringExpression::containsIgnoreCase);
}
}
- application.yml 설정부
spring:
data: # spring data rest - 관련 설정
rest:
base-path: /api #endpoint start path
detection-strategy: annotated
article엔티티의 title 테이블 검색방법 ex) http://localhost:8080/api/articles?title="(부분)검색" 으로 사용하면 된다