프레임워크와 라이브러리의 차이
프레임워크는 IoC(Inversion of Control)가 일어남 = 개발자가 정해진 규칙(사용 방식)을 따라감
라이브러리는 개발자가 사용하는 방식을 정해서 사용
org.green.패키지 이름
으로 적기 : 패키지 세번째 단어부터 ContextPath가 됨 ICmd cmdObj = cmds.get(cmd);
cmdObj.action(request);
String nextPage = cmd + ".jsp";
contextPath
)와 subfix(접미사=.jsp
)를 확인할 수 있다.<resources>
를 통해 resources 폴더에 대한 접근 제어 <!-- Handles HTTP GET requests for /resources/** -->
<!-- by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
resources : 정적 자원을 담은 폴더 (js, css 등)
** : 모든 하위 폴더
servlet-context.xml에 annotation 기반으로 움직일 것 정의
(bean 찾으라는 의미도 포함)
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
일 하는 로직을 담당하는 객체를 Cmd 객체라고 함 (자바 통용)
스프링에서는 이걸 Service 객체라고 부름
디자인 패턴 많이 들어감
퍼싸드 패턴 (복잡한 과정을 숨기고 겉면만 보여주는 패턴) 등
DAO 패턴
DB, repository, legacy에 접근하는 객체를 따로 두는 것
자바 Bean vs DTO
형태로는 같으나 의미하는 것이 조금 다름
Bean은 스펙 관점의 정의(이렇게 정의하라는 의미)
DTO는 쓰는 용도 관점에서 정의(이렇게 만들어서=이 형태로 사용하라는 의미)
(자바 Bean과 스프링 Bean은 다르다!)
@(annotation)
을 통해 연결되는 cmd(service)를 결정 * 어노테이션 의미 및 상속관계 정리
* (어노테이션은 interface로 만들어지며 상속관계를 가질 수 있다!)
* @Component : 빈으로 등록
* - @Controller : Component 의미 + 컨트롤러로 사용
* - @Service : Component 의미 + 커맨트 객체와 같은 역할
* - @Repository : Component 의미 + DAO 클래스 역할
* - @Configuration : + 구성 = 빈 여러개 등록시 활용 (중복빈 안만듦)
@Controller
public class HomeController {
@Autowired
private Some s;
...
}
@autowired
를 선언해주면, 스프링이 알아서 객체를 만들어준다.autowired
)해준다.아이콘 위 S 표시의 의미
- 스프링이 관리하는 객체라는 의미
WEB-INF/spring/root-context.xml
웹 어플리케이션 구성 요소들에게 보이는 공유 자원들을 정의하는 곳
Root Context: defines shared resources visible to all other web components
= Spring Bean으로 등록한다
xml 방식을 통해서만 같은 타입의 Bean 객체를 여러개 만들 수 있음!!
기본 생성자 이외의 생성자를 통해 Bean 만들기 (패러미터 순서 주의!)
<bean id="some1" class="org.green.first.Some" />
<bean id="some2" class="org.green.first.Some">
<constructor-arg value="custom" />
</bean>
<bean id="some3" class="org.green.first.Some">
<constructor-arg value="7" />
<constructor-arg value="custom" />
</bean>
// 같은 타입의 Bean 객체를 여러개 만드는 경우 = 보통 다른 생성자를 통해 객체를 만드는 것
// 일반적으로는 잘 안 씀
scope
singleton (default) : Bean 객체는 유일. 하나.
prototype : 매번 새로 생성
request : request마다 빈 생성
session : session마다 빈 생성
@Component
: 클래스 앞에 달아 Spring Bean으로 등록servlet-context.xml
의 <context:component-scan>
에서 처리@Component
public class Dummy implements ISome {
@Override
public String toString() {
return "dummy";
}
}
<context:component-scan base-package="패키지명">
서블릿 생성시에 base-package 내부의 클래스를 scan해서 annotation을 확인한 후 빈을 등록한다.
@Component
public class BeanMaker {
@Bean
public Some some1st() {
return new Some();
}
@Bean
public Some some2nd() {
return new Some();
}
@Bean
public SomeContainer someContainer() {
return new SomeContainer(some1st());
}
}
@Configuration
public class BeanMaker {
@Bean
public Some some1st() {
return new Some();
}
@Bean
public Some some2nd() {
return new Some();
}
@Bean
public SomeContainer someContainer() {
return new SomeContainer(some1st());
}
}
Maven - 프로젝트 형상관리 도구
- sts에 내장된 maven이 pom.xml의 dependencies에 작성된 라이브러리를 관리해준다.
C:\Users\사용자명\.m2\repository
에 저장.
pom.xml
- properties 값을 el 형태로 불러와서 사용 가능
@autowired
어노테이션 표시type 일치
, 객체명과 beanId 일치
, @Qualifier(String beanId)로 지정
bean id 정의
- xml에서 id="id명" 정의
- class명의 첫글자를 소문자로 전환하여 자동 정의
@Component(String beanId)
로 정의
어노테이션은 인터페이스로 만든다.
우리가 만들수도 있다. 근데 안 만든다.
@Controller
public class PhoneController {
@Autowired
private IPhoneDao dao;
@Autowired
private PhoneService service;
@RequestMapping(value={"/", "/list"})
// @RequestMapping("/") : root로 들어오면 여기로 연결
// @RequestMapping(value = {"/", "list"}, method = RequestMethod.GET) : 연결될 url과 method 결정
public ModelAndView list(ModelAndView mav) {
// 스프링이 알아서 넣어주는 패러미터들이 존재
// 메서드를 자유롭게 정의할 수 있다는 것의 장점!
// 속성을 속성이라 하지 못하고... Spring에서는 model이라 하게 됩니다...
// HttpServletRequest 대신 Model을 사용 가능
// 아니면 ModelAndView (= 속성에 붙여 넘길 정보(model)와 이동할 페이지 이름(view)을 가지는 객체)를 쓸 수 있음
// ModelAndView는 파라미터로 받아와도 되고(자동 생성해줌) 아니면 내가 만들어도 됨
mav.addObject("list", service.getAll());
mav.setViewName("list");
return mav;
}
@RequestMapping(value="/goInsertPhone", method=RequestMethod.GET)
public String goInsertPhone() {
return "insert";
}
// void로 return을 주지 않으면 들어온 주소로 다시 감
@RequestMapping(value="/insertPhone", method=RequestMethod.POST)
public String insertPhone(@ModelAttribute("yourPhone") Phone phone) {
/*
* request의 패러미터 받아오기
* 1. request 객체 요구해서, request.getParameter() 하기
* 2. @RequestParam(패러미터 이름) type 패러미터 받아올 변수명
* 패러미터명과 받아올 변수명이 같으면 어노테이션 생략 가능!!!
* 3. @RequestParam(value=패러미터 이름)
* @RequestParam 내부 속성
* - value=패러미터명
* - required=boolean값 (어노테이션 생략시 false, 있으면 true)
* required true인데 해당 parameter가 없으면 400Error
* - defaultValue=기본값
* 4. @ModelAttribute
* - 객체 생성
* - 이름이 맞는 파라미터를 찾아 멤버변수에 대입해줌
* - request 속성으로 삽입 (name=Class 첫글자 소문자)
*/
Connection con = dao.connect();
dao.insertPhone(con, phone);
dao.disconnect(con);
return "redirect:list";
// return String의 세 가지 형태
// 1. jsp 페이지
// 2. redirect + jsp페이지
// 3. responsebody -> jsp를 거쳐 html로 변환하지 않고, 텍스트로 바로 보내는 것 (비동기 통신에서 활용)
}
@RequestMapping("/view/{p_id}")
public String viewPhoneInfo(@PathVariable("p_id") int p_id, Model model) {
// 파라미터로 받아오는 대신 url에 변수(p_id 정보)를 담아 보냄
// url에 파라미터 정보를 받아옴 - restful 방식
// url의 p_id => @pv에서 지칭하여 받아 => int p_id에 담기
model.addAttribute("phone", service.getPhoneById(p_id));
return "list";
}
}
<!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId> <!-- 자바로 따지면 이게 패키지 -->
<artifactId>spring-jdbc</artifactId> <!-- 자바로 따지면 이게 클래스명 -->
<version>3.1.1.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
<bean id="jdbcTmp" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="ds" />
</bean>
// Dao 내부 메서드가 비슷하다 -> spring에서 servlet을 만들어주듯이, dao를 만들어주는 프레임워크가 있다.
// Dao를 편리하게 만들어주는 프레임워크 -> myBatis, springJdbc, 하이버네이트
// myBatis를 쓸 때 문제점 = 서로 다른 프레임워크를 사용하기 때문에 서로 버전 충돌 문제!
// springjdbc 버전은 스프링프레임워크 버전과 맞추면 된다.
// Configuration
// class가 아니라 메서드 return을 Bean으로 등록하는 방법
// 굳이 독립적 class로 분리할 필요 없을 때 사용 (ex. interface implements 하는 익명 이너클래스 등)
// ★ pom.xml에 cglib를 가져와야 함 (cglib 라이브러리에 의존성)
@Configuration
public class DaoHelper {
@Bean
public RowMapper<Phone> phoneMapper() {
return new RowMapper<Phone>() {
@Override
public Phone mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Phone(
rs.getInt("p_id"),
rs.getString("p_model"),
rs.getInt("p_price"),
rs.getDouble("p_weight"),
rs.getString("p_maker"),
rs.getString("p_color"),
rs.getString("p_year")
);
}
};
}
}
@Repository
public class SpringPhoneDao {
@Autowired
private JdbcTemplate jdbcTmp;
@Autowired
private RowMapper<Phone> phoneMapper;
public int insertPhone(Phone phone) {
String sql = "INSERT INTO phones (p_model, p_price, p_weight, p_maker, p_color, p_year) VALUES (?, ?, ?, ?, ?, ?)";
return jdbcTmp.update(sql, phone.getP_model(), phone.getP_price(), phone.getP_weight(), phone.getP_maker(), phone.getP_color(), phone.getP_year());
}
public List<Phone> getAll() {
String sql = "SELECT * FROM phones ORDER BY p_id DESC";
List<Phone> list = jdbcTmp.query(sql, phoneMapper);
return list;
}
public Phone getPhoneById(int p_id) {
String sql = "SELECT * FROM WHERE p_id = ?";
List<Phone> list = jdbcTmp.query(sql, phoneMapper, p_id);
return list.get(0);
}
public int updatePhone(Phone phone) {
String sql = "UPDATE phones SET p_model=?, p_price=?, p_weight=?, p_maker=?, p_color=?, p_year=? WHERE p_id=?";
return jdbcTmp.update(sql, phone.getP_model(), phone.getP_price(), phone.getP_weight(), phone.getP_maker(), phone.getP_color(), phone.getP_year(), phone.getP_id());
}
public int deletePhone(int p_id) {
String sql = "DELETE FROM phones WHERE p_id = ?";
return jdbcTmp.update(sql, p_id);
}
}
ResponseBody
: html 이외의 데이터(텍스트)를 응답으로 보낼 때 사용?