필기 정리-Spring

조형찬·2023년 2월 13일
0

필기 정리

목록 보기
10/11
  • 정적 컨텐츠

파일을 그대로 고객(웹브라우저)에게 전달
웹 브라우저에서 내장 톰켓 서버에 신호를 보내면
우선 스프링 컨테이너에서 있는지 찾아보고
없으면 resource에서 찾아보는데
있으면 웹브라우저로 반환한다.


  • mvc와 템플릿 엔진

서버에서 좀 바꿔서 전달해주는 방식
jsp php등이 템플릿 엔진이다
mvc : model, view, controller
view- 화면에 보이는 것만 관여
controller-비지니스 적인 측면 강조
웹브라우저에서 내장 톰켓 서버로 보내면 컨트롤러, 뷰를 거쳐서
타임 리프 템플릿 엔진처리를 하고
정적 컨텐츠와 달리 변환을 해서 반환을 해준다


  • api 방식

json이라는 data포맷으로 내려준다.
웹브라우저에서 내장톰켓 서버로 보내면
스프링 컨테이너에서 @ResponseBody가 있을 때 문자면 StringConverter
객체면 jsonConverter를 통해서 웹브라우저로 보낸다


  • 테스트 코드 예시

board insert에서 

assertEquals(result,1) // 하나 추가했을 때 제대로 들어갔는지 확인
BoardVO getDbVO = dao.getBoard(vo.getBoardNum()); 
assertNotNull(getDbVO);
assertEquals(vo.getBoardContent(), getDbVO.getBoardContent()); //각각의 입력한 항목들 모두체크 
assertEquals(getDbVO.getBoardRelev(),0); //기본적으로 쿼리문에서 입력되는 것들 체크(date는 제외)
assertEquals(dao.deleteBoard(vo.getBoardNum()),1);  // 넣은거 바로 지우고 제대로 지워지는지 확인

  • @ 어노테이션

@을 붙이면 해당 class가 어떤 역할을 하는지 알려주면서 빈으로 등록한다.
@Component
@Controller
@Service
@Repository

이종류의 @어노테이션이 붙어있으면 클래스를 스프링이 new로 만들어 둔거임
따로 객체를 생성할 필요없이 사용할 수 있다.

빈으로 등록한다 = 스프링이 객체를 생성해서 가지고 있다(cf. spring이 객체로 가지고 있는 클래스에는package Explorer에서 아이콘 모양에 S가 붙어있음)

빈으로 등록하는 3가지 방법
1. 어노테이션 붙여서 만드는거 수정하려면 소스코드를 수정해야 함, 수정이 최소화 되기는 함. 대부분 이걸 많이 쓰긴함.
2. bean태그를 사용해서 만들기. 약간 불편하긴 함. 큰 프로젝트일수록 이걸 쓰기도한다.
3. 자바로 직접 프로그램을 짜는방법이 있다.

@은 클래스, 필드, 메서드에 붙이는 것들이 있다.
각각에만 붙일 수 있는 @이 있기도 하고 중복해서 붙일 수 있는 종류도 있다.
주로 쓰는 @들
@RequestMapping
@Autowired
@Test
@Data 등..


  • model영역

model이 repasitory 영역이라고 생각하면 된다.
예) model.addAttribute("servertime",formattedData);


  • jsp templates 적용

아래 내용을 프리퍼런스- 웹 -jspfile- templates -new jspFile html5에 저장해줌

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>


  • servlet-context.xml 간단설정

servlet-context.xml - namespaces(문서 클릭하면 콘솔창 위에있음) 에서 aop 추가로 체크하기


  • spring 객체 가져오기 @Autowired

예)
1. Interface인 MemberInterface의 구현체 MemberRepository에서
@Repository를 사용하여 객체를 만들어두었다.
2. @Service를 사용한 MemberService 클래스에서
@Autowired를 사용하고 MemberInterface obj; 를 해주었다면
new MemberRepository();등을 안해도 스프링에 저장된 객체를 가져온다.
만약 바꾸고자 한다면 구현체 중에서 @Repository가 들어간 부분을 바꿔주면된다.
혹은 새로운 구현체를 만들고 @Repository를 넣고 기존의 @Repository는 주석으로 달아준다.


  • WEB-INF안의 문서 보기

WEB-INF안의 파일은 외부에서는 실행되지 않고 Controller를 통해서만 볼 수 있다.
예) http://localhost/WEB-INF/views/home.jsp이렇게 들어가려고 하면 404에러가 나온다.


  • @Test

테스트 할 때 무조건 public void로 만들어야 한다.


  • 템플릿 메소드 패턴

납품을 할 때 추상화해서 상속해준거로 보내준다.
납품받은 회사는 본인 db만 바꿔서 연결하면 상속받은 소스의 기능들을 사용할 수 있다. 납품해준 곳에서는 핵심 소스까지 알려주지 않아도 된다.

그런데 이렇게 하면 관련된 클래스만 사용 가능하다
따라서 클래스로 분리하는 방법도 사용해볼 수 있다.
단, 인터페이스로 만드는 것이 제일 좋다


  • IOC 제어의 역전

사용자 쪽에서 연결할 객체를 선택


UserDao.java

public class UserDao {
	private ConnectionMaker connectionMaker;
	public UserDao(ConnectionMaker connectionMaker) {
		this.connectionMaker =connectionMaker;
	}
설명 : UserDao 클래스에서 DB연결을 각 납품회사별로 바꿀 수 있도록 따로 뺀다.


ConnectionMaker.java (인터페이스)

public interface ConnectionMaker {
	Connection getConnection() throws ClassNotFoundException, SQLException; 
}
설명 : 인터페이스로 연결할 것을 만든다.
	
OConnectionMaker.java

public class OConnectionMaker implements ConnectionMaker {
	@Override
	public Connection getConnection()throws ClassNotFoundException, SQLException {
		Class.forName("oracle.jdbc.OracleDriver");
		return DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","chan","chan");
	}

}
설명 : 납품회사 중 O회사가 본인 회사에 맞는 DB연결 작성을 한다.

UserTest.java

	public class UserTest {

	@Test
	public void addTest() throws ClassNotFoundException, SQLException {
		//테스트할 데이터 2개 만들기
		User user1 = new User("cc", "Chan", "1234");
		User user2 = new User("dd", "dan", "12342");
		
		UserDao dao = new UserDao(new OConnectionMaker());
		dao.add(user1);
		dao.add(user2);		
	}
설명 : 테스트를 할 때 O회사의 객체를 만들고 만들어진 객체를 변수로 넣어서 테스트를 하도록 함 (DI : 디펜던시 인젝션)

  • cf) 자바프로젝트에서 스프링 설정 추가

메이븐 사이트에서 검색

버전 5.2.9 spring download
https://mvnrepository.com/artifact/org.springframework/spring-context/5.2.9.RELEASE

스프링 라이브러리
D드라이브 다운로드 스프링 라이브러리에 저장

Spring Core
https://mvnrepository.com/artifact/org.springframework/spring-core/5.2.9.RELEASE

  1. Spring Beans
    https://mvnrepository.com/artifact/org.springframework/spring-beans/5.2.9.RELEASE

Spring Expression Language (SpEL) » 5.2.9.RELEASE
https://mvnrepository.com/artifact/org.springframework/spring-expression/5.2.9.RELEASE

Spring AOP » 5.2.9.RELEASE
https://mvnrepository.com/artifact/org.springframework/spring-aop/5.2.9.RELEASE


  • xml파일 생성

뉴 - 스프링 빈 컨피규레이션 파일 : xml파일 생성


  • 프로젝트 생성 후 단계
  1. 라이브러리 추가
    롬복 ojdbc 스프링 등등

  2. 패키지 추가

  3. xml파일 생성

  4. vo클래스에 필드 생성하고 롬복 써서 (@Data
    @AllArgsConstructor
    @NoArgsConstructor) 설정해줌

5.daotest 클래스에 테스트 메서드 만들고 (퍼블릭 보이드) 테스트 어노테이션 추가

@Test
	public void userAdd() {
		ApplicationContext context = new GenericXmlApplicationContext("beans.xml");
		UserDao dao = context.getBean("userDao",UserDao.class);
	}

이렇게해서 UserDao 만드는건 dao패키지에 만들기

6.UserDao에서 이제 각각의 메서드를 만들어줌
맨위에 DataSource 임포트 하기

7.beans.xml 설정


  • HikariDatasource 사용한 xml설정 등

<bean class="dbuser.dao.UserDao" id="userDao">
		<property name="dataSource" ref="dataSource" />
	</bean>
	
	<bean class="com.zaxxer.hikari.HikariConfig" id="hikariConfig">
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
		<property name="jdbcUrl" value="jdbc:oracle:thin:@127.0.0.1:1521:xe" />
		<property name="password" value="chan" />
		<property name="username" value="chan" />
	</bean>
	<bean class="com.zaxxer.hikari.HikariDataSource" id="dataSource" destroy-method="close">
		<constructor-arg ref="hikariConfig"></constructor-arg>
	</bean>

  

위 beans.xml의 내용은 아래와 같다.
UserDao는 HikariDatasource에서 참조해서 매개변수로 가져옴. 매개변수를 통해 주입받아서 초기화를 해줌 생성자로 만들거나 setter매서드로 주거나 함.

  
  class UserDao{
	DataSource dataSource; 
    //HikariDataSource보다 상위데이터타입(인터페이스)이 DataSource라서 이를 필드의 타입으로 씀

 setDataSource(DataSource dataSource) { //property는 set으로 받음
	this.dataSource = dataSource	
}
	나머지 다양한 메서드들..

}

class HikariDataSource{
	HikariConfig conf;	
	public HikariDataSource(HikariConfig conf){ //constructor-arg는 생성자로
	this.conf=conf;
}
}

class HikariConfig{
	String driverClassName;
	String jdbcUrl;
	String password;
	String username;

	public setDriverClassName(String driverClassName){
		this.driverClassName =driverClassName;
	
}	...나머지 jdbcUrl, password, username도 위처럼.
}
  

  • Spring bean configuration 설정 순서

baen태그안에 class에 UserDAOImpl 경로넣기, id는 상위 인터페이스를 넣는 것이 좋다

bean태그 안에 class에 hikaridatasource 경로 넣기 이거는 hikariconfig가 필요하다. 그리고 이거는 spring 자체가 아니기 때문에 생성자를 넣어줘야 한다. 생성자는 constructor-arg로 하고 ref에 hikariconfig의 id 넣는다.

bean태그 안에 class에 hikariconfig 경로 넣고 id는 hikariconfig로 한다. 여기에 property로 db연결 정보를 넣어준다. 각각 name, value가 필요하며

<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:xe"></property>
<property name="username" value="chan"></property>
<property name="password" value="chan"></property>
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>

이렇게 들어간다. 여기까지가 xml설정 완료


  • Testclass 설정 순서

우선 필드에

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/userAppContext.xml"})
두가지 어노테이션을 넣고

@Autowired
ApplicationContext context;
여기까지 추가해준다.

그 후 추가적으로 
@Autowired
UserDAO dao;	
정도도 추가하고 context, dao가 제대로 생성되었는지부터 테스트 해본다.

UserDAOImpl구현체 클래스에서
@Autowired
DataSource dataSource;
이부분도 추가를 해주는 것까지가 기본 세팅에 해당한다.

UserDAOQuery라는 인터페이스를 만들고 쿼리문을 다 적어줌.
userDAO인터페이스에 각 쿼리문에 맞는 메서드들을 적어준다(반환타입, 매개변수적기) 그러면 구현체에서 구체화 하도록 한다.

select작업만 rs가 필요하고 나머지는
Connection c=null; PreparedStatement ps = null; 만 넣어도 된다.
이러한 내용들이 jdbc를 활용하는 방법 (mybatis사용시 이러한 과정이 간단해진다)


  • 전략 패턴의 적용

개방 패쇄 원칙(OCP)을 잘 지키는 구조이면서도 템플릿 메소드 패턴보다 유연하고 확장성 뛰어난 것이, 오브젝트를 아예 둘로 분리하고 클래스 레벨에서는 인터페이스를 통해서만 의존하도록 만드는 전략 패턴이다. 전략 패턴은 OCP관점에서 보면 확장에 해당하는 변하는 부분을 별도의 클래스로 만들어 추상화된 인터페이스를 통해 위임하는 방식이다.
Context의 contextMethod()에서 일정한 구조를 가지고 동작하다가 특정 확장 기능은 Strategy 인터페이스를 통해 외부의 독립된 전략 클래스에 위임하는 것이다.


  • 람다식을 이용한 DAO

	overloading을 하나의 메서드만으로 정리하여 간략화 하는 예제

	private int executeSql(String query) {
		return this.jdbcContext.workWithStatementStrategy( new StatementStrategy() {
			public PreparedStatement makeStatement(Connection c) throws SQLException {
				return c.prepareStatement(query);
			}
		});
	}
	
	private int executeSql(String query, UserVO vo) { //아래 람다식 사용
		return this.jdbcContext.workWithStatementStrategy(  ( c ) -> {
			PreparedStatement ps = null;
			ps = c.prepareStatement(query);
			ps.setString(1, vo.getId());
			ps.setString(2, vo.getName());
			ps.setString(3, vo.getPassword());
			return ps;
			}
		);
	}
	 
	private int executeSqlTotal(String query, String ... vo) { //아래 람다식 사용
		return this.jdbcContext.workWithStatementStrategy(  ( c ) -> {
			PreparedStatement ps = null;
			ps = c.prepareStatement(query);
			for(int i = 1; i <= vo.length; i++) {
				ps.setString(i, vo[i]);
			}
			return ps;
			}
		);
	}

  • jdbctemplate을 활용한 방법 순서
DAOImpl에서 해야할 설정

class안에
	private JdbcTemplate JdbcTemplate;
	
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		JdbcTemplate = jdbcTemplate;
	}

이렇게 먼저 선언한다.
이걸 하면 여기서 JdbcTemplate을 사용하겠다는 의미임.
따라서 xml파일에서 아래와 같이 적어줘야 함.

<bean class="com.chan.board.dao.BoardDAOImpl" id="boardDAO">
	<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>

<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate" >
	<constructor-arg ref="dataSource"></constructor-arg>
</bean>


<bean class="com.zaxxer.hikari.HikariDataSource" id="dataSource">
	<constructor-arg ref="hikariConfig"></constructor-arg>
</bean>

<bean class="com.zaxxer.hikari.HikariConfig" id="hikariConfig">
	<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:xe"></property>
	<property name="username" value="chan"></property>
	<property name="password" value="chan"></property>
	<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
</bean>


Test.java에서 해야할 설정

클래스 밖에서 아래와 같이 설정하고
@RunWith(SpringJUnit4ClassRunner.class) // db에 연결할거니까 이거랑 아래거 적어주기
@ContextConfiguration(locations = { "/boardbeans.xml" }) //xml파일 이름

클래스 안에서는 아래와 같이 보통 설정한다
@Autowired
ApplicationContext context; //이거까진 필수

@Autowired
BoardDAO dao;

BoardVO data1, data2, data3;

  • post방식

post방식의 처리는 가능하면 빨리 다른 페이지를 보도록 브라우저 화면을 이동시키는 것이 좋다 계속해서 데이터를 받기 때문이다.


  • Controller 관계

Controller가 Service에 일을 시키고
Service에서 DAO에 일을 시킨다.
각 layer간에는 interface로 연결한다.


  • mybatis 설정시

maven에서 아래 검색해서 maven복사 후 pom.xml에 추가하는 것이 필수다
mybatis, mybatis Spring


  • 경로 찾을 때

(contextpath가 있는 경우)
예) src/main/java 안에 있는 파일의 경로 찾을 때 classpath 사용
(contextpath가 없는 경우)
src폴더 부터 시작하는 경로 찾을 때 file: 사용


  • el태그

#{userId} =el을 사용한 것으로 el은 앞에 get이 들어가 있는것과 동일한 것이다.
즉 get userId와 같다고 볼 수 있다.


  • mybatis cf)

mybatis는 jdbc template 대신 sqlsession이 필요하다.


  • mybatis

mybatis 설정중 root-context할 때 namespace에서 context랑 mybatis를 추가해준다 ntext:component-scan base-package="com.chan.mbex02" />리고 이거를 추가한다 (""안에는 패키지 이름
이게 있어야 @등을 읽을 수 있다.)

root-context.xml에 <mybatis-spring:scan base-package="com.chan.mapper" />
이거를 추가해주면 인터페이스에 쿼리를 만들어도 알아서 클래스를 만들어서 bean에 등록시켜준다.


  • @RequestMapping ,메서드의 타입이 void일때

@Controller
public class HomeController {
@RequestMapping(value = "/home", method = RequestMethod.GET)
	public void homeNon(Locale locale, Model model) {
		logger.info("Welcome home! The client locale is {}.", locale);
		
		Date date = new Date();
		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,
        DateFormat.LONG, locale);
		
		String formattedDate = dateFormat.format(date);
		
		model.addAttribute("serverTime", formattedDate ); 
//메서드에서 void를 해주면 요청한 그대로 mapping을 시켜준다. WEB-INF/views//home.jsp	
	}}

value = "/home" 이거 대신 value = {"/home", "/chan"} 이렇게 쓰면
메서드를 여러개 만들지 않아도 WEB-INF/views//home.jsp, WEB-INF/views//chan.jsp 으로 이동하는 경우를 만들 수 있다.
value = /* 를 적어줄 경우 /뒤에 적어주는 위치대로 이동한다(해당파일이 있을 경우)
cf) sendredirect를 하기 위해서는 반환값 앞에 redirect가 있어야 하는데 void의 경우 반환이 없기 때문에 무조건 포워딩만 가능하다.


  • @RequestMapping return값이 있을 때
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
	logger.info("Welcome home! The client locale is {}.", locale);
		
	Date date = new Date();
	DateFormat dateFormat = DateFormat.getDateTimeInstanc(DateFormat.LONG, 
    DateFormat.LONG, locale);	
	String formattedDate = dateFormat.format(date);
	model.addAttribute("serverTime", formattedDate );				
    return "../index";
	}

return "../index"; 여기서 ..은 한단계 위로 올라가라는 의미다.
즉 상위 폴더에서 index.jsp파일을 찾으라는 의미다.


  • jackson-databind
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-databind</artifactId>
	<version>2.14.1</version>	
</dependency>

json문자열을 java object로 맵핑하여 변환할 수 있는 라이브러리이다.
이를 pom.xml에 넣어야 json을 사용하여 ajax를 통해 data를 주고 받는 것이 가능하다.

ajax를 사용하여 데이터를 주고 받을 때 서버에서는

@ResponseBody 어노테이션 사용하여 데이터를 주고 받는다.) 
@RequestMapping(value="/databind") //  경로: connex//databind
@ResponseBody   //데이터를 주고받을 때 사용해야 함
public MemberVO dataReq() {
	MemberVO vo = new MemberVO("aaa","paswwword","name","suwon",19);
	return vo;
	}
결과 :
{"id":"aaa","password":"paswwword","name":"name","address":"suwon","age":19}
//javascript - json의 형태

  • jquery를 이용하여 정보 가져오는 예시
<script>
var objItem = [ 'id', '아이디', 'password', '비밀번호', 'name', '이름', 
               'address', '주소', 'age', '나이' ];
var innerHTML = '';
for (let i = 0; i < objItem.length; i = i + 2) {
innerHTML = innerHTML + '<tr><th>' + objItem[i + 1]+ '</th><td id="'+ objItem[i] +'"></td></tr>'}
$('table').html(innerHTML)
$('button').click(function() {	
$.ajax({url : "http://localhost/conex/databind",
method : "GET"}).done(function(json) {
for (let i = 0; i < objItem.length; i = i + 2) {$('#' + objItem[i]).text(json[objItem[i]]);}

/*
$('#id').text(json.id);
$('#password').text(json.password);
$('#name').text(json.name);
$('#address').text(json.address);
$('#age').text(json.age);*/
	});
});
</script>

  • @GetMapping
@RequestMapping(value="six", method = RequestMethod.GET) 
//cf. @RequestMapping보다는 @GetMapping또는 @PosttMapping을 사용하는 것이 좋다.
@GetMapping(value="six")
public void six(@ModelAttribute("vo") MemberVO vo,
	@ModelAttribute("test") int test) {
}

  • @Controller, @RequestMapping

@Controller 어노테이션을 쓰면 해당클래스가 컨트롤러 역할을 수행한다는 것을 알림.
@RequestMapping 를 사용한 후 value에 이동할 url을 적어준다.
이때 void타입을 쓸 경우

)
@RequestMapping("three") 
/*servlet-context.xml에서 이미 /WEB-INF/jsp가 적혀 있기 때문에 /WEB-INF/three.jsp로 이동하는 것과 같다.
public void three(@RequestParam("data1") String[] data1) {}
data1이라는 data를 문자열 data1으로 받겠다는 의미와 같다.*/

value 뒤에  method=RequestMethod.GET or POST 등을 적으면 어떤 방식으로 이동할 지 나타낼 수 있다. 
get,post이외에도 여러 방식이 있긴하지만 보통 사용되지 않는다. 
특정 method를 적지 않으면 두가지 모두 사용 될 수 있다.
가능하다면 사용목적에 맞게 @GetMapping 또는 @PostMapping으로 나타내는 것이 좋다.

  • 파라미터 값이 MemberVO일 때

MemberVO클래스는 lombok을 통해 처리가 모두 된 상태이다.

@Data
@AllArgsConstructor
@NoArgsConstructor
@RequestMapping("four2")
public void four2(MemberVO vo) {
	}

이때 four2.jsp파일에서 ${memberVO}로 받을 경우 넘어온 data를 나타낼 수 있다.
cf. 파라미터에서 적은 MemberVO에서 앞글자가 소문자로 받으면 된다. (memberVO)


  • Model객체

Model 객체는 Controller 에서 생성된 데이터를 담아 View 로 전달할 때 사용하는 객체이다.
※ Servlet의 request.setAttribute() 와 비슷한 역할을 함
addAttribute("key", "value") 메서드를 이용해 view에 전달할 데이터를 key, value형식으로 전달할 수 있다.


  • ajax

Ajax는 JavaScript의 라이브러리 중 하나이며 Asynchronous Javascript And Xml(비동기식 자바스크립트와 xml)의 약자이다. 브라우저가 가지고 있는 XMLHttpRequest 객체를 이용해서 전체 페이지를 새로 고침하지 않고도 페이지의 일부만을 위한 데이터를 로드하는 기법이다. 즉 JavaScript를 사용한 비동기 통신, 클라이언트와 서버간에 XML 데이터를 주고받는 기술이라고 할 수 있다.
Json이나 xml 형태로 필요한 데이터만 받아 갱신할 수 있다.
cf. facebook등에서 스크롤하면 새로운 데이터가 생성되는 것 등


  • db연결 library c3p0

c3p0 library는 hikaricp처럼 db에 연결해주는 library이다.
이를 사용하려면 pom.xml에 hikaricp대신 dependency설정을 추가하면 된다.

예)
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.5</version>
</dependency>

  • db연결 설정중 참고사항
  1. name="driverClass" 는 value="oracle.jdbc.OracleDriver"로 적는것이 좋다.
    oracle.jdbc.driver.OracleDriver 대신 oracle.jdbc.OracleDriver 사용
  2. name="jdbcUrl" value="jdbc:oracle:thin:@127.0.0.1:1521:xe" 여기서 :뒤에 xe는 SID이름이고 xe(학습용)버전이 아닐경우 다른 내용이 들어간다.
    혹은 SERVICE NAME을 알 경우 /SERVICE NAME를 적어준다.
  3. 1521은 기본 포트 번호인데 보안을 위해서 다른 것으로 바꿔주는 것이 좋다.

  • AOP : 관점 지향 프로그래밍

관심사항을 분리(Aspect라는 독립된 모델로 분리)해서 개발한다.
Aspect: Advice와 Point cut을 합친 개념이다.
Advice:부가적인 기능을 정의한 코드이다.(해야 할 일 기능을 나타내는 것)
Point cut: 어디에 적용할지를 나태는 것이다.(예. A라는 클래스의 go라는 메서드)
Target: 부가기능을 부여할 대상이다.(각각의 클래스)
Join point:부가 기능이 적용될 수 있는 위치(끼어들 지점 예. 메서드를 실행할 때 등)
weaving: 실제 실행단계에서 삽입되는 과정
Spring AOP:프록시를 기반으로 AOP를 적용한다.(method에 대해서만 신경쓴다.)


  • Advice 종류

-before
-after,after returning, after throwing
(서로 다른 동작 시점을 갖는다)
(after : 성공, exception발생과 무관하게 동작하는 어드바이스)
(after returning : 성공적으로 리턴이 될 때 동작하는 어드바이스)
(after throwing : exception이 발생되었을 때 동작하는 어드바이스)

-around

성능을 평가하는 어드바이스 만들기
=> 유형 : around 어드바이스
=> 기능 : target 객체의 실행시간을 계산해서 출력하는 부가기능
=> 구현메서드 : trace(ProceedingJoinPoint jp)


  • aspectj 사용을 위한 설정 정보

aspectjrt,aspectj weaver maven설정 필요


<properties>
<java-version>1.11</java-version>
<org.springframework-version>5.2.9.RELEASE</org.springframework-version>
<org.aspectj-version>1.9.6</org.aspectj-version> <!--aspectj 버전 바꾸기-->
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
<!-- AspectJ -->
<dependency>
	<groupId>org.aspectj</groupId>
	<artifactId>aspectjrt</artifactId>
	<version>${org.aspectj-version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
	<groupId>org.aspectj</groupId>
	<artifactId>aspectjweaver</artifactId>
	<version>${org.aspectj-version}</version>
</dependency>

  • root-context.xml 설정참고

<context:component-scan base-package="com.chan.aopex" />
이 내용이 servlet-context.xml에 있으면 서버를 실행할 때 동작함

root-context.xml에 있으면 서버와는 무관하게 동작함
따라서 테스트를 사용하기 위해서는 여기에 있어야 하고 namesapce에서 context설정도 체크해야 한다.


  • 포인트컷 표현식 지정정보

execution(리턴타입 패키지정보 클래스명 메서드명과 매개변수)

  • 리턴타입 지정 정보=> *,void,!void

    -패키지 지정 정보 =>*.. 문자를 이용할 수 있다.
    예) com.chan.biz => 정확하게 com.chan.biz패키지만을 대상으로 한다.
    예) com.chan.biz.. => com.chan.biz패키지로 시작하는 모든 패키지를 대상으로 한다.
    예) com.chan.biz..impl =>com.chan.biz패키지로 시작하면서 마지막 패키지 이름이 impl로 끝나는 패키지를 대상으로 한다.
    예) com.chan.biz.* => com.chan.biz패키지로 시작을 하면서 하위 어떤 패키지라도 상관없이 대상이 된다.(단 이경우는 하위 패키지만 대상이다.)

-클래스 지정 정보=> *+문자를 이용할 수 있다.
예) MemberDAOImpl => MemberDAOImpl클래스만을 대상으로 한다.
예) Member => Member로 시작하는 모든 클래스를 대상으로 한다.
예)
Impl => Impl로 끝나는 모든 클래스를 대상으로 한다.
예) MemberService+ => MemberService를 상속받거나 구현하는 모든 클래스를 대상으로 한다.

-메서드 지정 정보 => *문자를 이용할 수 있다.
예) (매개변수) => 모든 메서드를 대상으로 한다.
예) get
(매개변수) =>get으로 시작하는 모든 메서드를 대상으로 한다.

-매개변수 지정 정보 =>*..문자를 이용할 수 있다.
예) (..) => 매개변수의 개수와 타입에 상관없는 메서드를 의미한다.
예) () => 반드시 1개의 매개변수를 갖는 메서드를 의미한다.
예) (MemberVO) => MemberVO를 매개변수로 갖는 메서드를 의미하나 사용이 불가능하다. 사용하려면 패키지 이름까지 전부다 지정해야 한다.
예) (!com.chan.vo.MemberVO) => com.chan.vo.MemberVO를 매개변수로 갖지 않는 메서드를 의미한다.
예) (Integer,..) => 1개 이상의 매개변수를 갖되 반드시 첫번째는 정수형인 메서드를 의미한다.
예) (Long,
) => 반드시 2개의 매개변수를 갖되 반드시 첫번째는 정수형인 메서드를 의미한다.


  • mybatis를 사용하여 게시판 만들기 하는 과정

-pom.xml설정
버전이 중요하다. 버전이 안맞아서 테스트를 해도no tests found matching 오류가 계속 나왔다..

나의 경우 다른 것이 원인이었지만
no tests found matching 이 오류의 원인으로 주로 나오는 것은 아래와 같다.
1. junit4버전이 아니라 junit5로 쓰인 경우(import 오류 등)
2. pom.xml에서 junit4.8로 되어있는 경우 (4.12버전으로 바꾸기)
3. junit의 <scope>test</scope> 이 부분을 지우거나 주석 처리 되어있지 않는 경우
4. intelij같은 경우 gradle설정 등의 오류가 있는듯하지만 나의 경우 eclipse를 사용해서 달랐다.
5. junittest를 run as할 때 runas configuration에서 기본이 junit4인지도 확인해야 한다.

나의 경우 이 모든 내용이 정상적이었으나 되지 않았다.

pom.xml설정에서
springframwork관련된 버전은 모두 ${org.springframework-version}로 통일 해주었다.
아직도 정확한 원인은 모르겠지만 springtx의 버전이 높았던것이 원인인 듯하다.

이후 가장 중요한 부분이 root-context.xml 설정이다.
일단 기본적으로 hikaricp를 사용해야 하니까 configdataSource를 설정한다. 그리고 mybatis를 쓰기 위해 sqlSessionFactoryBean을 설정한다. 그리고 여러곳을 찾다가 mapperLocation등을 추가하는 것도 있었는데 이걸 추가하니까 오류가 계속 생겼다.
따라서 설정은 여기까지하고 그다음으로
namespace에서 context,mybatis를 체크해서 설정해준다.

종합 root-context.xml설정 예)

	<context:component-scan
		base-package="com.chan.do1"></context:component-scan>
	<!-- Root Context: defines shared resources visible to all other web components -->
	<mybatis-spring:scan
		base-package="com.chan.do1.mapper" />	
	<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
		<property name="driverClassName"
			value="oracle.jdbc.OracleDriver" />
		<property name="jdbcUrl"
		value="jdbc:oracle:thin:@127.0.0.1:1521:xe" />
		<property name="username" value="chan" />
		<property name="password" value="chan" />
	</bean>

	<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource"
		destroy-method="close">
		<constructor-arg ref="hikariConfig" />
	</bean>

	<bean id="sqlSessionFactory"
		class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
	</bean>

</beans>

여기까지 필수 설정

이후
mapper.xml만 이용하거나
@만 이용하거나
xml,@를 같이 사용하는 방법(내가 찾은 방법)
dao로 사용하는 방법등이 있다.(수업에서 사용)

xml,@를 같이 사용하는 방법은
@으로 간단한 쿼리문은 빠르게 작성하고
복잡한 쿼리문은 xml에서 정의하는 방법을 이용한다.
이를 위해서 src/main/java안에 mapper인터페이스를 만들어서 @를 사용하여 기본 쿼리문을 작성한다.
또한 src/main/resources안에 mapper인터페이스와 똑같은 패키지 이름으로 mapper.xml을 만든다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  <mapper namespace="com.chan.do1.mapper.SimpleMapper">

그리고 위와 같이 설정을 먼저 해준다. namespace에는 mapper인터페이스 경로를 적어준다. (나의경우 SimpleMapper로 인터페이스 이름을 설정했다.)

이후 쿼리문을 추가하고 싶을 때

  1. SimpleMapper인터페이스에 추가한다.
예)
	@Select("SELECT sysdate FROM dual")
	public String gettime();

	public String gettime2();

여기서 gettime()같은 경우 이미 @를 사용해서 만든 것이다.
xml파일에는 gettime2를 구체화 하는 작업이 필요하다.

예)
  <select id="gettime2" resultType="string">
  	SELECT * FROM dual
  </select>

종류가 같아야 하며 예)select, insert 등
id가 메서드 이름과 같아야 한다.
resulttype,파라메터 타입등을 설정하고 쿼리문을 넣는다.

test를 해보고 싶을 때.
테스트 패키지에서 테스트 클래스를 하나 만들고

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "file:src/main/webapp/WEB-INF/
spring/root-context.xml")

제일먼저 두가지 설정을 해준다.
Runwithjunit4에서 가능한 설정인데 컨테이너를 만들어 준다는 것이다. 이를 쓰면 아래의 ContextConfiguration을 꼭 설정해야 한다. 이는 참고할 위치를 적어달라는 뜻이다. 설정정보가 담긴 root-context.xml로 가야 하기 때문에 의도적으로 바꾸지 않는 이상 저 경로를 쓴다고 생각하면 된다.
이후 ApplicationContext를 가져올 필요는 없다. (헷갈렸던 부분)
대신 SimpleMapper는 가져와야 한다.

	 @Autowired
	 SimpleMapper simpleMapper;

왜냐면 쿼리문 등이 여기 있으니까.
여기까지가 필수이자 기본 설정이다.


profile
서버개발 공부중

0개의 댓글