✿∘˚˳°∘°
74일차 : loC, DI, springMVC 본문
1. loC / DI
loC : Inversion of Control 제어의 역행
프로그램을 구동하는데 필요한 객체 생성에 대한 생성/변경등을 프로그램을 구동하는 컨테이너에서 직접관리
역할 - 객체의 생명주기와 의존성 관리
DI : 의존성 주입 / 컨테이너가 빈의 설정정보를 읽어와 자동으로 해당 객체를 연결
장점 - 개발자가 작성해야할 코드가 단순해짐
MemberService service = new MemberService();
@Autowired
MemberService service;
스프링에서 객체를 자동적으로 저장해주게 만듬(의존성 주입)
필요한건 한번씩만 파일로 만들어두고 서버시작때마다 사용하기때문에 개발자가 작성할 코드가 적어짐
B class를 수정할 때 A class에 연쇄적으로 수정해야하는게 많은 경우를 결합도가 강하다고 표현
(코드를 칠때는 결합도가 약할수록 좋다 - 수정사항이 적어지니까)
결합도를 낮출 때 스프링이 좋다.
WEB-INF 아래 web.xml 파일을 보면 서블릿의 생성유무에 따라 코드가 다르다
서블릿을 생성하면 서블릿에 대한 정보가 들어가는 것
spring mvc : 일반 mvc보다 구조는 복잡하지만 개발자가 작성하는 코드는 적다(나머지는 spring에서 제공하는기능을 사용)
모든 클라이언트의 요청을 Dispatcher Servlet으로 받음
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Hello Spring</h1>
<hr>
<h3>결합도와 응집도</h3>
<form action="/test1.do" method="get">
<input type="radio" name="brand" value="samsung" id="samsung">
<label for="samsung">SAMSUNG</label>
<input type="radio" name="brand" value="lg" id="lg">
<label for="lg">LG</label>
<input type="submit" value="제출">
</form>
<h3><a href="/test2.do">DI 테스트</a></h3>
</body>
</html>
- Controller
test1Servlet.java
package kr.or.iei.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import kr.or.iei.vo.BeanFactory;
import kr.or.iei.vo.LgTV;
import kr.or.iei.vo.TV;
/**
* Servlet implementation class Test1Servlet
* 이클립스에서 서블릿을 사용할 때는
* @WebServlet(name = "Abcd", urlPatterns = { "/abcd.do" })
* 라고 정의가 되어있지만 Spring에는 정의가 없는대신 web.xml에 서블릿정보가 기재되어있음.
* 서블릿을 잘못만들어서 삭제해야하는 경우 web.xml에서 해당 서블릿 관련정보도 지워줘야한다
*/
public class Test1Servlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public Test1Servlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
SamsungTV tv = new SamsungTV();
tv.powerOn();
tv.powerOff();
tv.volumUp();
tv.volumDown();
LgTV tv = new LgTV();
tv.on();
tv.off();
tv.soundUp();
tv.soundDown();
//거의 동일한 코드를 다시 작성해줘야하기 때문에 번거로움 - 이럴 때 사용하는게 인터페이스
*/
//SamsungTV tv = new SamsungTV();
//현재는 객체를 생성하는 코드만 변경해주면 된다 - 결합도를 낮추는 작업
//LgTV tv = new LgTV();
//부모객체를 사용해서 SamsungTV만 변경해주면된다.(다형성이용)
//LgTV()라는 객체도 사용하고 싶지 않을 때 -> 사용자가 선택한걸 가져오고 싶을 때
//TV tv = new LgTV();
String brand = request.getParameter("brand");
System.out.println(brand);
BeanFactory factory = new BeanFactory();
TV tv = factory.getBean(brand);
tv.powerOn();
tv.powerOff();
tv.volumeUp();
tv.volumeDown();
response.sendRedirect("/");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
test2Servlet.java
package kr.or.iei.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import kr.or.iei.vo.Member;
import kr.or.iei.vo.MemberMgr;
/**
* Servlet implementation class Test2Servlet
*/
public class Test2Servlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public Test2Servlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//spring 설정파일을 읽어오는 객체 생성
AbstractApplicationContext cntx = new GenericXmlApplicationContext("memberContext.xml");
//여러개의 bean중에 필요한 bean의 id를 가져옴 - 항상 Object로 리턴하기 때문에 형변환이 필요
Member member1 = (Member)cntx.getBean("member1");
System.out.println(member1.getName());
System.out.println(member1.getAge());
System.out.println(member1.getAddr());
MemberMgr mm = (MemberMgr)cntx.getBean("mm");
Member member3 = mm.getMember();
System.out.println(member3.getName());
System.out.println(member3.getAge());
System.out.println(member3.getAddr());
Member member2 = (Member)cntx.getBean("member2");
System.out.println(member2.getName());
System.out.println(member2.getAge()); //20
System.out.println(member2.getAddr());
member2.setAge(1000);
System.out.println(member2.getAge()); //1000
Member member22 = (Member)cntx.getBean("member2");
// 위코드 실행마다 새로운 객체가 생성된다 - 20
// 이미 만들어진 객체를 이용하는것이다 - 1000
// 옵션을 줄 수 있음(옵션이 없으면 아래가 기본값) scope="prototype"을 하면 계속 새로운 객체를 만듬
System.out.println(member22.getAge());
response.sendRedirect("/");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
- VO
TV ( Inteface)
package kr.or.iei.vo;
public interface TV {
public void powerOn();
public void powerOff();
public void volumeUp();
public void volumeDown();
}
- lombok이 해주는 일
package kr.or.iei.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
//lombok이 해주는 일 - getter/setter/생성자를 작성하지 않아도 다 만들어준다.
@Data // getter/setter
@NoArgsConstructor // 매개변수 없는 생성자
@AllArgsConstructor //모든 매개변수가 있는 생성자
//변수추가삭제의 경우 전부 수정해줘야하는데 lombok을 사용하면 모두 자동으로 생성된다.
//단, 매개변수가 일부만 있는 경우에는 직접 만들어줘야한다.
public class Member {
private String name;
private int age;
private String addr;
}
- test
package kr.or.test;
import org.springframework.stereotype.Component;
//Component : 서버가 시작될 때 객체를 만들지말지 결정
@Component
//component를 붙여도 s(스프링에서 클래스를만들었다는 뜻)가 생기지 않음
//WEB-INF/spring/appServlet/servlet-context.xml 에 해당 패키지 <context:component-scan base-package="패키지" /> 를 작성해주어야함.
//Component와 Scan이 항상 함께 이루어져야한다.
public class TestClass2 {
public TestClass2() {
super();
System.out.println("TestClass2 생성완료!");
}
}
2. SpringMVC (DB연결 X)
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Spring MVC</h1>
<hr>
<form action="/login.do" method="post">
아이디 : <input type="text" name="memberId"><br>
비밀번호 : <input type="password" name="memberPw"><br>
<input type="submit" value="로그인">
</form>
<hr>
<form action="/search.do" method="get">
조회 할 아이디 : <input type="text" name="memberId">
<input type="submit" value="조회">
</form>
</body>
</html>
- controller
DispatcherServlet
package kr.or.iei.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class DispatcherServlet
*/
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public DispatcherServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//(1) 최초요청받기
request.setCharacterEncoding("utf-8");
//사용자가 요청한 컨트롤러 주소 확인
String uri = request.getRequestURI();
System.out.println("사용자 요청 URI : "+uri);
HandlerMapping map = new HandlerMapping();
//(2)
Controller controller = map.getController(uri);
//(3), (5)
String result = controller.request(request);
ViewResolver resolver = new ViewResolver();
//(6)
String view = resolver.getView(result);
//(7)
response.sendRedirect(view);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
HandlerMapping
package kr.or.iei.controller;
import java.util.HashMap;
public class HandlerMapping {
private HashMap<String, Controller> mappings;
public HandlerMapping() {
super();
mappings = new HashMap<String, Controller>();
mappings.put("/login.do", new LoginController());
mappings.put("/search.do", new SearchMember());
}
public Controller getController(String uri) {
return mappings.get(uri);
}
}
LoginController
package kr.or.iei.controller;
import javax.servlet.http.HttpServletRequest;
public class LoginController implements Controller{
@Override
public String request(HttpServletRequest request) {
//2.값추출
String memberId = request.getParameter("memberId");
String memberPw = request.getParameter("memberPw");
//3. 비즈니스로직
//-> memberId : user01 이고, memberPw : 1234면 로그인 성공 아니면 실패
if(memberId.equals("user01") && memberPw.equals("1234")) {
return "loginSuccess";
}else {
return "loginFail";
}
}
}
SearchMember
package kr.or.iei.controller;
import javax.servlet.http.HttpServletRequest;
public class SearchMember implements Controller{
@Override
public String request(HttpServletRequest request) {
//2. 값추출
String memberId = request.getParameter("memberId");
//3. 비즈니스로직
//memberId가 user01이면 조회성공 아니면 실패
if(memberId.equals("user01")) {
return "searchSuccess";
}else {
return "searchFail";
}
}
}
ViewResolver
package kr.or.iei.controller;
public class ViewResolver {
public String getView(String result) {
return "/view/"+result+".jsp";
}
}
3. SpringMVC 2(DB연결 O)
[ 프로젝트 생성 시 해줘야하는 Setting]
0. Spring Lagacy Project 생성
1. 프로젝트우클릭 - propertice - project Facets - java version 1.8 / Runtimes - apach-tomcat 8.5 선택
2. 서버 add and remove 후 더블클릭해서 modules의 path 를 /로변경 -> 서버에 프로젝트 add시마다 해줘야한다.
3. pom.xml의 overview 설정변경
4. jstl 라이브러리추가(경로 : webapp/WEB-INF/lib)
[ 사전 Setting ]
- pom.xml (mavenrepository에서 검색 후 추가)
: Spring JDBC 사용을 위한 라이브러리 추가 [ Spring-jdbc / commons-dbcp ]
Spring jdbc / 첫번째 클릭 / 5.0.6ver
commons-dbcp / 두번째 클릭 / 최신ver
: Oracle 연동을 위한 ojdbc 추가
ojdbc6 검색 / 버전 1개 / 복사
: lombok 추가
lombok / 첫번째 클릭 / 1.18.12복사
<!-- Spring JDBC 사용을 위한 라이브러리 추가 2개(spring-jdbc, commons-dbcp) -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- ORACLE 연동을 위한 ojdbc -->
<!-- https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc6 -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.4</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
- web.xml
: 인코딩 추가
<!-- 인코딩 필터 설정 -->
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
: 마지막 url-pattern *.do로 변경
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
- WEB-INF/spring/appServlet/servlet-context.xml
: DB접속정보 + JDBCTemplet 추가
<!-- DB 접속정보를 저장하는 객체 생성 -->
<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<beans:property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<beans:property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:xe" />
<beans:property name="username" value="spring" />
<beans:property name="password" value="spring" />
</beans:bean>
<!-- JDBCTemplet -->
<beans:bean id="jdbcTemplet" class="org.springframework.jdbc.core.JdbcTemplate">
<beans:property name="dataSource" ref="dataSource"></beans:property>
</beans:bean>
: 하단에 패키지 추가(패키지가 추가될때마다 해야하는 작업)
<context:component-scan base-package="kr.or.iei" />
<context:component-scan base-package="kr.or.member" />
- Controller / Service / Dao 사전작업
@Controller
public class MemberController {
//선언만 해놓으면 안에는 null이 들어있지만 AutoWired를 사용하면 null(X)
@Autowired
private MemberService service;
public MemberController() {
super();
System.out.println("MemberController 생성");
}
}
@Service
public class MemberService {
@Autowired
private MemberDao dao;
public MemberService() {
super();
System.out.println("MemberService 생성");
}
}
@Repository
public class MemberDao {
@Autowired
private JdbcTemplate jdbc;
public MemberDao() {
super();
System.out.println("MemberDao 생성");
}
}
3 - 1 ) 아이디 조회하기
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Spring MVC CRUD</h1>
<hr>
<form action="/searchMember.do" method="get">
조회할 아이디 입력 : <input type="text" name="memberId">
<input type="submit" value="조회">
</form>
</body>
</html>
Controller
@RequestMapping(value="/searchMember.do")
public String searchMember(String memberId, Model model) {
//searchMember.do를 처리할 컨트롤러임을 알려줘야함 : 메소드 위에 기재
//이제 서블릿은 Spring이 만들기 때문에 메소드만 생성해줌
//값추출은 매개변수로 받음 - name값이랑 변수명이 동일해야한다.
//3. 비즈니스로직
Member member = service.selectOneMember(memberId);
//4. 결과처리
if(member == null) {
return "member/searchFail";
}else {
//request.setAttribute와 같은 역할을 해줌
model.addAttribute("member", member);
return "member/searchMember";
}
}
Service
public Member selectOneMember(String memberId) {
//트랜잭션 관리는 우선 자동으로
Member member = dao.selectOneMember(memberId);
return member;
}
Dao
public Member selectOneMember(String memberId) {
//1. preparedStatement 방식으로 query 작성
String query = "select * from member_tbl where member_id = ?";
//2. 위치홀더가 한개라도 있는 경우(만약, 위치홀더가 0개인 경우 2번과정 생략)
//위치홀더의 순서에 맞춰서 Object 배열에 추가
Object[] params = {memberId};
//3. 쿼리문 실행(select 인 경우 객체생성 - query()메소드 사용)
//query 매개변수 3개(쿼리문, 위치홀더에 들어갈 값 배열, 결과를 처리할 객체)
List list = jdbc.query(query, params, new MemberRowMapper());
//조회결과는 1개이건, 여러개건 무조건 List로 반환
if(list.isEmpty()) {
return null;
}else {
Member m = (Member)list.get(0);
return m;
}
}
'국비수업 > Spring' 카테고리의 다른 글
79일차 : Dynamic Mybatis (0) | 2023.03.21 |
---|---|
78일차 : Mybatis (0) | 2023.03.21 |
77일차 : SpringMVC - 게시판2 (0) | 2023.03.17 |
76일차 : 정규화, SpringMVC - 게시판 (0) | 2023.03.16 |
75일차 : SpringMVC - 회원, 공지사항 (0) | 2023.03.15 |