데이터 전송에는 여러 경우가 생기는데 이번에 했던거 또 하게되어서 기억겸 정리!!

1. form 양식에는 summit버튼만 누르면 name만으로 잘 controller에 전송이되는데 할꺼냐 말꺼냐 confirm할경우에 버튼의 속성을 summit아니고 단순 button으로 했더니 잘가던 네임값이 전송이 안되어서 추가했다. 

 

 

function  fn_detailUser(){
    if(confirm(name + "님의 정보를 삭제하시겠습니까? 취소불가합니다.")){
        let form = $("form");
        var action_mode = $("<input>").attr("type", "hidden").attr("name", "action_mode").val("delete");

        form.append(action_mode);
        form.submit();
    }
}

 

 

2. form결과를 후속처리를 해야한다....이럴경우.ajax을 써야하기때문에 양식변경한다.

if(confirm(name + "님의 정보를 수정하시겠습니까? ")){
    var queryString = $("form").serialize() ;
    queryString += "&name=yourName&action_mode=modify"
    $.ajax({
        url: '/admin/user/goUserAction.do',
        type: 'POST',
        data: queryString,
        dataType: 'json',
        success(result){
            console.log("result : ", result);
        },
        error(e){
            console.log(e);
            alert("에러 발생! 잠시후에 재시도 요망");
        }
    });
}

 

 

 

 

 

 

1. 혹시나 남아 있는 mysql의 흔적 지우기.

1-1 폴더 삭제. 제어판에서 mysql이라고 시작되는거 싹 지우기.

1-2.검색에서 win+R 단축키 > %appdata% 개인설정 폴더 나옴. 거기서 mysql폴더 삭제

1-3 port 번호 확인. 전에 설치했다 삭제 했다 반복 이력이 있었는데 port잡혀있었음

     cmd에서 netstat -ano | find "3306"선택하면 PID 가나오고

      cmd 에서 resmon.exe확인하면 리소스 모니터 나오고 여기서 mysql3306의  PID를 확인함

      cmd를 관리자 모드로 들어가서 taskkill /F /PID [PID 번호} 누르면 삭제됐다고 메세지...

    https://dana-study-log.tistory.com/entry/MySQL-MySQL-%EC%84%A4%EC%B9%98-3306-Port-%EC%98%A4%EB%A5%98

 

[MySQL] MySQL 설치 3306 Port 오류

오류 메시지 MySQL을 설치하는 중에 네트워크 설정시 port 설정에서 오류가 발생했다. 오류 메세지는 아래와 같았다. "the specified port already in use" 원인 MySQL은 기본 설정으로 127.0.0.1주소의 3306번의

dana-study-log.tistory.com

 

 

이과정을 하고 다시 설치 했던. 그렇게 안뜨떤 #developer default 모드가 뜬다....신기할세 

뭐가 자꾸 중간과정에 오류가 2번이상 나면 일단 모두 삭제 후 재설치 가 답이였음..ㅠㅠ

 

 

공부하면 별거 아니지만 은근히 안외워지고 그때그때 자꾸 검색해야해서 기록함..

예제입니다. 간단히...^^

#체크박스 선택시 해당 tr의 원하는 td값 가져오기

라디오 버튼 클릭시 칸2의 값을 가져옵니다...해당칸까지 포함해서 계산합니다.

// 버튼 클릭 이벤트 처리
$("#but").on("click", function() {
// 체크된 체크박스들의 3번째 칸 데이터 출력

$("input[name=poizon]:checked").each(function(index) {
var $row = $(this).closest("tr"); // 체크된 체크박스가 속한 행
var thirdCellText = $row.find("td:nth-child(3)").text(); // 3번째 칸의 텍스트 조회
var thirdCellText = $row.find("td").eq(2).text(); // 3번째 칸의 텍스트 조회
console.log("선택된 2번째 칸 데이터: " + thirdCellText);
});

var chose=$("input[name=poizon]:checked");
var tr_1 = chose.closest("tr");
var td_3 =tr_1.find("td:nth-child(3)").text();
console.log(td_3);
});

each를 통하면  tr의 td값을 순서대로 출력도 가능함.

$("input[name=poizon]:checked").each(function () {
var $row = $(this).closest("tr"); // 체크된 체크박스가 속한 행
var rowData = ""; // 행의 데이터를 저장할 변수

// 행의 각 셀 데이터를 조회하여 rowData에 추가합니다.
$row.find("td").each(function () {
rowData += $(this).text() + " | ";
});

// 마지막에는 "|" 구분자를 제거하고 데이터를 출력합니다.
console.log("선택된 행 데이터: " + rowData.slice(0, -3));
});

#라디오 버튼 선택시 해당 tr만 배경색 바꾸기....

$('input[name=poizon]').change(function() {
var chose=$("input[name=poizon]:checked");
// Get the parent row of the radio
var row = chose.closest('tr');
$('tr').css("background-color","");
row.css("background-color","gray");

});

css로 간단히 변경이 가능하다.

'JQUERY' 카테고리의 다른 글

게시판아코디언  (0) 2022.08.25

너무 길면 보기 싫기도 하고 나도 나중에 찾기 어렵고.....해서 좀 쪼갰습니다.

3. controller는 2가지로 볼수가 3가지로 볼수가 있습니다. 처음 화면 이동은 HomeContrller가 이건 뭐 비슷들 하니깐...pass

  그다음 채팅방 입장을 위해서와 여러가지 로직들을 처리하는 ChatContrller와  채팅의 websocket을 위한 controller 로 볼수 있습니다.

이 websocket은

@Component
@ServerEndpoint(value="/chatting", configurator = CustomSpringConfigurator.class)
public class WebSocketChatt {


    @Autowired
    public ChatRedisRepository repo;

    private static Set<Session> clients = Collections.synchronizedSet(new HashSet<Session>());

    public WebSocketChatt() {
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }

    @OnMessage
    public void onMessage(Session session, String message) throws Exception {
        // 메시지 처리 로직 작성
        System.out.println("receive WebSocketChatt message : " + message);

        // ChatDto 객체 생성
        ObjectMapper objectMapper = new ObjectMapper();
        ChatDto chatDto = objectMapper.readValue(message, ChatDto.class);


        // ChatDto 객체를 Redis에 저장
        try {
            repo.save(chatDto);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("에러  : " + e.getMessage());
        }

        for (Session s : clients) {
            System.out.println("send data : " + message);
            s.getBasicRemote().sendText(message);
        }
    }

    //클라이언트가 접속할때
    @OnOpen
    public void onOpen(Session session) {
        System.out.println("open session : " + session.toString());
        if(!clients.contains(session)) {
            clients.add(session);
            System.out.println("session open : " + session);
        }else {
            System.out.println("이미 연결된 session 임!!!");
        }

    }

    @OnClose  //클라이언트 종료시,,,브라우저 끄러나 다른 경로 갈때.
    public void onClose(Session session) {
        System.out.println("session close : " + session);
        repo.findChatList();
        clients.remove(session);
    }
}

여기서 저를 3일이나 괴롭혔던

@ServerEndpoint

@Autowired
public ChatRedisRepository repo;

나옵니다. ... AutoWired를 해결하면 serverEndopoint가 안되고 serverEndopoint가 되면 autoWired가 안되는 짜증나는 상황에서 chatGPT3는 저를 악의 구렁텅이로 밀어 넣었어요....그래서 더 3일이나 걸린듯합니다.ㅠㅠ

마지막에 그냥 구글 선배님 글 검색했습니다....선배님들 최고예요!!!!!!!

이걸 해결한것이 아까 2번의

@ServerEndpoint(value="/chatting", configurator = CustomSpringConfigurator.class)

입니다. 클래스는 2번 스토리에 있어요...^^  springboot, webSocket, Redis. chat --2. 설정 및 DTO :: 미치게힘든코딩 (tistory.com)at --2. 설정 및 DTO ::

 

springboot, webSocket, Redis. chat --2. 설정 및 DTO

1. 웹소켓을 통해 채팅 프로그램 만들기...1에서 왠만한건 다 복붙해서 이런건 감사... 2. 1:N 으로 적용해야합니다. 3. 저장은 DB로 해야하는데 이때 저는 REDIS를 알게 되었습니다. 그냥 활용해보기..

codingisnoteasy.tistory.com

추가는 DTO객체를 적용시킨것 밖에는 없어요....1번글의 선배님 글에서 ....

더보기
@Repository
public class ChatRedisRepository {
    private static final Logger logger = LoggerFactory.getLogger(ChatRedisRepository.class);
    private static final String HASH_KEY = "chatData";
    private RedisTemplate<String, ChatDto> RedisTemplate;
    private HashOperations<String, String, Map<String, String> > hashOperations;

    public ChatRedisRepository(RedisTemplate<String, ChatDto> RedisTemplate) {
        this.RedisTemplate = RedisTemplate;
        this.hashOperations = RedisTemplate.opsForHash();
        }

    public void save(ChatDto chatDto) {
        String key = chatDto.getId(); //자동생성된 id 값을 사용한다.
        Map<String, String> hashData = new HashMap<>();
        hashData.put("nickName", chatDto.getNickName());
        hashData.put("message", chatDto.getMessage());
        hashData.put("roomName", chatDto.getRoomName());
        hashData.put("date", chatDto.getDate());

        hashOperations.put(HASH_KEY, key, hashData);
    }
    public ChatDto findByNickName(String nickName) {
        Map<String, String> hashData = hashOperations.get(HASH_KEY, nickName);
        logger.info("******** findByNickName hashData : {}", hashData);
        if (!hashData.equals("null") || hashData != null) {
            ChatDto cDto = ChatDto.builder().roomName(nickName).build();
            return cDto;
        }
        return null;
    }
    //모든 대화 리스트 출력
    public void findChatList() {

        Map<String, Map<String, String> > allEntries = hashOperations.entries(HASH_KEY);
        logger.info("채팅 전체 데이터 : ");
        logger.info("{}",allEntries);
        logger.info("-----------------------");

        for (Map.Entry<String, Map<String, String>> entry : allEntries.entrySet()) {
            String key = entry.getKey();
            Map<String, String> data = entry.getValue();

            System.out.println("Key: " + key);

            ChatDto chat = new ChatDto();
            chat.setNickName(data.get("nickName"));
            System.out.print("nickName : "+ chat.getNickName());
            chat.setMessage(data.get("message"));
            System.out.print(", message : "+ chat.getMessage());
            chat.setRoomName(data.get("roomName"));
            System.out.print(", roomName : "+ chat.getRoomName());
            chat.setDate(data.get("date"));
            System.out.println(", date : "+ chat.getDate());

            System.out.println("---------------------");
        }
    }

전체 조회하면 이런식으로 나옵니다. 이걸 활용해서 이것저것 할수 있는거죠..^^

추가로 채팅정보에 관련된 controller는

 @Controller
public class ChatController {
    private static final Logger logger = LoggerFactory.getLogger(ChatController.class);
    private ChatRedisRepository repo;
    private RoomRedisRepository roomRepo;
    @Autowired
    public ChatController(ChatRedisRepository repo,RoomRedisRepository roomRepo ) {
        this.repo = repo;
        this.roomRepo = roomRepo;
    }
    @Autowired
    private RedisTemplate<String, CRoomDto> redisTemplate;
 	
    @RequestMapping("/chatting")
    public ModelAndView searchRoomNum(String roomName, String password, ModelAndView mv) throws JsonProcessingException {
        try{
            CRoomDto cRoo = roomRepo.findById(roomName);

            if (cRoo.getPassWord() == null ) {
                CRoomDto cRoom = CRoomDto.builder().roomName(roomName).passWord(password).build();
                roomRepo.save(cRoom);
                mv.addObject("roomName", roomName);
                mv.setViewName("chat/chatting");
                return mv;
            } else {
                mv.addObject("roomName", roomName);
                mv.setViewName("chat/chatting");
                logger.info("all list : {}",roomRepo.findRoomAll());
                return mv;
            }
        }catch (JsonProcessingException je){
            mv.addObject("message", je.getMessage());
            mv.setViewName("index");
            return mv;
        }
    }
    }

이런거였습니다.......

제가 국비학원 졸업시 프로젝트 부분이  ajax으로 하는 채팅프로그램였습니다. 그때는 부트를 배우기 전이라서 나중에 꼭 부트 공부하고 websocket으로 해보리라 다짐했는데 업무로 어거지로 한것이 아니라 제스스로 했다는 만족감과

제가 redis도 접해봤다는것에 너무 뿌듯함을 느끼는 저만의 글입니다.^^

 

1. 웹소켓을 통해 채팅 프로그램 만들기...1에서 왠만한건 다 복붙해서 이런건 감사...

2. 1:N 으로 적용해야합니다. 

3. 저장은 DB로 해야하는데 이때 저는 REDIS를 알게 되었습니다. 그냥 활용해보기...

key, value값인데 뭘 어떻게 조회해야하나...여러 고민을 하였습니다. 첫번째 블로그만해도 금방 sysout프린트 되서
아~~~!!!너무 좋구나야 했는데 이걸 채팅룸에 비번 넣고 저장하고 불러오고 CRUD redis와 이런걸 하려니 너무 어렵더라구요. 이제부터 검색과 chatGPT(무료버전이라 오류가 좀 많아요)와의 싸움입니다... 기간은 2주였고 실제 작업한 일은 7일 정도입니다.

websocket 채팅 프로그램 코드등에 대해 정리합니다.

디자인 패턴을 꼼꼼히 맞춰서 만들지는 않았고 일단 빠른 진행을 목적으로 만들었으니깐 참고해주세요. 

1. 웹소켓을 bean으로 설정하기 위해 파일도 만들었다 어쩌구 저쩌구 많은 고생을 했는데 결론은

@SpringBootApplication
public class Chat3Application {
    /*웹소켓을 사용하기위해 설정한 Bean*/
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

    public static void main(String[] args) {
        SpringApplication.run(Chat3Application.class, args);
    }
}

여기다 붙이는게 가장 좋았습니다. 이유는 @serverEndpoint  때문이였습니다. 
이놈 붙은건 @기본생성자를 만들어야만 했기에 controller같은 파일은 만들어서 진행하기가 어려웠어요...왜냐??
DB저장해야하잖아요....기본로직을 따라가려니 잘 안되더라구요....3일째 여러 고생하다가 안착한 곳이...

@SpringBootApplication

붙은 Application 클래스였습니다. 에러안나는 곳은 여기 뿐이였어요.

2. 

@Configuration
public class CustomSpringConfigurator extends ServerEndpointConfig.Configurator implements ApplicationContextAware {

    /**
     * Spring application context.
     * ServerEndpoint 는 웹소켓에 의해 세션이 연결될때마다 인스턴스가 JWA 구현에 의해 생성되고 관리되기에
	 * 생성될때마다 의존성 주입을 할수 있도록 별도 설정이 필요
     */
    private static volatile BeanFactory context;

    @Override
    public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
        return context.getBean(clazz);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        CustomSpringConfigurator.context = applicationContext;
    }
}

redis설정....application.properties에는 기재내용은 검색해봐도 많이 넣을 필요 없이 심플심플하게..

#redis설정 == application.properties 파일에
spring.redis.host=localhost
spring.redis.port=6379

//별도로 Config 파일로 설정해주는데 
//비번 설정을 안했기에 주석처리 했구요...
//tamplate메소드는 매핑처리하는데 필요, Serializer (JSON) 처리로 추가..
@EnableRedisRepositories
@Configuration
public class RedisConfig {
    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

   /* @Value("${spring.data.redis.password}")
    private int password;
*/
   @Bean
   public RedisConnectionFactory redisConnectionFactory() {
       return new LettuceConnectionFactory(host, port);
   }

    @Bean
    public RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        // Key Serializer
        redisTemplate.setKeySerializer(new StringRedisSerializer());

        // Value Serializer (JSON)
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));

        // Hash Key Serializer
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());

        // Hash Value Serializer (JSON)
        redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));

        return redisTemplate;

    }
        @Bean
    public ObjectMapper objectMapper() {
        return new ObjectMapper();
    }

3. dto ..저는 채팅룸과 실제 채팅내용을 분리해서 만들었습니다.

timetoLive는 만료시간을 설정하는 속성으로 30으로 적어서 30초 후에 만료 및 조회되면 안되는데 조회됩니다.

검색결과redis폴더에서 redis.conf파일을 들어가서 maxmemory-policyvolatile-lru 또는 volatile-ttl로 설정하라고 하는데....

https://blog.naver.com/PostView.naver?blogId=whddbsml&logNo=222389726721&parentCategoryNo=&categoryNo=&viewDate=&isShowPopularPosts=false&from=postView 글도 참고해보고

이렇게 조회는 되는데.....전 공부용이라서 일단 그냥 두었습니다..ㅠㅠ 사실 conf 파일까지 검색할때는 거의 끝나가는 부분이였어요. 정리를 나름 순서대로 하느라 그렇치 하면서 저는 마지막이라 이미 지쳤습니다.ㅠㅠ

그리고 왜 redis 할때 로그인 정보라던가 이런거 할때 많이 쓴다고 하더라구요. 그때 임의의 랜덤 key값이 사용되는데 그때 이건가봐요.

private String id= UUID.randomUUID().toString();

참고하세요.,

1. 프로젝트 만들어야 하잖아요...

https://jobtc.tistory.com/59 잘 만드셨더군요.......거의 복붙수준으로 했습니다...감사합니다. 선배님 꾸벅!!!

2. 저는 redis로 진행해보고 합니다.. 일단 설치...

https://learn.microsoft.com/en-us/windows/wsl/install 위에 글에도 있는데 혹시나해서...

했으나 이 후가 너무 어렵다.......영상 검색....https://www.youtube.com/watch?v=jvCC6huscOI 보세요.

Installing the Service  ------------ *--service-install*

Uninstalling the Service------------ *--service-uninstall*

Starting the Service---------------- *--service-start*

Stopping the Service---------------- *--service-stop*

Naming the Service------------------ *--service-name **name***

redis-server --service-install --service-name redisService1 --port 10001

redis-server --service-start --service-name redisService1

redis-server --service-install --service-name redisService2 --port 10002

redis-server --service-start --service-name redisService2

redis-server --service-install --service-name redisService3 --port 10003

redis-server --service-start --service-name redisService3

나가기 exit//
종료는 redis-cli.exe shutdown
종료후 재시작할때는 redis-server --service-install

http://redisgate.kr/redis/command/hashes.php

 

HASHES Introduction Redis

hashes_intro HASHES Introduction 소개 Field와 value로 구성 Hashes는 key 하나에 여러개의 field와 value로 구성됩니다. key 하나에 field와 value 쌍을 40억개(4,294,967,295)까지 저장 가능합니다. Table과 Hash의 유사한

redisgate.kr

redis와 관련된 대부분을 것을 조회 할수 있었습니다.

명령어들 일일이 검색하는것보다 훨씬 좋습니다.

1.불안함을 감추고 구글 cloud 가입해서 카드 등록 하고.(결제 맘대로 하지는 않는다고 하니깐...) 

2.적용할...프로젝트 하나만들고

3.사용자 설정하고.

4. 이클립스에  라이브러리 설치하고,

5. 환경변수 별도로 해줘야 한다.

5. gradle. build에 설정하고.

6. java class하나 만들어서 실행해보기...젠장. 2일(4시간씩)이나 걸렸다....... 말이 왜이케 어렵냐....지들은 한방에 이해할지 모르겠지만.. 난정말.아무리 내가 개발 초자라고 해도 글치 뭔말을 이렇게 어렵게 해놨는지..이미지 보여주는 것도 라이브러리 관련해서 밖에 없고. 자료 검색해도 별로 안나오고 구글 나뻐.!!!!!!!!!

일단 나중에 또 구글 api를 써야 하기때문에 정리 하는 것임으로 부족해도 참고하시길....

 

1. 회원가입하니깐 자동을 화면이 뜹니다...예시 이미지도 필요없어요....돈받아야 하니깐 알아서 화면 활성화....

구글 클라우드 플랫폼(Google Cloud Pltafrom) 계정 생성하는 방법 - LZ (lainyzine.com)  가입과정은 잘나옴.

구글 지오코딩 API 키 발급 받는 방법 (Geocoding API) - 코스모스팜 블로그 (cosmosfarm.com) 3번의 사용자 설정이 잘나옴.

 

2. .

https://cloud.google.com/translate/docs/apis?hl=ko

문서에 들어가서 가이드 내용을 참고하시는데 여기 말이 어려워요...

환경변수는 json파일로 받아서 설정해라...이거 이클립스 깔때많이 한거예요..사용자변수가서 하면되는데...

변수명 GOOGLE_APPLICATION_CREDENTIALS으로 넣어주고 파일주소 복붙해주고...

 

4.라이브 러리 에서 좀 해맸는데...그냥 나온데로 이클립스에서 마켓플레이스 가서 깔고 build설정해 줍니다...

그냥 build에 기재하고 import하면 안되어요 안되.....이거 받아야 해요.

implementation 'com.google.cloud:google-cloud-translate:2.16.0'

그이후에 실행했던...계속 에러...에러...나 사용자 계정 나 했는데 계속 에러...

에러 메세지io.grpc.StatusRuntimeException: PERMISSION_DENIED: Cloud IAM permission 'cloudtranslate.generalModels.predict' denied. 계속 발생

봤더니 가이드 문서에서 가져온 코드가  나하고 안맞는거였다..ㅠㅠ

import com.google.cloud.translate.Translate;
import com.google.cloud.translate.TranslateOptions;
import com.google.cloud.translate.Translation;

public class TranslateText {
  public static void main(String... args) throws Exception {
    // Instantiates a client
    Translate translate = TranslateOptions.getDefaultInstance().getService();

    // The text to translate
    String text = "Hello, world!";

    // Translates some text into Russian
    Translation translation =
        translate.translate(text, Translate.TranslateOption.targetLanguage("ru"));

    System.out.printf("Text: %s%n", text);
    System.out.printf("Translation: %s%n", translation.getTranslatedText());
  }
}

그랬더니..나왔다..ㅋㅋㅋㅋㅋㅋㅋ드뎌.사용.

막상 다 해놓으면 별거 없는데....하는데까지 오랜시간이 걸린다..ㅠㅠㅠ

MariaDB Products & Tools Downloads | MariaDB

 

MariaDB Downloads: Free open source database & tools | MariaDB

Download MariaDB products, tools and connectors. Get the latest versions of MariaDB Community Server, MaxScale, and free trials of SkySQL and Xpand.

mariadb.com

 업무상 필요해서 한번 설치 해봅니다~

버전은 10.9.6  이고 다운로드 후 인스톨까지 마친다음...cmd창에서 여부 확인입니다.

mysql.exe -u root -p 입력하고 엔터하면 비번....비번 입력후 엔터하면...쭈루룩 나옵니다.

CREATE DATABASE Investar;  Investar란 DB생성하고

SHOW DATABASES; Investar에 아무것도 없음을 확인.

use investar; investar db를 쓰겠다~~~~

 show tables; 테이블 보자~~~~

drop database investar; db삭제

select version(); 버전확인. 이렇게 하고.....이클립스에서 db연결하면됩니다.

 

build.gradle엔

//DB연결

implementation group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '10.9.6'

 

~application.java파일에는

spring.datasource.hikari.driver-class-name=org.mariadb.jdbc.Driver

spring.datasource.hikari.jdbc-url=jdbc:mariadb://localhost:3306/(DB이름)?characterEncoding=UTF-8&serverTimezone=UTC

spring.datasource.hikari.username=사용자이름을 넣으세요...

spring.datasource.hikari.password=비번넣으셔요.

이랬던.......web.xml이 생기면서 에러가 납니다.....그럼 

 

이클립스 스프링부트 혼자하기 2- 재설치...mysql과의 씨름 :: 미치게힘든코딩 (tistory.com)

 

이클립스 스프링부트 혼자하기 2- 재설치...mysql과의 씨름

사실 db설치부터 굉장히 고생했다.. 오라클.....회사서 설치하니 방화벽 머시기 땜시 2일을 죽도로 삭제 - 재설치 - 삭제 재설치.......무한반복했는데 선배님 왈 """설정부터 안되는건 안되는건여요

codingisnoteasy.tistory.com

마지막꺼 보세요......뻘짓도 다~~~역사가 됩니다.

 

////////////////////////////////////////////////////////////////////////////////////////////////

새벽 2시 22분입니다....

드디어 마리아 db연결해서 스프링 부트가 완성되었습니다....

1차 에러 났는데...

implementation group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '10.9.6' 빌드가 잘못되었어요......

마리아DB는 db와 연결하는 Connector/J 가 별도로 있습니다......여기서 버전은 이 Connector/J  입니다...2.7.9로 다시 기재하니깐 연결이 됩니다...그럼 자동 설치....많이 해맸습니다.ㅠㅠ

2차. spring.datasource.hikari.username=root로 넣었는데.....사용자 이름이였어요...전 따로 설정했는데 깜박했습니다...ㅠㅠ

3차. 연결되었나 했더니.....Entity클래스가 없다나 뭐래나.........부트 할때 jpa관련 라이브러리 설치했는데 그것 때문인가 싶어....dependency삭제했더니 됩니다...이건 눈치껏 금방 알았습니다... 

드뎌 부트가 실행되었습니다. 마리아 db  까지만 연결하고 오늘은 요만...ㅠㅠ

'SPRING' 카테고리의 다른 글

springboot, webSocket, Redis. chat --1 설치  (1) 2023.06.09
구글 translation api 사용해보기.  (1) 2023.05.20
LOG를 대체하는 logger  (0) 2022.11.10
JUNIT TEST 2-controller//  (0) 2022.11.10
LOG4j 등록  (0) 2022.10.11

로그인하면 정보를 보내야 하는데....나는 왜이렇게 뭉게 구름같을까????

내가한거 정리하는 차원에서....ㅠㅠ

1.

// controller
	@PostMapping(value="/member/login.do")
	public String getLogin(@RequestParam String email, @RequestParam String pw,
			HttpServletRequest request, Model model) {

		MemberDTO loginDto = mService.getMemberLogin(email, pw);
  		if(loginDto.getId() != 0) {  
            HttpSession session = request.getSession();
            session.setAttribute("id",loginDto.getId());
            session.setAttribute("nickName",loginDto.getNickName());
          	model.addAttribute("session",session);
            return "member/myInfo";
        }else { //회원정보안나오면 에러처리
            model.addAttribute("msg", "회원정보가 없습니다.");
            model.addAttribute("url", "/member/myInfoView.do");
            return "common/alert";
        }	
   }
  
  //jsp 화면
<% session=request.getSession();%>
//맨위에 한줄 넣고
<c:choose>
    <c:when test="${session.getAttribute('nickName') ne null }">
        <p>${session.getAttribute('nickName')}님
    </c:when>
    <c:when test="${session.getAttribute('nickName') eq null }">
        <c:out value="로그인 필요"/>
    </c:when>
</c:choose>
// 로그인정보를 쓰는 내용을 구상

근데 문제가 있다.......... 이 정보를 header페이지에 넣고 다른 페이지에 모두 include를 했는데.....처음 같 페이지 말고는 다시 읽어들이지를 않는것이다...

session은 다른 페이지는 고냥 얻어지는 것이 아닌것인가????

고민을 거듭....검색을 거듭하여...

https://ohju.tistory.com/869 이분 글을 참조하여 다시 코딩해보았다.

 

반영이 되는건 확인.....

홈화면으로 갈때도 로그인 정보가 콘솔로 나온다.....근데...이걸 jsp에서 나오는데 이걸 어떻게 이용해야하는것인가???

사실 많은 검색으로 장황하게 코드만 벌려 놓기도 했는데 ..

결론은 앞서 한것도 상관은 없는듯 하다......일단 너무 많이 벌려 놔서 저렇게 심플하게 다시 돌아가기에는 노력에 발목을 잡는다...버리기 아까움...ㅋㅋㅋㅋ 이런태도 안좋은줄 압니다...ㅋㅋㅋㅋㅋ

일단 정리.

1. 로그인 정보를 저장할 클래스를 만든다. 이걸 하면.  @SessionAttribute 불러 올때 편한다.

public interface SessionConst {
	/*
	 * Session을 다룰 때 글자만 참고-사용하기위해 상수를 인터페이스로 생성 직접 사용하지는 않는다.
	 */
	String LOGIN_MEMBER = "userDTO";
}

2. 간단한 환경 설정을 properties에다 준비.

# 세션 유지 시간을 설정한다. 초 단위로 적용된다.
server.servlet.session.timeout=1800

#URL 전달 방식을 끄고 항상 쿠키를 통해 세션을 유지한다.
server.servlet.session.tracking-modes=cookie

 쿠키로도 할수 있다는 데 오늘은 세션만 했다....세션이 좋다...나는 쿠키 생성은 내일이나 모레정도 예정

3. 메인화면들어갈때부터 session여부를 체크하여 진행한다.나는 index이라서....

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String welcome(
		@SessionAttribute(name=SessionConst.LOGIN_MEMBER, required=false) MemberDTO mDto
		, Model model){
		//Session 여부를 체크한다
		// @SessionAtrribute를 통해 위에서 Session에 값을 저장한 상수를 불러와 사용한다.
		if(mDto == null) {
			LOGGER.info("로그인 정보 없음 ");	
			return "index";
		} else {
			LOGGER.info("로그인 정보 : " + mDto);	
			model.addAttribute("MemberDTO" , mDto);
			LOGGER.info("보낼정보 : " + model);
		return "index";
		}
	}

 

4. 로그인하려 가볼까나.....

/* 로그인 */
	@PostMapping(value = "/member/login.do")
	public String getLogin(@RequestParam String email, @RequestParam String pw, HttpServletRequest request,
			Model model) {
		//내가 받은 정보
		LOGGER.info("[로그인 정보] pw ={}, email = {} ms", pw, email, (System.currentTimeMillis() - startTime));
	
		MemberDTO loginDto = mService.getMemberLogin(email, pw);
		//정보 db 가져와서 pw 맞는지 확인
		if (!(loginDto.getPw().equals(pw))) {
			model.addAttribute("msg", "비밀번호가 다릅니다.");
			model.addAttribute("url", "/member/loginView.do");
			return "common/alert";
		} else {
			//pw 맞으면 session 보관	
			if (loginDto.getId() != 0) {
				HttpSession session = request.getSession();
				//세션에다가 인터페이스 SessionConst 상수에 넣어서 불러오기 한다.
				session.setAttribute(SessionConst.LOGIN_MEMBER, loginDto);
				//일정시간동안 서버에 응답을 보내지 않으면 해당 세션을 소명시킨다.
				//session.setMaxInactiveInterval(1000); properties에다가 1800이라고 설정했다.
				session.getAttributeNames().asIterator().forEachRemaining(
						name -> LOGGER.info("session name = {}, value = {}", name, session.getAttribute(name)));

				LOGGER.info("sessionId = {}", session.getId());
				LOGGER.info("getMaxInactiveInterval = {}", session.getMaxInactiveInterval());
				LOGGER.info("creationTime = {}", new Date(session.getCreationTime()));
				LOGGER.info("lastAccessedTime = {}", new Date(session.getLastAccessedTime()));
				LOGGER.info("isNew = {}", session.isNew());
				model.addAttribute("MemberDTO",loginDto);
				return "member/myInfo";
			} else {
				model.addAttribute("msg", "회원정보가 없습니다.");
				model.addAttribute("url", "/member/myInfoView.do");
				return "common/alert";
			}
		}

	}

HttpSession session = request.getSession();

session.setAttribute(SessionConst.LOGIN_MEMBER, loginDto);

요렇게 하면 sesstion넣는것은 끝...

보낸주는것은 model 객체로 하는것.......controller에서 계속 해야한다.

  

5. session을 단독으로 구현해봤음.....다른거랑 같이하니깐 은근 여러가지 고려해야해서...

/* session관련  */
	@GetMapping(value = "/member/session")
	public String sessionStudy(
    		@SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) MemberDTO loginDto
            , HttpServletRequest request
            , HttpSession session
            , Model model) {

		/* HttpSession session = request.getSession(false); */

		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("MemberDTO", loginDto);
		LOGGER.info("@조정해봄 {} ", loginDto);
		LOGGER.info("@세션 정보만 {} ", session.getAttribute("nickName"));
		LOGGER.info("@request {} ", request.getSession());
		LOGGER.info("@SessionAttribute {} ", map);
		LOGGER.info("SessionConst.LOGIN_MEMBER",(MemberDTO)session.getAttribute(SessionConst.LOGIN_MEMBER));
		
		model.addAttribute("MemberDTO", loginDto);
		model.addAttribute("map", map);
		return "member/sessionStudy";
	}

@SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) MemberDTO loginDto

한줄이면 session정보 불러오는것 끝!!!!!

콘솔에서 나오는 내용 포함

 

6. JSP기재사항 정리....은근히 나오는데 별로 없었다...검색력 부족.......

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%@ page session ="true"%>
<%@ page import = "java.util.Date"%>
<%@ page import = "java.text.SimpleDateFormat"%>
<%
Date time = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
					<h3>세션에 설정된 모든 값을 읽어오기</h3>

        세션 ID: <%= session.getId()%><br>
        <% time.setTime(session.getCreationTime());  %>
        세션생성시간: <%=formatter.format(time) %><br>
        <% time.setTime(session.getLastAccessedTime()); %>
        최근접근시간: <%=formatter.format(time) %>
		
	다른방법....	<br>
<%-- 	//에러발상으로 일단 지움...Enumeration 확인요망	
<%
      application.setAttribute("age", 30); 
      Enumeration<String> attrNames = application.getAttributeNames();                
      while(attrNames.hasMoreElements()){
            String attrName = attrNames.nextElement();
            Object attrValue = application.getAttribute(attrName);
            System.out.println(attrName + " : " + attrValue);
      }
%> --%>
<!-- hasMoreElements() 메서드는 Enumeration 의 메서드로 
현재 커서가 가리키는 다음 위치에도 요소가 있으면 true를 반환합니다. 
nextElement()는 커서를 다음 요소를 가리키도록 변경하고 해당 위치의 요소를 반환합니다. 
얻어온 요소(여기서는 속성명) 을 가지고 getAttribute() 메서드를 통해 속성값을 가져옵니다. -->
		
		
		
		<!-- map으로 정보 확인 -->
		건너 받은 map 정보 : ${map }<br>
		건너 받은 nickName만 : <c:out value="${map.MemberDTO['nickName'] }"/><br>
		<c:forEach var="MemberDTO" items="${map.MamberDTO }">
			${MemberDTO.id }<br>
			${MemberDTO.nickName }<br>
			${MemberDTO.email}<br>
		</c:forEach>
		<!-- session으로 정보 확인 -->
		
		건너 받은 MemberDTO : ${MemberDTO }<br>
		건너 받은 nickName만  : ${MemberDTO.nickName }<br>

출력 결과

sesstion의 정보를 jsp파일에서 어떻게 활용해야할지 일단 그냥 전달하는 것과 map 같이 전달할것 포함해서 넣었다.

리스트 같은거랑 같이 보낼수도 있으니깐....

 

sesstion정보는 많은데 이걸 내가 소화 하는 건 너무나도 어렵다...ㅠㅠ

 

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds">
	<!-- moduleId는 프로젝트가 설치된 폴더명 또는 구분할 수 있는 식별자이면 됨 -->
	<property name="moduleId" value="boot_jeong"/>
	<!-- 로그파일명을 구성하는 인자 -->
	<property name="type" value="jeong"/>
	<!-- log를 저장할 최종 디렉토리명 -->
	<property name="logback" value="logback"/>
	<property name="logdir" value="C:\디렉토리명\logFiles"/>
	<!-- Appender  -->
	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    	<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
    		<level>DEBUG</level>
    	</filter>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>[%d{yy-MM-dd HH:mm:ss}] [%-5level] [%thread] [%logger{0}:%line] - %msg%n</pattern>
        </encoder>
    </appender>
    
    <!-- root레벨 설정 -->
    <root level="INFO">
    <appender-ref ref="console"></appender-ref>
    </root>
</configuration>

logback-spring.xml

package com.boot.jeong.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class FrontController {
	
	private final Logger LOGGER = LoggerFactory.getLogger(FrontController.class); 
	
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String welcome() {
		LOGGER.info("Info Log");
		return "index";
	}

}

Logging system failed to initialize using configuration from 'null'

java.lang.IllegalStateException: Logback configuration error detected:

ERROR in ch.qos.logback.core.joran.action.AppenderRefAction - Could not find an appender named [console]. Did you define it below instead of above in the configuration file?

ERROR in ch.qos.logback.core.joran.action.AppenderRefAction - See http://logback.qos.ch/codes.html#appender_order for more details.

 

구성파일에 console을 찾을 수 없다고???뭔소리지...검색~~~안나온다.

가만히 관심술을 부려본다.......화면을 뚜러지게 쳐다보자.....날보세요 하는 대문자 CONSOLE이 보인다.

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">

요기는 이래놓고 root쪽에는 소문자로 해놯다...둘다 대문자로 변경하니 정상작동ㅋㅋㅋㅋ

그리고 영상을 보다가 로그글씨의 색상을 넣을 수 있다는 언급이 있어서 추가로 검색했다.

처음엔 알록달록 이쁘게 하루만 나오고 이후로 색상은 나오지 않아서 많이 아쉬웠는데 다른 급한 문제가 시급해서....

일단 검색하니.

blue, cyan, faint, green, magenta, red, yellow 색상을 지원한다고 하고

<!-- log에 글씨 넣기 -->

<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>

 

넣은다음에

패턴에 넣으라는 것이다.

<pattern>[%magenta(%d{yy-MM-dd HH:mm:ss})] [%highlight(%-5level)] %cyan(%logger{30}:%line) - %msg%n</pattern>

오로콤 수정했다...

사실 기본으로 나온게 이쁜것 같은데 ...

%cyan을 %green으로 변경했다....

 

 

정리/////

스프링 부트에는 일단 logback기능이 자동으로  있다.....뭐 특별히 작성하지 않아도 기본 내용이 있기 때문에 보기 불편하지 않는다면 괜히 한것 같은 아쉬운 느낌.....스프링에서는 dependency해야하는데 boot니깐 안해도 되서 편함.

하지만 표시 내용을 보기 좋게 꾸미거나 축소하거나 뭐 암틈 다듬고 싶다면.....만드는 것으로 정리됨

나는 흑백으로 나오던걸 컬러표현을 한 것으로 만족!

 

그리고 에러라고 할것도 없다.......그냥 배겼다..ㅋㅋㅋ 이번엔 딴직안하고 하란데로만 했더니 잘된것임 ㅋㅋ

+ Recent posts