ModelAndView객체는 Model객체와 데이터를 넘길 페이지값을 가진 return을 합친 것입니다.
즉, 데이터와 넘길 페이지의 값을 모두 가지고 있는 객체입니다.

@Controller
public class TestModelAndView {
@RequestMapping("models/modelAndView")
    public ModelAndView testModelAndView(){
        ModelAndView mv = new ModelAndView();
        mv.addObject("name", "이름");
        mv.setViewName("/sample/modelAndView");
        return mv;
    }
}


혹은 생성자에서 ModelAndView("/sample/modelAndView") 해주어도 됩니다.

return mv하게되면 ViewResolver를 거쳐서 View를 보여주게됩니다.


ViewResolver는

Controller가 넘긴 View이름을 통해 알잡은 view를 찾는 역할을 합니다.

Controller는 ModelAndView객체에 응답할 view이름을 넣어 넘기면

DispatchServlet은 ViewResolver에게 응답한 view를 요청한다

ViewResolver는 View이름을 이용해 알맞은 viwe객체를 찾아서 DispatchResolver에게 전달한다.


viewResolver를 context에 선언해주어야한다. 


    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>


'Programming > Spring' 카테고리의 다른 글

Spring 진행과정  (0) 2018.02.14
root-context & servlet-context  (0) 2018.02.14
파일 업로드/ 다운로드  (0) 2018.02.09
MariaDB Auto_Increment  (0) 2018.02.08
DAO, DTO, VO  (0) 2018.02.08

큰뼈대만 기록해둡니다.


파일입출력의 핵심은 DB에는 파일이 저장된 경로와 저장되었을때의 파일명과 원본 파일명을 기록해 두는것이다.

그리고 출력시에 ViewResolver의 순서를 InternalResourceViewResolver가 먼저가 아닌 BeanNameViewResolver의 순서를 우위에 두게 해서 빈객체 @Component("FileDownloadView")가 View객체로 사용되게 하는 것이다.


pom.xml

<!-- MultipartHttpServletRequset -->

<dependency>

    <groupId>commons-io</groupId>

    <artifactId>commons-io</artifactId>

    <version>2.0.1</version>

</dependency>

 

<dependency>

    <groupId>commons-fileupload</groupId>

    <artifactId>commons-fileupload</artifactId>

    <version>1.2.2</version>

</dependency>



MultipartHttpServletRequert를 실행하기 위해서 commons-io와 commons-fileupload를 maven에 추가합니다.



root-context.xml

<!-- File io -->

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

       <property name="maxUploadSize" value="100000000" />

       <property name="maxInMemorySize" value="100000000" />

</bean>



그리고 root-context에는 최대upload사이즈와  최대 메모리 사이즈를 지정해줍니다.



upLoad

@Component("AppUtils")

public class AppUtils {


private static final String filePath = "C:\\path";

    

    public List<Map<String,Object>> parseInsertFileInfo(Map<String,Object> map, HttpServletRequest request) throws Exception{

   

    MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest)request;

        Iterator<String> iterator = multipartHttpServletRequest.getFileNames();

       

        MultipartFile multipartFile = null;

        String originalFileName = null;

        String originalFileExtension = null;

        String storedFileName = null;

         

        List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();

        Map<String, Object> listMap = null;

         

        String boardIdx = (String)map.get("IDX");

         

        File file = new File(filePath);

        

        if(file.exists() == false){

            file.mkdirs();

        }

         

        while(iterator.hasNext()){

           

        multipartFile = multipartHttpServletRequest.getFile(iterator.next());

            

        if(multipartFile.isEmpty() == false){

                

        originalFileName = multipartFile.getOriginalFilename();

                originalFileExtension = originalFileName.substring(originalFileName.lastIndexOf("."));

                 

                Date dt = new Date();

                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");

                

                storedFileName = originalFileName + String.format("(%s)", sdf.format(dt)) + originalFileExtension;

                

                file = new File(filePath + storedFileName);

                

                //File transfer

                multipartFile.transferTo(file);

                 

                listMap = new HashMap<String,Object>();

                

                listMap.put("BOARD_IDX", boardIdx);

                listMap.put("ORIGINAL_FILE_NAME", originalFileName);

                listMap.put("STORED_FILE_NAME", storedFileName);

                listMap.put("FILE_SIZE", multipartFile.getSize());

                

                list.add(listMap);

            }

        }

        return list;

   

    }

   }




downLoad

 @RequestMapping(value="/board_detail/download", method = RequestMethod.GET)
     public ModelAndView downloadFile(@RequestParam("path") String FileName) throws Exception{
             
             String path = "C://dev//file";
             String FileFullPath = path + "//" + FileName;        
             java.io.File file = new java.io.File(FileFullPath);
      
             return new ModelAndView("FileDownloadView", "downloadFile", file );
     }


@Component("FileDownloadView")
public class FileDownloadView extends AbstractView {
   
    public FileDownloadView() {
        // TODO Auto-generated constructor stub
    }
   
    @Override
    protected void renderMergedOutputModel(Map<String, Object> map, HttpServletRequest req,
                                                                                                 HttpServletResponse res) throws Exception {
        // TODO Auto-generated method stub
       

try {
            File file = (File)map.get("downloadFile");
           
            res.setContentType(getContentType());
            res.setContentLength((int) file.length());
            res.setHeader("Content-Disposition", "attachment; filename=\""
                                                             + java.net.URLEncoder.encode(file.getName(), "utf-8") + "\";");
            res.setHeader("Content-Transfer-Encoding", "binary");
           
            OutputStream out = res.getOutputStream();
            FileInputStream fis = null;
           
            fis = new FileInputStream(file);
            FileCopyUtils.copy(fis, out);
           
            fis.close();
            out.flush();
           
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
   
}



'Programming > Spring' 카테고리의 다른 글

root-context & servlet-context  (0) 2018.02.14
ModelAndView 와 ViewResolver  (0) 2018.02.14
MariaDB Auto_Increment  (0) 2018.02.08
DAO, DTO, VO  (0) 2018.02.08
@Autowired, @Resource, @Inject  (0) 2018.02.05


CREATE TABLE POST
(
    ID VARCHAR(30),
    NO_POST INT AUTO_INCREMENT,
    TITLE VARCHAR(100) NOT NULL,
    CONTENTS VARCHAR(4000) NOT NULL,
   
    PRIMARY KEY (CD_POST, ID)
);


AUTO_INCREMENT로 정의된 컬럼은 PK여야한다.
앞쪽에 나와야된다. 아니면 에러뜨더라...


Auto_increment 초기화 :

ALTER TABLE 테이블명 AUTO_INCREMENT = 1;

'Programming > Spring' 카테고리의 다른 글

ModelAndView 와 ViewResolver  (0) 2018.02.14
파일 업로드/ 다운로드  (0) 2018.02.09
DAO, DTO, VO  (0) 2018.02.08
@Autowired, @Resource, @Inject  (0) 2018.02.05
Filter, Interceptor, AOP  (0) 2018.02.05

DAO


웹서버는 DB와 연결하기 위해서 매번 커넥션 객체를 생성하는데, 이것을 해결하기 위해 나온것이 컨넥션 풀입니다. ConnectionPool 이란 connection 객체를 미리 만들어 놓고 그것을 가져다 쓰는것입니다. 또 다쓰고 난 후에는 반환해 놓는 것. 하지만 유저 한명이 접속해서 한번에 하나의 커넥션만 일으키지 않고 게시판 하나만 봐도 목록볼때 한번, 글읽을때마다 한번, 글쓸때 한번 등등… 엄청나게 많은 커넥션이 일어나기에, 커넥션풀은 커넥션을 또 만드는 오버헤드를 효율적으로 하기 위해 DB에 접속하는 객체를 전용으로 하나만 만들고, 모든 페이지에서 그 객체를 호출해다 사용한다면? 이렇게 커넥션을 하나만 가져오고 그 커넥션을 가져온 객체가 모든 DB와의 연결을 하는것이 바로 DAO 객체입니다

DAO(Data Access Object)는 DB를 사용해 데이터를 조화하거나 조작하는 기능을 전담하도록 만든 오브젝트를 말한다.

사용자는 자신이 필요한 Interface를 DAO에게 던지고 DAO는 이 인터페이스를 구현한 객체를 사용자에게 편리하게 사용 할 수 있도록 반환해줍니다.

DB에 대한 접근을 DAO가 담당하도록 하여 데이터베이스 엑세스를 DAO에서만 하게 되면 다수의 원격호출을 통한 오버헤드를 VO나 DTO를 통해 줄일 수 있고 다수의 DB 호출문제를 해결할 수 있습니다. 또한 단순히 읽기만 하는 연산이므로 트랜잭션 간의 오버헤드를 감소할 수 있습니다.


DTO(=VO)

DTO(Data Transfer Object)는 VO(Value Object)로 바꿔 말할 수 있는데 계층간 데이터 교환을 위한 자바 빈즈를 말합니다.

여기서 말하는 계층간의 Controller, View, Business Layer, Persistent Layer를 말하며 각 계층간 데이터 교환을 위한 객체를 DTO 또는 VO라고 부릅니다 그런데 VO는 DTO와 동일한 개념이지만 read only 속성을 가짐

일반적인 DTO는 로직을 갖고 있지 않는 순수한 데이터 객체이며 속성과 그 속성에 접근하기 위한 getter, setter 메소드만 가진 클래스를 말합니다




출처 : https://jungwoon.github.io/common%20sense/2017/11/16/DAO-VO-DTO/

'Programming > Spring' 카테고리의 다른 글

ModelAndView 와 ViewResolver  (0) 2018.02.14
파일 업로드/ 다운로드  (0) 2018.02.09
MariaDB Auto_Increment  (0) 2018.02.08
@Autowired, @Resource, @Inject  (0) 2018.02.05
Filter, Interceptor, AOP  (0) 2018.02.05

이번에 소개하는 세가지 어노테이션 @Autowired, @Resource,@Inject은 모두 의존관계를 자동으로 연결해주는 기능을 가진 어노테이션입니다. 다만 조금씩의 차이가 있습니다. 

 

 

 @Autowired

 @Inject

@Resource 

 범용

스프링 전용

자바에서 지원 

자바에서 지원

 연결방식

타입에 맞춰서 연결 

타입에 맞춰서 연결 

이름으로 연결

 

 자세한 설명을 하자면, @Inject와 @Resource는 JSR에 실려있는 자바 기존의 어노테이션입니다. 반면 @Autowired의 경우에는 스프링에서 등장한 어노테이션입니다. 따라서 스프링 이외에서는 사용 할 수 없습니다. 만약에 프로젝트를 스프링에서 다른 프레임워크로 바꿀 생각이 있으시다면 @Autowired보단 @Inject나 @Resource를 쓰시면 됩니다. 다만 이런 경우는 거의 없다고 봅니다.

 

또한 연결 방식은 @Autowired와 @Inject는 타입에 맞춰서 하는 반면, @Resource는 이름에 맞춰서 연결하게 됩니다. 예를 들어보겠습니다.

 

Bird 인터페이스를 상속하는 Chicken과 Penguin 이라는 클래스가 있다고 합시다. 

Chicken과 Penguin 클래스를 연결할 것이므로 @Component로 빈에 등록해주었습니다.

public class Bird{}

@Component

public class Chicken implements Bird{}

@Component

public class Penguin implements Bird{}

 

  

그리고 다음과 같이 연결해봅시다.

@Autowired

private Chicken penguin;  //Chicken 타입으로 연결됩니다.

 

@Inject

private Penguin chicken; //Penguin 타입으로 연결됩니다.

@Resource

private Chicken penguin;  //penguin 타입으로 연결됩니다만, Chicken 클래스를 자료형으로 두었기에 캐스팅이 되지 않아 에러가 납니다

 

@Resource

private Bird penguin;      //penguin 타입으로 연결되어 호출해보면 penguin 클래스의 값을 호출하는 것을 볼 수 있습니다.


@Autowired와 @Inject의 경우에도 @Qualifier 어노테이션을 사용하면, 타입 이외의 방법으로도 연결 할 수 있습니다.

(찾은 같은 타입의 빈객체 중에서 이름이(@Qualifier = Name) 같은 것으로 연결)

@Autowired

@Qualifier("chicken")

pirvate Brid penguin;

Bird타입의 빈객체중 chicken이라는 이름을 가진 빈 객체와 연결해서 맵핑




'Programming > Spring' 카테고리의 다른 글

ModelAndView 와 ViewResolver  (0) 2018.02.14
파일 업로드/ 다운로드  (0) 2018.02.09
MariaDB Auto_Increment  (0) 2018.02.08
DAO, DTO, VO  (0) 2018.02.08
Filter, Interceptor, AOP  (0) 2018.02.05

Filter,Interceptor,AOP 모두 요청 중간에 가로채서 사전처리,사후처리를 하는 의미는 비슷하다.

로깅처리 또한 셋다 가능.

차이점이라고 하면 ,


1. 셋의 시점이 다르다는것

: Filter > Interceptor > AOP


2. 적용하는 방식이 다름

: Filter : web.xml ,

  Interceptor : servlet-context.xml




###Filter


클라이언트 요청정보를 제공하는 객체를 정의 : ServletRequest 객체

서블릿 컨테이너는 ServletRequest 객체를 생성하고 이를 서블릿의 Service 메소드에 인수로 전달한다.

ServletRequest 객체는 매개 변수 이름과 값, 속성 및 입력 스트림을 포함하는 데이터를 제공한다.


-클라이언트 요청 정보를 제공하는 객체를 정의

-IP, hostname, 프로토콜 형식, 서버이름, 포트번호, ContentType 등을 가져올 수 있다.

-일반적인 네트워크 통신 기반에 의해서 사용되는 것들

-Servlet 의 web.xml에서 정의

-요청과 응답을 함께 다룰 수 있다.

-doFilter 메소드의 chain.doFilter(request,response) 를 기점으로 전/후 처리가능



###Interceptor





ServletRequest 인터페이스를 확장하여 HTTP 서블릿에 대한 요청 정보를 제공한다.

즉 , ServletRequest의 자식 Interface가 HttpServletRequest이다.

서블릿 컨테이너는 HttpServletRequest 객체를 생성하고 이를 서블릿의 서비스 메소드 (doGet, doPost등)에 인수로 전달


-public interface HttpServletRequest extends ServletRequest

-Http 프로토콜에 존재하는 정보들

-요청 파라미터, HTTP 헤더, 세션 및 쿠키 데이터, 요청에 사용된 URL 등을 가져올 수 있다.

-Spring에서 실행될 컨트롤러 빈 오브젝트, 컨트롤러가 돌려주는 ModelAndView, 발생한 예외 등을 제공받을수 있음.

-servlet-context.xml에 정의




### Filter : 
  - init() : 필터 초기화
  - doFilter() : 전, 후처리용 메소드, 내부에서 filterChain.doFilter를 호출하여 해당 비즈니스처리를 계속해서 수행할 수 있다.
  - destory() : 필터 종료이후 실행.



### Interceptor : 
  - preHandle() : 핸들러가 수행되기 전에 실행됨.
  - postHandle() : 핸들러가 수행되고 나서 실행됨.
  - afterCompletion() : View작업까지 완료되고 나서 실행됨.



### 파라미터의 차이
- Filter는 ServletRequest, ServletResponse등을 받게 된다.
- Interceptor은 HttpServletRequest, HttpServletResponse, 그리고 대상핸들러 등을 받아서 처리할 수 있다.

### ServletRequest와 HttpServletRequest의 차이.


SERVLETREQUESTHTTPSERVLETREQUEST
javax.servlet패키지에 포함됨. javax.servlet.http 패키지에 포함됨. 

ServletRequest의 하위 인터페이스임
getParameter()와 같은 많은 메소드를 제공 ServletRequest의 다양한 메소드를 상속받음.
getQueryString()등과 같은 추가 메소드를 제공함
HTTP프로토콜의 헤더, 바디, 컨텐츠타입, 쿠키, 세션등  다양한 정보를 쉽게 사용할 수 있도록함. 
GenericServlet과 함께 사용됨. HttpServlet과 함께 사용됨. 
프로토콜에 독립적으로 사용가능 프로토콜에 독립적이나, HTTP프로토콜 에 특화되어 사용 
HTTP가 사용되지 않았을때 클라이언트에서 요청이 들어오면 web container는 servletRequest 객체를 생성하고 service()메소드로 전달하는 방식으로 운용되었다. 클라이언트에서 요청이 HTTP프로토콜을 이용하여 들어온경우 Web container는 HttpServletRequest 객체를 생성하고 service()메소드에 전달하여 사용한다.


### AOP


AOP의 여러가지 기능들을 이용하여 메소드가 시행되기 전, 후 등에 처리

: 개념이나 사용법에 대해선 http://hayunstudy.tistory.com/49 참고


### 결론


세군데 전부 로깅이 가능하지만, AOP에 하는 것이 가장 적절하다고 판단.

Filter에 하면 모든 로깅이 다 체크되므로 비효율적이고 시스템에 부하가 걸릴수있다.

Interceptor에 로깅한다면 적당한 controller 및 ModelAndView 예외처리에 다 로깅 가능하다.

하지만 비지니스업무상 insert 또는 update 하는부분에만 로깅하고싶다거나 특정 에러처리 부분만 로깅할때 즉 세밀한 로깅처리불가

AOP 에서 로깅 처리를 하면 개발자가 원하는 시점에 로깅처리가 가능하기때문에 적절.


*Filter

-전체적인 Request단에서 어떤 처리가 필요할때

-인증, 이미지변환, 데이터압축, 암호화필터, 토크나이징 필터,

  XML 컨텐츠를 변형하는 XSLT 필터,

  URL 및 기타정보를 캐시하는 필터

-문자 인코딩


*Interceptor

-세션 및 쿠키 체크하는 http 프로토콜 단위로 처리해야 하는 업무가 있을 때

-로그인 세션 체크, 업로드파일처리


*AOP

-비즈니스 단에서 세밀하게 조정하고 싶을때

-로깅, 트랜잭션, 예외처리, 권한체크




구분 Filter Interceptor AOP
실행 위치 서블릿 서블릿 메서드
실행 순서 1 2 3
설정 위치 web.xml xml or java xml or java
실행 메서드 init(), doFilter(), destroy() preHandler(), postHanler(), afterCompletion() 포인트 컷으로 @After, @Before, @Around 위치를 지정




출처 :

http://blog.naver.com/PostView.nhn?blogId=fortunerain&logNo=220964510870&parentCategoryNo=&categoryNo=69&viewDate=&isShowPopularPosts=true&from=search


https://uncle-bae.blogspot.kr/2016/05/spring-interceptor-and-filter.html


'Programming > Spring' 카테고리의 다른 글

ModelAndView 와 ViewResolver  (0) 2018.02.14
파일 업로드/ 다운로드  (0) 2018.02.09
MariaDB Auto_Increment  (0) 2018.02.08
DAO, DTO, VO  (0) 2018.02.08
@Autowired, @Resource, @Inject  (0) 2018.02.05

out


out 키워드를 사용하면 변수를 전달하기전 초기화 하지 않고도 전달이 가능


using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;


namespace ConsoleApplication1

{

    class Program

    {

        static void Main(string[] args)

        {

            int a;


            Add(out a);

            Console.WriteLine("a={0}", a);

        }


        static void Add(out int a)

        {

            a = 100;

        }

    }

}


결과:

a=100


'Programming > C#' 카테고리의 다른 글

params  (0) 2017.08.06
foreach  (0) 2017.08.06
변수 출력  (0) 2017.08.06
c# 동적으로 textbox 생성하기  (0) 2017.08.05
winform 파일 쓰기  (0) 2017.08.05

params

길이에 제한받지 않고 수를 넘겨주어 그 수의 총 합을 구하고 싶을때 사용

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("sum={0}", total(20, 10, 40, 4, 7, 6, 44, 55, 2));
            Console.WriteLine("sum={0}", total(30, 4, 5));
        }

        static int total(params int[] list)
        {
            int sum = 0;

            for (int i = 0; i < list.Length; i++)
                sum += list[i];

            return sum;
        }
    }
}


'Programming > C#' 카테고리의 다른 글

out  (0) 2017.08.06
foreach  (0) 2017.08.06
변수 출력  (0) 2017.08.06
c# 동적으로 textbox 생성하기  (0) 2017.08.05
winform 파일 쓰기  (0) 2017.08.05

+ Recent posts