전체 글
- 89DAY / 프로젝트 시작, Github Commit 2017.08.09
- 88DAY / MySQL 랭크함수 2017.08.08
- 80DAY / 카페24 호스팅 & 81DAY(7/28) 2017.07.27
- 66DAY / Spring / model2 웹게시판 예제 2017.07.06
- 61DAY / jQuery 메서드 2017.06.30
- 53DAY / 안드로이드 앱 만들기 2017.06.20
- 50DAY / Android / 버튼 클릭 이벤트 처리, 터치이벤트 처리 2017.06.15
- 49DAY / Android Studio / 설치, 프로젝트생성, 아이콘바꾸기 2017.06.14
- 45DAY / JSP지시어 2017.06.08
89DAY / 프로젝트 시작, Github Commit
Spring 에서 깃허브 프로젝트 가져오기
Import - Git - Projects From Git - Clone URI 하고 깃허브의 주소와 아이디 비밀번호 입력한다
Github에 Commit할때
마우스 우클릭 - Team - Commit
저장소에 저장되지 않은 변경된 내역 중에 커밋할 내용을 드래그한 후
커밋메세지를 작성한 후 커밋한다.
커밋과 동시에 PUSH해서 깃허브에 올리고 싶다면 Commit and Push를 클릭한다
Push할때 브랜치를 생성할 수 있다.
88DAY / MySQL 랭크함수
Oracle과 달리 MySQL에서는 랭크함수가 없어서 구현해줘야한다.
같은 점수면 동점처리하고
원래는 1등 1명, 2등 2명이면, 다음 등수는 4등이 되어야하지만
우리 프로젝트에서 처리하기엔 더 불편할 것같아서 다음 등수는 3등이 되게하였다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | SELECT sns_board_no, CASE WHEN @prev = liker then @Rank WHEN @prev := liker then @Rank := @Rank +1 END AS rank, liker FROM ( SELECT sns_board_no ,count(sns_like_no) as liker FROM sns_like WHERE MONTH(sns_like_date) = (MONTH(NOW())-1) GROUP BY sns_board_no ORDER BY count(sns_like_no) DESC )sub1 CROSS JOIN (select @Rank := 0 ,@prev := NULL) sub2 ; | cs |
MySQL 사용자 변수 사용
1)SET을 사용하여 변수설정
1 | SET @exam = 1; | cs |
1 | SELECT @exam := 1; | cs |
80DAY / 카페24 호스팅 & 81DAY(7/28)
카페24 호스팅 신청
카페24에 회원가입한 후 서비스를 신청한다.
톰캣 JSP 광호스팅의 제일 저렴한 절약형으로 결정.
가입 후 처음으로 호스팅을 신청하여 신청하지 않은 아이디라고 뜨는데
2번째 이상 호스팅 신청시에는 새로운 아이디가 발급된다.
최초로 신청한 아이디인 부아이디에서 2번째 신청시 발급된 자아이디를 관리할 수 있다.
신청할 때 MySQL에서 사용할 비밀번호를 설정해준다.
서버환경 / 기간 / 도메인 선택하고 결제하면 신청완료.
기간이 길면 할인율이 높아진다.
신규도메인 등록하려면 돈 내야해서 무료도메인 쓰는데 카페24가입 아이디가 도메인된다.
신청할 때는 몰랐는데
닷홈의 무료호스팅 신청을 이용하면 무료로 도메인을 설정할 수 있다.
닷홈에서는 개인 당 3개의 계정을 무료호스팅 받을 수 있다
http://www.dothome.co.kr/web/free/index.php
닷홈으로 도메인을 신청하였으면 보유도메인에 체크하여 주소를 입력해준다.
그 후 닷홈으로 가서 네임서버에 카페24등록한다.
다음에 기회가 되면 해봐야겠다.
추가)닷홈 무료도메인은 지원하는 버전이 너무낮아서 활용도가 낮다한다.
66DAY / Spring / model2 웹게시판 예제
Spring 개발단계 - 준비
(1)Spring Tool 설치
Spring Community http://spring.io/
>TOOLS 들어가서 다운로드
(2)톰캣 서버 가져오기
-기존 서버아닌 톰캣 9.0사용하였다.
(3) legacy project생성
-MVC프로젝트선택
(4)JRE System Library 버전 변경
[ Java build path ]에서 JRE System Library 을 수정한다.
(5)web.xml파일 수정과 root-context.xml파일삭제를 한다.
-servlet 3.0 으로 변경
1 2 3 4 5 6 7 8 | <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> </web-app> | cs |
-해당부분삭제
]
: 부팅이 두개 되기때문에
(6)
pom.xml 파일에서 springframework 버전을 최신버전(4.3.9.RELEASE)으로 다운로드 한다.
mysql도 추가한다.
1 2 3 4 5 6 7 | <!-- mysql --> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.39</version> </dependency> | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure --> <!-- Enables the Spring MVC @Controller programming model --> <mvc:annotation-driven /> <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory --> <mvc:resources mapping="/resources/**" location="/resources/" /> <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean> <context:component-scan base-package="com.jjdev.mvc" /> </beans> | cs |
(8)마우스 우클릭 - [ run as ] - [ run on server] 실행확인
(9)Board , BoardDao 클래스 생성
(10)boardAdd.jsp 생성
(11)BoardController 클래스 생성후 BoardAdd()메소드 추가
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package com.jjdev.mvc; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class BoardController { @Autowired BoardDao boardDao; @RequestMapping(value="/boardAdd", method=RequestMethod.GET) public String boardAdd(){ return "boardAdd"; } @RequestMapping(value="/boardAdd", method=RequestMethod.POST) public String boardAdd(Board board){ boardDao.insertBoard(board); return "redirect:/"; } } | cs |
(13)글작성 후 mysql에 데이터저장되었는지 확인.
61DAY / jQuery 메서드
선택기 메서드
children : 선택된 대상의 1단계 자식검색
find : 선택된 대상의 자식 전체 검색
parent : 선택된 대상의 1단계 부모검색
parents : 선택된 대상의 html최상위까지 검색(매개변수로 인하여 브레이크 가능) 최상위:html
first : 선택된 대상의 첫번째를 선택
last : 선택된 대상의 마지막을 선택
eq : 선택된 대상의 해당 index를 선택
index : 선택된 대상의 index값을 구한다. ex) $('선택자').index($(this));
html제어메서드
wrap : 선택된 대상에 부모를 생성한다
append : 선택된 대상의 자식요소 마지막에 html을 생성한다.
prepend : 선택된 대상의 자식요소 첫번째에 html을 생성한다.
html : 선택된 대상의 내부의 html을 생성한다.
next : 선택된 대상의 다음순서에 html을 삽입한다.
prev : 선택된 대상의 이전순서에 html을 삽입한다.
비교메서드
prop : 선택대상의 속성의 상태를 비교하여 boolean으로 리턴해준다. 혹은 실행
ex) 상태정보 - var isCheck = $('선택자').prop('checked');
상태실행 : $('선택자').prop('checked', true or false);
$('선택자').prop('readonly', true);-- true일때 readonly
is : 선택대상의 속성 및 존재여부를 확인하여 boolean으로 리턴해준다.
ex) 상태정보 : var isCheck =$('선택자').prop(':checked');
상태정보 : var isCheck = $('선택자').prop('클래스 혹은 아이디');
$('article').parent().find('h1:eq(0)').remove();
article의 부모의 1단계아래자식중 h1의 첫번째
var btn1 =$('<button></button>');
btn1.attr('type','button');
btn1.addClass('add');
btn1.text('추가');
var btn2 =$('<button></button>');
btn2.attr('type','button');
btn2.addClass('del');
btn2.text('삭제');
$(document).on('click','.add',function(){
var clone = $(this).parents('article').clone();
clone.find('h1').text('냠냠');
$('article').parent().prepend(clone);
});----만든객체도 추가됨
$('.add').click(function(){
var clone =$(this).parents('article').clone();
clone.find('h1').text('한국스마트정보교육원');
$('article').parent().prepend(clone);
}); ===얜 안됨
$(document).on('click','.indexCheck',function(){
var parentObj = $(this).parents('article');
var ptext = parentObj.find('p').text();
alert(ptext);
});
53DAY / 안드로이드 앱 만들기
공공api를 이용한 미세먼지 확인 앱 만들기
(1)공공api를 얻기위해 권한을 신청한다. 저번에 신청한 api를 사용하겠다
(2)새 프로젝트를 생성한다. 버전은 android4.4(kikat)으로 생성하였다
(3)AndroidManifest.xml파일에 permission을 추가한다
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
(4)Air라는 자바파일안에
DataTime, 시도명을 Setter and Getter , To String 해준다.
(5)AirService.java 생성
package com.example.airapp.airapp;
import android.util.Log;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
public class Airservice {
public static Air getAir() {
//새로운 객체를 불러온다.
Air air = new Air();
String str = getAirList();
try {
//XML파싱
//(1)factory 생성한다.
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
//(2)factory에서 pullparser를 생성한다.
XmlPullParser parse = factory.newPullParser();
//(3)parser에서 사용할 데이터를 입력한다. StringReader타입으로 데이터를 전달해줘야 하기 때문에 getAirList라는 메서드를 생성하였다.
parse.setInput(new StringReader(str));
//(4)현재 팟의 이벤트 타입을 받는다.
int type = parse.getEventType();
boolean flag = false; //값이 참일때만 수행하기위해 생성
String local = "";
//(5)LOOP구문 : parser의 마지막 </tag>가 될때까지
while(type != XmlPullParser.END_DOCUMENT){
//(6)<tag>text</tag>이므로 startTag뒤에있는 Text를 찾기위한 switch절이다.
switch(type){
case XmlPullParser.START_TAG: //(6)-1.start Tag가 다음 중 하나일 때 flag값이 true가 된다.
local = parse.getName();
if(local.equals("dataTime")
||local.equals("seoul")
|| local.equals("busan")
|| local.equals("daegu")
|| local.equals("incheon")
|| local.equals("gwangju")
|| local.equals("daejeon")
|| local.equals("ulsan")
|| local.equals("gyeonggi")
|| local.equals("gangwon")
|| local.equals("chungbuk")
|| local.equals("chungnam")
|| local.equals("jeonbuk")
|| local.equals("jeonnam")
|| local.equals("gyeongbuk")
|| local.equals("gyeongnam")
|| local.equals("jeju")
|| local.equals("sejong")){
flag = true;
}
break;
case XmlPullParser.TEXT: //(6)-2.위의 case조건에 맞았다면 flag값은 true이므로 if문이 실행된다.
if(flag) {
if(local.equals("dataTime")) { //(6)-3.조건에 맞는 TEXT값을 int형으로 바꾸어 세팅한다. flag값은 false가된다
air.setDataTime(parse.getText());
}else if(local.equals("seoul")) {
air.setSeoul(Integer.parseInt(parse.getText()));
} else if(local.equals("busan")){
air.setBusan(Integer.parseInt(parse.getText()));
} else if(local.equals("daegu")){
air.setDaegu(Integer.parseInt(parse.getText()));
} else if(local.equals("incheon")){
air.setIncheon(Integer.parseInt(parse.getText()));
} else if(local.equals("gwangju")){
air.setGwangju(Integer.parseInt(parse.getText()));
} else if(local.equals("daejeon")){
air.setDaejeon(Integer.parseInt(parse.getText()));
} else if(local.equals("ulsan")){
air.setUlsan(Integer.parseInt(parse.getText()));
} else if(local.equals("gyeonggi")){
air.setGyeonggi(Integer.parseInt(parse.getText()));
} else if(local.equals("gangwon")){
air.setGangwon(Integer.parseInt(parse.getText()));
} else if(local.equals("chungbuk")){
air.setChungbuk(Integer.parseInt(parse.getText()));
} else if(local.equals("chungnam")){
air.setChungnam(Integer.parseInt(parse.getText()));
} else if(local.equals("jeonbuk")){
air.setJeonbuk(Integer.parseInt(parse.getText()));
} else if(local.equals("jeonnam")){
air.setJeonnam(Integer.parseInt(parse.getText()));
} else if(local.equals("gyeongbuk")){
air.setGyeongbuk(Integer.parseInt(parse.getText()));
} else if(local.equals("gyeongnam")){
air.setGyeongnam(Integer.parseInt(parse.getText()));
} else if(local.equals("jeju")){
air.setJeju(Integer.parseInt(parse.getText()));
} else if(local.equals("sejong")){
air.setSejong(Integer.parseInt(parse.getText()));
}
flag = false;
}
break;
default:
break;
}
//(7)parser의 진행을 다음(태그,속성,글자...)로 이동한다.
type = parse.next();
}
} catch (Exception e) {
e.printStackTrace();
}
return air;
}
private static String getAirList() {
HttpURLConnection conn = null;
BufferedReader rd = null;
StringBuilder sb = null;
try {
Log.v("air","try...");
StringBuilder urlBuilder = new StringBuilder("http://openapi.airkorea.or.kr/openapi/services/rest/ArpltnInforInqireSvc/getCtprvnMesureLIst"); /*URL*/
urlBuilder.append("?" + URLEncoder.encode("ServiceKey", "UTF-8") + "=서비스키"); /*Service Key*/
urlBuilder.append("&" + URLEncoder.encode("itemCode", "UTF-8") + "=" + URLEncoder.encode("PM10", "UTF-8")); //미세먼지 정보만 불러옴
urlBuilder.append("&" + URLEncoder.encode("dataGubun", "UTF-8") + "=" + URLEncoder.encode("HOUR", "UTF-8")); //시간별 데이터
urlBuilder.append("&" + URLEncoder.encode("pageNo", "UTF-8") + "=" + URLEncoder.encode("1", "UTF-8")); //데이터페이지중 1번페이지
urlBuilder.append("&" + URLEncoder.encode("numOfRows", "UTF-8") + "=" + URLEncoder.encode("1", "UTF-8")); //최신데이터 1개를 가지고온다.
URL url = new URL(urlBuilder.toString());
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Content-type", "application/json");
Log.v("air","Response code: " + conn.getResponseCode());
if (conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
Log.v("air","if...");
rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} else {
rd = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
}
sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
//예외처리
} catch (IOException e) {
Log.v("air","catch...");
e.printStackTrace();
} finally {
Log.v("air","finally...");
try {
rd.close();
} catch (IOException e) {
e.printStackTrace();
}
conn.disconnect();
}
return sb.toString();
}
}
(6)MainActivity
public class MainActivity extends AppCompatActivity {
TextView dataTime;
ProgressBar seoulbar;
ProgressBar busanbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dataTime = (TextView)findViewById(R.id.dataTime);
seoulbar = (ProgressBar)findViewById(R.id.seoulbar);
busanbar = (ProgressBar)findViewById(R.id.busanbar);
new MyThread().execute();
}
class MyThread extends AsyncTask{
@Override
protected Object doInBackground(Object[] params){
Air air = Airservice.getAir();
Log.d("air",air.toString());
return air;
}
//주체 : mainThread
@Override
protected void onPostExecute(Object o){
Log.d("air","onPostExecute:"+o.toString());
Air air = (Air)o;
dataTime.setText(air.getDataTime());
seoulbar.setProgress(air.getSeoul());
busanbar.setProgress(air.getBusan());
}
}
}
(7)activity_main.xml
50DAY / Android / 버튼 클릭 이벤트 처리, 터치이벤트 처리
버튼 클릭 이벤트 처리
1) 액티비티에서 View타입을 매개변수로받는 메서드 생성 후
레이아웃에서 메서드 호출설정
레이아웃
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.firstapp.firstapp.MainActivity">
<Button
android:id="@+id/hellobtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click"android:onClick="testOnClick"/>
</android.support.constraint.ConstraintLayout>
액티비티
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(layout.activity_main);
}
public void testonClick(View view) {
Toast.makeText(MainActivity.this, "EventTest Click", Toast.LENGTH_SHORT).show();
}
}
}
2)이벤트리스너를 사용
공통레이아웃
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.firstapp.firstapp.MainActivity">
<Button
android:id="@+id/hellobtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click"
</android.support.constraint.ConstraintLayout>
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(layout.activity_main);
Button button = (Button)findViewById(id.hellobtn);
button.setOnClickListener(new MyListener());
}
class MyListener implements View.OnClickListener {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "EventTest Click", Toast.LENGTH_SHORT).show();
}
}
}
3)익명클래스를 사용
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(layout.activity_main);
Button button = (Button)findViewById(id.hellobtn);
button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "EventTest Click", Toast.LENGTH_LONG).show();
}
});
}
}
4)액티비티 스스로 이벤트리스너 구현
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(layout.activity_main);
Button button = (Button)findViewById(id.hellobtn);
button.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Toast.makeText(this, "EventTest Click", Toast.LENGTH_LONG).show();
}
}
터치 이벤트 처리
안드로이드는 문자열을 다룰때 자바의 String타입이 아닌 CharSequence라는 자체 문자열 타입을 사용한다.
그래서 안드로이에서 생성된 문자열에 자바API를 사용할려면 먼저 toString()메서드를 이용하여 CharSequence타입을 String타입으로 변경해야 한다.
49DAY / Android Studio / 설치, 프로젝트생성, 아이콘바꾸기
안드로이드 프레임워크
C기반 개발툴
안드로이드 스튜디오 Android Studio 시작하기
안드로이드 스튜디오 다운로드
https://developer.android.com/studio/index.html
API7.0
1) 환경변수 설정하기
안드로이드 스튜디오를 사용하기 전에 Java JDK 환경변수를 설정해준다.
[제어판] - [시스템] - [시스템보호] - [고급]탭에 환경변수를 클릭한 후
아래 시스템변수 새로만들기에
변수 이름 : JAVA_HOME
변수값 : JDK설치된 경로
를 입력해준다
(2)새 프로젝트만들기
안드로이드 스튜디오 설치가 끝나면 실행하여 새로운 프로젝트를 생성한다.
프로젝트 명과 도메인 명 저장될 경로를 지정한다.
기본적으로 생성되는 액티비티와 레이아웃
(2)가상머신 설정하기
프로젝트에서 API 7 버전인 Nougat를 사용할 것이기 때문에 다운로드해준다.
디바이스 추가 완료!
휴대폰에 연결하기
(1)기종에 맞는 USB 드라이브 소프트웨어 설치후
(2)[ Tools ] - [ Android ] - [ Android Device Mointor ]
##안드로이드 스튜디오 디바이스 연결이 되지 않을 때
https://freeandroidroot.com/download-and-install-universal-adb-driver/
ADB드라이버를 설치 후 다시 시도한다.
아이콘 바꾸기
(3) AndroidMainfest.xml 파일에서 다음과 같이 수정한다.
android:icon="@mipmap/png파일명"
파일명은 영소문자만 가능하다
45DAY / JSP지시어
JSP지시어 (Directive)
<%@ page langauge = "java" %>
JSP파일 내에서 사용 될 스크립트 언어 지정
<%@ page extends = "클래스명" %>
상속할 부모 클래스 지정
<%@ page import = "패키지명.클래스명" %>
Java의 import와 같은기능
<%@ page session = "true" %>
JSP내에서 세션사용
*세션(Session) : HTTP의 Stateless특성으로 인해 커넥션을 매번 새로 생성해야하기 때문에 동일한 클라이언트에 대해 정보를 유지할 필요가 있는 경우, 정보유지가 가능하도록 만드는 가상의 커넥션
<%@ page buffer = "8kb" %>
JSP페이지가 서블릿으로 변환되어 응답을 생성해 클라이언트에 전송할 때 사용되는 버퍼의 크기 지정
none으로 설정 할 경우 버퍼를 사용하지 않는다
<%@ page autoFlush = "true" %>
buffer속성에서 지정한 버퍼가 다 채워졌을경우
true : 클라이언트에게 전송 후 버퍼비운다
false : Exception발생시킨다
<%@ page isThreadSafe = "true" %>
다중스레드에 의한 동시접근을 차단한다
<%@ page info = "페이지설명" %>
페이지전체에 대한 주석의 역할
<%@ page errorPage = "errorpage.jsp" %>
예외가 발생했을 때 에러페이지를 지정해 에러페이지에서 예외처리함
<%@ page contentType = "text/html" %>
JSP페이지가 전송할 응답의 MINE형식 지정 대분류/소분류 순으로 명시한다
<%@ page isErrorPage = "false" %>
현재 페이지가 다른 페이지에서 발생한 예외처리할 페이지 일때 지정한다
<%@ page pageEncoding = "euc-kr" %>
JSP페이지 문자셋 인코딩방식을 지정
파일 업로드
</form>
enctype 속성을 multipart/form-data 로 지정하지 않으면 파일객체가 아닌 파일이름 이 문자열형태로 전송된다.
예제 / 단일 파일 업로드
<form action="./partUplaodPro1" method="post" enctype="multipart/form-data">
<label for ="writer">작성자</label>
<input type=text name="writer" id="writer"><br>
<label for ="partFile1">업로드 파일</label>
<input type="file" name="partFile1" id="partFile1">
<input type="submit" value="업로드">
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
@WebServlet("/partUplaodPro1")
@MultipartConfig(
fileSizeThreshold=0 ,
location = "d:/upload"
)
public class partUploadPro1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String writer = request.getParameter("writer");
System.out.println(writer);
Part part = request.getPart("partFile1");
String contentDisposition = part.getHeader("content-disposition");
String contentType = part.getHeader("content-type");
System.out.println(part);
if(contentType.equals("image/gif")
|| contentType.equals("image/jpeg")
|| contentType.equals("image/png")){
System.out.println(contentDisposition);
int dotPosition = contentDisposition.lastIndexOf(".");
String temp = contentDisposition.substring(dotPosition,contentDisposition.length()-1);
UUID uuid = UUID.randomUUID();
String fileName = uuid.toString()+temp;
part.write(fileName);
File srcFile = new File("d:\\upload\\"+fileName);
File destFile = new File("d:\\upload\\_"+fileName);
BufferedImage srcbi = ImageIO.read(srcFile);
BufferedImage destbi = new BufferedImage(50, 50, BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g = destbi.createGraphics();
g.drawImage(srcbi, 0, 0, 50, 50, null);
ImageIO.write(destbi, temp.substring(1), destFile);
}
else{
response.sendRedirect("./partUploadForm1.jsp");
}
}
}
코드설명 /
@MultipartConfig 는 서블릿에서 multipart/form-data 형태로 전송된 데이터를 처리할 수 있게 지정한다.
파일이 최종 저장될 경로는 d:/upload 이고
업로드된 파일이 0바이트보다 커지면 임시 디렉토리에 저장된다.
파일이 gif,jpeg,png형식이 아닐경우 partUploadForm1.jsp로 돌아가고 맞을경우엔 흰화면