Git 명령어 통해서 저장소 옮기기
#기존 저장소명 변경
git remote rename origin origin_backup
#변경할 저장소 추가
git remote add origin https://github.com/mandiwise/awesome-new-repo.git
#저장소로 파일 업로드
git push origin master
#기존 저장소 삭제
git remote rm origin_backup
#기존 저장소명 변경
git remote rename origin origin_backup
#변경할 저장소 추가
git remote add origin https://github.com/mandiwise/awesome-new-repo.git
#저장소로 파일 업로드
git push origin master
#기존 저장소 삭제
git remote rm origin_backup
CREATE DATABASE test default CHARACTER SET UTF8;
use test;
DROP table IF EXISTS menu;
CREATE TABLE menu (
no int PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
parent int NULL,
depth int NOT NULL,
sequence int,
reg_date DATETIME,
modify_date DATETIME
)ENGINE=INNODB;
DESCRIBE menu;
DROP TABLE menu;
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date) VALUES("메뉴1" ,0 ,1, 1, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date) VALUES("메뉴1-1" ,1 ,2, 1, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date) VALUES("메뉴1-2" ,1 ,2, 2, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date) VALUES("메뉴1-1-1" ,2 ,3, 1, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date) VALUES("메뉴2" ,0 ,1, 2, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date) VALUES("메뉴2-1" ,5 ,2, 1, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date) VALUES("메뉴2-2" ,5 ,2, 2, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date) VALUES("메뉴2-1-1" ,6 ,3, 1, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date) VALUES("메뉴1-1-2" ,2 ,3, 2, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date) VALUES("메뉴2-1-2" ,6 ,3, 2, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date) VALUES("메뉴2-1-3" ,6 ,3, 3, now(), now());
SELECT * FROM menu;
/* 계층형 mysql 쿼리 정렬 함수 */
DROP FUNCTION IF EXISTS hierarchy_connect_by_parent_eq_prior_no;
DELIMITER $$
CREATE FUNCTION hierarchy_connect_by_parent_eq_prior_no(value INT) RETURNS INTEGER
NOT DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE _parent INT;
DECLARE _rank INT;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET @id = NULL;
SET _parent = @id;
SET _rank = 0;
IF @id IS NULL THEN
RETURN NULL;
END IF;
LOOP
SET @innerrank = 0;
SELECT p.no
INTO @id
FROM (
SELECT no, @innerrank := @innerrank+1 AS ran
FROM menu
WHERE COALESCE(parent, 0) = _parent
ORDER BY sequence
) p
WHERE p.ran > _rank LIMIT 0, 1;
IF @id IS NOT NULL OR _parent = @start_with THEN
SET @level = @level + 1;
RETURN @id;
END IF;
SET @level := @level - 1;
SET @innerrank = 0;
SELECT COALESCE(p.parent, 0), p.ran
INTO _parent, _rank
FROM (
SELECT no, parent, @innerrank := @innerrank+1 AS ran
FROM menu
WHERE COALESCE(parent, 0) = (
SELECT COALESCE(parent, 0) FROM menu WHERE no = _parent
)
ORDER BY sequence
) p
WHERE p.no = _parent;
END LOOP;
END;
$$
DELIMITER ;
/* 계층형 메뉴 정렬*/
SELECT CONCAT(REPEAT(' ', depth - 1), CAST(ou.no AS CHAR)) AS no, parent, depth, CONCAT(REPEAT(' ', depth - 1), CAST(ou.name AS CHAR)) AS name, sequence, level FROM (
SELECT mn.name , mn.no, depth , parent, sequence, level FROM (
SELECT hierarchy_connect_by_parent_eq_prior_no(no) AS no,
@level AS level
FROM (
SELECT @start_with := 0, @id := @start_with, @level := 0
) vars, menu
WHERE @id IS NOT NULL
) m
JOIN menu mn ON mn.no = m.no
) ou;
/* 계층형 mysql 쿼리 정렬 함수 - 특정 번호 */
DROP FUNCTION IF EXISTS hierarchy_connect_by_parent_eq_prior_id;
DELIMITER $$
CREATE FUNCTION hierarchy_connect_by_parent_eq_prior_id(value INT) RETURNS INTEGER
NOT DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE _no INT;
DECLARE _parent INT;
DECLARE _next INT;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET @no = NULL;
SET _parent = @no;
SET _no = -1;
IF @no IS NULL THEN
RETURN NULL;
END IF;
LOOP
SELECT MIN(no)
INTO @no
FROM menu
WHERE parent = _parent
AND no > _no;
IF @no IS NOT NULL OR _parent = @start_with THEN
SET @depth = @depth + 1;
RETURN @no;
END IF;
SET @depth := @depth - 1;
SELECT no, parent
INTO _no, _parent
FROM menu
WHERE no = _parent;
END LOOP;
END;
$$
DELIMITER ;
/* 조건에 따라 메뉴 출력 */
SELECT mn.name , mn.no, depth , parent, sequence
FROM (
SELECT no, @depth AS vars_depth FROM menu WHERE no= '원하는메뉴번호'
UNION ALL
SELECT hierarchy_connect_by_parent_eq_prior_id(no) AS no, @depth AS vars_depth
FROM (
SELECT @start_with := '원하는메뉴번호',
@no := @start_with,
@depth := 0
) vars, menu
WHERE @no IS NOT NULL
) fn
JOIN menu mn
ON mn.no = fn.no;
<mvc:resources mapping="/resources/**" location="/resources/" />
<!DOCTYPE html>
<html lang="ko">
<head>
<script src="/resources/ckeditor/ckeditor.js"></script>
<script>
window.onload = function(){
ck = CKEDITOR.replace("editor");
};
</script>
</head>
<body>
<form>
<textarea name="editor1" id="editor1" rows="10" cols="80">
This is my textarea to be replaced with CKEditor.
</textarea>
</form>
</body>
</html>
<script src="/resources/components/ckeditor/ckeditor.js"></script>
<script>
var editorConfig = {
filebrowserUploadUrl : "/ckEditor/imgUpload", //이미지 업로드
};
CKEDITOR.on('dialogDefinition', function( ev ){
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
switch (dialogName) {
case 'image': //Image Properties dialog
//dialogDefinition.removeContents('info');
dialogDefinition.removeContents('Link');
dialogDefinition.removeContents('advanced');
break;
}
});
window.onload = function(){
ck = CKEDITOR.replace("editor", editorConfig);
};
</script>
//파일 기본경로
String defaultPath = request.getSession().getServletContext().getRealPath("/");
//파일 기본경로, 상세경로
String filePath = defaultPath + "resources" + File.separator + "ckEditorImg" + File.separator;
파일을 저장한 위치와 요청한 url을 매칭시키는 설정을 추가한다.<mvc:resources mapping="/ckEditorImg/**" location="/resources/ckEditorImg/" />
ckeditor/plugins
디렉토리에 넣는다<script src="/resources/components/ckeditor/ckeditor.js"></script>
<script>
var editorConfig = {
filebrowserUploadUrl : "/ckEditor/imgUpload?type=image", //이미지만 업로드
extraPlugins : 'uploadimage'
};
CKEDITOR.on('dialogDefinition', function( ev ){
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
switch (dialogName) {
case 'image': //Image Properties dialog
//dialogDefinition.removeContents('info');
dialogDefinition.removeContents('Link');
dialogDefinition.removeContents('advanced');
break;
}
});
window.onload = function(){
ck = CKEDITOR.replace("editor", editorConfig);
};
</script>
public class LoginUserInfoArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
Class clazz = methodParameter.getParameterType();
if(clazz == LoginUserInfo.class)
return true;
return false;
}
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
LoginUserInfo loginUserInfo = (LoginUserInfo)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return loginUserInfo;
@SpringBootApplication
public class LoginApplication{
public static void main(String[] args) {
SpringApplication.run(LoginApplication.class, args);
}
@Override
public void addArgumentResolvers(List resolvers) {
resolvers.add(new LoginUserInfoArgumentResolver());
}
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>true</scope>
</dependency>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.8.RELEASE</version>
</dependency>
</dependencies>
</plugin>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
@RunWith(SpringRunner.class) @WebMvcTest(BoardController.class)
@Autowired private MockMvc mvc;
mvc.perform(get("/boards").with(new RequestPostProcessor() {
@Override
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest mockHttpServletRequest) {
User user = new User();
user.setId(1L);
user.setName("홍길동");
mockHttpServletRequest.setAttribute("loginUser", user);
return mockHttpServletRequest;
}
}))
.andExpect(status().isOk()) // 200 OK면 성공
.andExpect(model().attribute("list", page)) // ModelMap에 값을 담으면, 템플릿까지 값이 전달된다. Controller에서 ModelMap에 "list"란 이름으로 값을 담았는데, 그게 page와 같은지 본다.
.andExpect(content().string(containsString("test1"))); // content()는 템플릿엔진을 통해 랜더링한 결과에 "test1"이라는 문자열이 있는지 본다.
}
mvc는 Spring MVC가 controller를 실행하는 것을 시뮬레이션 한다. perform메소드는 controller의 특정메소드를 get, post, put, delete등으로 실행하도록 한다.@MockBean BoardService boardService;
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>5.0.4.RELEASE</version>
<scope>test</scope>
</dependency>
@WithMockUser(username = "admin@gmail.com", authorities = {"USER"})로그인한 사용자의 username과 권한을 지정할 수 있다.
// with()부분은 Controller가 아닌 인터셉터에서 로그인한 정보를 저장하는데,
// 이 부분이 템플릿에서 사용하기 때문에 request에 로그인한 정보를 넣어줌.
ResultActions content1 = mvc.perform(get("/boards/1")
.with(mockHttpServletRequest -> {
User user = new User();
user.setId(1L);
user.setName("홍길동");
mockHttpServletRequest.setAttribute("loginUser", user);
return mockHttpServletRequest;
}))
.andExpect(status().isOk())
.andExpect(content().string(containsString("content1")));
인터셉터에서 정보를 넣어주는 로직이 있을때 사용한다.@RunWith(SpringRunner.class) @SpringBootTest @Transactional public class UserRepositoryTest
@RunWith(SpringRunner.class) @DataJpaTest public class UserRepositoryTest
java -jar /Users/mac/programing/CI/jenkins/jenkins.war --httpPort=9999 > /Users/mac/programing/CI/jenkins/app.log 2> /Users/mac/programing/CI/jenkins/error.log &
실행 확인ps -ef | grep jenkins
@RunWith(SpringRunner.class) @SpringBootTest @Transactional public class UserRepositoryTest
@RunWith(SpringRunner.class) @DataJpaTest public class UserRepositoryTest
sudo launchctl unload /System/Library/LaunchDaemons/org.apache.httpd.plist
#도커 이미지 목록
docker images
#도커 컨테이너 전체 목록
docker container ls -all
#도커 실행중인 목록
docker ps
#도커 컨테이너 전체 목록
docker ps -a
#도커 죽이기
docker kill 컨테이너id
#도커 삭제하기
docker rm 컨테이너 id
#도커 이미지 삭제하기
docker rmi 컨테이너 id
#Compose 파일로 컨테이너 생성(-d : 백그라운드 실행), docker-compose.yml파일이 있는곳 실행
docker-compose up -d
#Compose 파일에 정의 된 서비스 용 컨테이너 제거
docker-compose down
#도커 이미지 생성 및 태그 부여(현재지점)
#tag명:버전 (입력하지않으면 latest로 입력되고 생성할대 마다 이미지가 계속 쌓인다)
docker build -t 태그명 .
#도커 이미지 실행
#-d : 백그라운드 실행
docker run -p 내컴퓨터포트:도커연결할포트 태그명 -d
#로그보기
docker logs 컨테이너id
#도커로그인
docker login
#도커이미지 복사하기
docker tag 내컴퓨터에있는이미지명 계정명/생성할이미지명:생성할태그명
#도커hub에 이미지 업로드
docker push 계정명/이미지명:태그명
#도커서비스 목록
docker service ls
docker service ps 서비스명
#도커 swam시작하기(라운드로빈가능)
docker swarm init
#docker swam join문을 실행하여 다른 컴퓨터와 연결할 수 있다.
docker swarm join --token 토큰키 아이피:포트
#docker yml설정 파일 기반으로 swam실행하고 이름 지정하기
docker stack deploy -c docker-compose.yml swam생성이름
#docker-compose.yml 예제
version: "3"
services:
web:
# replace username/repo:tag with your name and image details
image: username/repo:tag
deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
ports:
- "80:80"
networks:
- webnet
networks:
webnet:
#docker swam 서비스중인 목록
docker service ls
#docker swam 이름으로 실행중인 서비스 목록 보기
docker service ps swam생성이름
#docker swam 종료
docker swarm leave --force
#docker swam 제거
docker stack rm swam생성이름
#도커 이미지 목록
docker images
#도커 컨테이너 전체 목록
docker container ls -all
#도커 실행중인 목록
docker ps
#도커 컨테이너 전체 목록
docker ps -a
#도커 죽이기
docker kill 컨테이너id
#도커 삭제하기
docker rm 컨테이너 id
#도커 이미지 삭제하기
docker rmi 컨테이너 id
#도커 이미지 생성 및 태그 부여(현재지점)
#tag명:버전 (입력하지않으면 latest로 입력되고 생성할대 마다 이미지가 계속 쌓인다)
docker build -t 태그명 .
#도커 이미지 실행
#-d : 백그라운드 실행
docker run -p 내컴퓨터포트:도커연결할포트 태그명 -d
#로그보기
docker logs 컨테이너id
#도커로그인
docker login
#도커이미지 복사하기
docker tag 내컴퓨터에있는이미지명 계정명/생성할이미지명:생성할태그명
#도커hub에 이미지 업로드
docker push 계정명/이미지명:태그명
#도커서비스 목록
docker service ls
docker service ps 서비스명
#도커 swam시작하기
docker swarm init
#docker swam join문을 실행하여 다른 컴퓨터와 연결할 수 있다.
docker swarm join --token 토큰키 아이피:포트
#docker yml설정 파일 기반으로 swam실행하고 이름 지정하기
docker stack deploy -c docker-compose.yml swam생성이름
#docker-compose.yml 예제
version: "3"
services:
web:
# replace username/repo:tag with your name and image details
image: username/repo:tag
deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
ports:
- "80:80"
networks:
- webnet
networks:
webnet:
#docker swam 서비스중인 목록
docker service ls
#docker swam 이름으로 실행중인 서비스 목록 보기
docker service ps swam생성이름
#docker swam 종료
docker swarm leave --force
#docker swam 제거
docker stack rm swam생성이름
git remote add origin URL_TO_YOUR_REPO
git push origin master -f
git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch *.yml' --prune-empty -- --all # 모든 히스토리에서 해당 파일 삭제
git push origin --force --all
git rm file1.txt
git commit -m "remove file1.txt"
git push
git rm --cached file1.txt
git commit -m "remove file1.txt"
git push
#파일권한 변경
chmod 400 키파일디렉토리/lalwrj.pem
sudo passwd
처음엔 일반사용자 패스워드 입력.su -
sudo cp /home/ec2-user/.ssh/authorized_keys /root/.ssh
service sshd restart
wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u171-b11/512cd62ec5174c3487ac17c61aaa89e8/jdk-8u171-linux-x64.tar.gz"
압출풀기
tar xvzf jdk-8u171-linux-x64.tar.gz
tar xvzf jdk-8u171-linux-x64.tar.gz
mv jdk1.8.0_171 /loal/java/
java -version
javac -version
기존 설치 버전이 계속 사용되면 제거 후 다시 확인
rpm -qa | grep jdk
yum remove jdk명
tar xvzf apache-tomcat-8.5.31.tar.gz
파일 이동mv apache-tomcat-8.5.31.tar.gz /local/tomcat8.5
wget http://mirror.apache-kr.org/maven/maven-3/3.5.4/binaries/apache-maven-3.5.4-bin.tar.gz
압출풀기tar xvzf apache-maven-3.5.4-bin.tar.gz
파일 이동mv apache-maven-3.5.4 /local/apache-maven-3.5.4
vi ~/.bash_profile
마지막에 하단에 내용 입력export JAVA_HOME=/local/java/jdk1.8.0_171
export MAVEN_HOME=/local/maven/apache-maven-3.5.4
export CATALINA_HOME=/local/tomcat8.5
export CLASSPATH=.:$JAVA_HOME/jre/lib/ext:$JAVA_HOME/lib/tools.jar:$CATALINA_HOME/lib/jsp-api.jar:$CATALINA_HOME/lib/servlet-api.jar PATH=$PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin
export PATH=$PATH:$JAVA_HOME/bin:$MAVEN_HOME/bin
환경변수 적용source ~/.bash_profile
vi ~/.bash_profile
UTF-8인코딩 설정LANG="ko_KR.UTF-8"
LANGUAGE="ko_KR:ko:en_US:en"
설정정보 적용source ~/.bash_profile
env명령어로 확인
env
/local/tomcat8.5/bin/startup.sh
@Setter
@Getter
@ToString
public class UserJoinForm {
@NotNull
@Size(min = 2, max = 10)
private String name;
@NotNull
@Size(min = 2, max = 50)
private String email;
@NotNull
@Size(min = 2, max = 100)
private String address;
@NotNull
@Size(min = 11, max = 11)
private String phone;
@NotNull
@Size(min = 2, max = 15)
private String password;
@NotNull
@Size(min = 2, max = 15)
private String rePassword;
}
@PostMapping(path = "/join")
public String join(@Valid UserJoinForm userJoinForm, BindingResult bindingResult){
//에러발생
if(bindingResult.hasErrors()){
return "/login/join";
}
if(!userJoinForm.getPassword().equals(userJoinForm.getRePassword())){
FieldError fieldError = new FieldError("userJoinForm", "rePassword", "암호가 일치하지 않습니다");
bindingResult.addError(fieldError);
return "login/join";
}
User userByEmail = userService.getUserByEmail(userJoinForm.getEmail());
if(userByEmail != null){
FieldError fieldError = new FieldError("userJoinForm", "email", "이미 존재하는 email입니다.");
bindingResult.addError(fieldError);
return "login/join";
}
User user = new User();
BeanUtils.copyProperties(userJoinForm, user);
PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
user.setPassword(passwordEncoder.encode(user.getPassword()));
UserRole userRole = new UserRole();
userRole.setRoleName("USER");
user.addUserRole(userRole);
User saveUser = userService.addUser(user);
return;
}
<form class="form" id="formJoin" role="form" autocomplete="off" novalidate="" method="POST" th:object="${userJoinForm}" th:action="@{/users/join}" action="#">
<div class="form-group">
<label for="name">name</label>
<input type="text" class="form-control form-control-lg rounded-0" name="name" id="name" required="" th:field="*{name}">
<small class="text-danger" th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></small>
</div>
<div class="form-group">
<label for="email">email</label>
<input type="text" class="form-control form-control-lg rounded-0" name="email" id="email" required="" th:field="*{email}">
<small class="text-danger" th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></small>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control form-control-lg rounded-0" id="password" name="password" required="" th:field="*{password}" >
<small class="text-danger" th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></small>
</div>
<div class="form-group">
<label>Re Password</label>
<input type="password" class="form-control form-control-lg rounded-0" id="rePassword" required="" th:field="*{rePassword}" >
<small class="text-danger" th:if="${#fields.hasErrors('rePassword')}" th:errors="*{rePassword}"></small>
</div>
<div class="form-group">
<label>phone</label>
<input type="text" class="form-control form-control-lg rounded-0" id="phone" name="phone" required="" size="11" maxlength="11" th:field="*{phone}">
<small class="text-danger" th:if="${#fields.hasErrors('phone')}" th:errors="*{phone}"></small>
</div>
<div class="form-group">
<label>address</label>
<button type="button" class="btn btn-info btn-sm" id="addressSearch">search</button>
<input type="text" class="form-control form-control-lg rounded-0" id="address" name="address" required="" th:field="*{address}">
<small class="text-danger" th:if="${#fields.hasErrors('address')}" th:errors="*{address}"></small>
</div>
<div>
<label class="custom-control custom-checkbox">
<input type="checkbox" class="">
<span class="custom-control-indicator"></span>
<span class="custom-control-description small text-dark">Remember me on this computer</span>
</label>
</div>
<i class="fab fa-facebook"></i>
<div class="form-group row">
<div class="col-sm-10">
<a th:href="@{/sign-in/facebook}">facebook 가입 및 로그인</a>
</div>
</div>
<button type="submit" class="btn btn-success btn-lg float-right" id="join">Join</button>
</form>
spring:
profiles:
active: local
my:
address: 192.168.1.100 <----- 공통설정
---
spring:
profiles: local
my:
address: 127.0.0.1 <---- local
---
spring:
profiles: real
my:
address: 192.168.1.120 <---- real
@Controller
@RequestMapping("/boards")
public class BoardController {
@Value("${my.address}")
private String address;
}
java -jar 스프링부트애플리케이션.jar --spring.profiles.active=real
package examples.boot.simpleboard.service;
public interface MyService {
public String getName();
}
ckage examples.boot.simpleboard.service.impl;
import examples.boot.simpleboard.service.MyService;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
@Service
@Profile("real")
public class RealServiceImpl implements MyService {
@Override
public String getName() {
return "real";
}
}
package examples.boot.simpleboard.service.impl;
import examples.boot.simpleboard.service.MyService;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
@Service
@Profile("local")
public class MyServiceImpl implements MyService {
@Override
public String getName() {
return "local";
}
}
@Autowired
MyService myService;
public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
// https://stackoverflow.com/questions/28862483/spring-and-jackson-how-to-disable-fail-on-empty-beans-through-responsebody
// https://github.com/FasterXML/jackson-datatype-hibernate/issues/87
// https://stackoverflow.com/questions/33727017/configure-jackson-to-omit-lazy-loading-attributes-in-spring-boot
@Override
public void configureMessageConverters(List> converters) {
// http://jsonobject.tistory.com/235 iso8601 형식으로 날짜 정보 출력하기
ObjectMapper mapper = Jackson2ObjectMapperBuilder.json().featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS).modules(new JavaTimeModule()).build();
mapper.registerModule(new Hibernate5Module());
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
MappingJackson2HttpMessageConverter converter =
new MappingJackson2HttpMessageConverter(mapper);
converter.setPrettyPrint(true);
converters.add(converter);
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>